Define custom URL helpers that will be added to the application's routes. This allows you to override and/or replace the default behavior of routing helpers, e.g:
direct :homepage do
"https://rubyonrails.org"
end
direct :commentable do |model|
[ model, anchor: model.dom_id ]
end
direct :main do
{ controller: "pages", action: "index", subdomain: "www" }
end
The return value from the block passed to direct
must be a valid set of arguments for url_for
which will actually build the URL string. This can be one of the following:
-
A string, which is treated as a generated URL
-
A hash, e.g.
{ controller: "pages", action: "index" }
-
An array, which is passed to
polymorphic_url
-
An Active Model instance
-
An Active Model class
NOTE: Other URL helpers can be called in the block but be careful not to invoke your custom URL helper again otherwise it will result in a stack overflow error.
You can also specify default options that will be passed through to your URL helper definition, e.g:
direct :browse, page: 1, size: 10 do |options|
[ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
end
In this instance the params
object comes from the context in which the block is executed, e.g. generating a URL inside a controller action or a view. If the block is executed where there isn't a params
object such as this:
Rails.application.routes.url_helpers.browse_path
then it will raise a NameError
. Because of this you need to be aware of the context in which you will use your custom URL helper when defining it.
NOTE: The direct
method can't be used inside of a scope block such as namespace
or scope
and will raise an error if it detects that it is.
Define custom polymorphic mappings of models to URLs. This alters the behavior of polymorphic_url
and consequently the behavior of link_to
and form_for
when passed a model instance, e.g:
resource :basket
resolve "Basket" do
[:basket]
end
This will now generate “/basket” when a Basket
instance is passed to link_to
or form_for
instead of the standard “/baskets/:id”.
NOTE: This custom behavior only applies to simple polymorphic URLs where a single model instance is passed and not more complicated forms, e.g:
# config/routes.rb
resource :profile
namespace :admin do
resources :users
end
resolve("User") { [:profile] }
# app/views/application/_menu.html.erb
link_to "Profile", @current_user
link_to "Profile", [:admin, @current_user]
The first link_to
will generate “/profile” but the second will generate the standard polymorphic URL of “/admin/users/1”.
You can pass options to a polymorphic mapping - the arity for the block needs to be two as the instance is passed as the first argument, e.g:
resolve "Basket", anchor: "items" do |basket, options|
[:basket, options]
end
This generates the URL “/basket#items” because when the last item in an array passed to polymorphic_url
is a hash then it's treated as options to the URL helper that gets called.
NOTE: The resolve
method can't be used inside of a scope block such as namespace
or scope
and will raise an error if it detects that it is.
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2170 def resolve(*args, &block) unless @scope.root? raise RuntimeError, "The resolve method can't be used inside a routes scope block" end options = args.extract_options! args = args.flatten(1) args.each do |klass| @set.add_polymorphic_mapping(klass, options, &block) end end