When your routes are mapped, the defaults from the route declarations are stored in a hash. When you call your route helper foo_path
, these defaults are passed as a hash of options to ActionDispatch::Routing.url_for
:
def url_for(options = nil)
case options
when nil
_routes.url_for(url_options.symbolize_keys)
when Hash
_routes.url_for(options.symbolize_keys.reverse_merge!(url_options))
when String
options
else
polymorphic_url(options)
end
end
Now, as we're receiving a hash, it reverse_merge!
s with url_options
(where your default from overriding the default_url_options
is declared!). As it's a reverse_merge!
it means that the values in options
take precedence over that in url_options
, so the default value for currency
will always be what it is set to in the routes file, regardless of what you put in your default_url_options
in your ApplicationController
. These defaults then get passed onto a chain of url_for
methods and the like, and your path is returned.
What's more, the currency parameter gets removed from your returned path completetely, with these lines of code:
def format path_options
path_options.delete_if do |key, value|
value.to_s == defaults[key].to_s && !required_parts.include?(key)
end
Visitors::Formatter.new(path_options).accept(path.spec)
end
It determines that the default value in your path_options
('eur'
) is equivalent to the defaults
from where it was selected (duhhh?), so it removes it for some reason.
So what we've learnt is that the defaults in your routes file will always take precedence over url_options
.
My advice therefore, would be to remove the defaults:
key from your routing scope, and then you will always have a :currency
parameter in your URL, and you can specify the default in the controller.