Generating URLs within Rails applications can involve specifying parameters for various routes. Prior to Rails 7.1, dealing with scoped routes presented a minor challenge.
Imagine your routes are configured with a :client_id
scope, like this:
1
2
3
4
5
# config/routes.rb
scope ":client_id" do
get "/orders", to: "orders#index"
get "/orders/:id", to: "orders#show"
end
Previously, you needed to explicitly include the client_id
in every instance where you generated a link for these scoped routes, even within your views. This could be cumbersome and error-prone.
One solution involved overriding the default_url_options
method in your ApplicationController
:
1
2
3
4
5
6
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def default_url_options
{ client_id: "1234" }
end
end
While this ensured client_id
was included in all URLs, it had a downside. All routes, including those outside the client_id
scope, received the ?client_id=1234
query parameter:
1
2
orders_path # => /1234/orders
products_path # => /products?client_id=1234
This wasn’t ideal, as it added clutter and potentially unnecessary information to URLs.
Rails 7.1 introduces path_params
to the rescue! This new option within the url_for
helper offers granular control over URL generation. You can pass a hash of parameters, and only those that align with named segments in the route will be used, while others are discarded.
With path_params
, the default_url_options
implementation becomes cleaner:
1
2
3
4
5
class ApplicationController < ActionController::Base
def default_url_options
{ path_params: { client_id: "1234" } }
end
end
Now, the url_for
helper behaves as follows:
1
2
3
4
orders_path # => /1234/orders
orders_path(client_id: "5678") # => /5678/orders
products_path # => /products
products_path(client_id: "5678") # => /products?client_id=5678
The view file can now simply reference the path without explicitly passing client_id
:
1
2
# app/views/orders/index.html.erb
<a href="<%= orders_path %>">Orders</a>
This simplifies your code and avoids unnecessary query parameters.