Rails 7.1 adds new option path_params for url_for helper method

Neenu Chacko

By Neenu Chacko

on November 7, 2023

This blog is part of our  Rails 7 series.

With Rails 7.1, the url_for helper now supports a new option called path_params.

Prior to Rails 7.1, if you had your routes configured to be scoped under say, user_id as shown below, you would have to explicitly specify the user_id in every single place where you want to generate a link for the scoped routes, such as when writing view files.

2Rails.application.routes.draw do
3  root "articles#index"
5  scope ":user_id" do
6    get "/articles", to: "articles#index"
7    get "/articles/:id", to: "articles#show"
8  end
10  get "/categories", to: "categories#index"
1<!-- app/views/articles/index.html.erb -->
3<a href="<%= articles_path(user_id: @current_user.id) %>"> Articles </a>

This could be solved by updating ApplicationController and overwriting the default_url_options method:

1# application_controller.rb
2class ApplicationController < ActionController::Base
3  def default_url_options
4    { user_id: "unique-id" }
5  end

The default_url_options method is used to overwrite and set default options for all the methods based on url_for. However, this meant that all routes, even those that did not belong to the user_id scope, would have the ?user_id=unique-id query param added to the end of them resulting in the following output:

1articles_path # => /unique-id/articles
2categories_path # => /categories?user_id=unique-id

Rails 7.1 fixes this issue with the addition of the path_params option. If you pass a hash of parameters to this key, those parameters will only be used for the named segments of the route. If they aren't used, they are discarded instead of being appended to the end of the route as query params.

With this change, we can implement the default_url_options method as follows:

1class ApplicationController < ActionController::Base
2  def default_url_options
3    { path_params: { user_id: "unique-id" } }
4  end

The url_for helper method will now give you the following output:

1articles_path # => /unique-id/articles
2articles_path(user_id: "test-id") # => /test-id/articles
3categories_path # => /categories
4categories_path(user_id: "test-id") # => /categories

The view file can now be written as:

1<a href="<%= articles_path %>"> Articles </a>

This is very useful in situations where you only want to add a required param that is part of the route's URL without introducing unnecessary query params for other routes.

Please check out this pull request for more details.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.