2

我在路由中使用了两个默认参数:

scope '(/:locale)(/:currency)', currency: /eur|usd/, locale: /de|en/, defaults: { currency: 'eur' } do ...

因为货币应该用于整个访问,所以我在 ApplicationController 中的 default_url_options 中添加了语言环境和货币:

def default_url_options options = {}
 { locale: I18n.locale, currency: params['currency'] }
end

当我生成 URL 时,即使用 url_for(),Rails 默认会忘记货币。只有当我手动添加它时它才有效。例如:

root_path(currency: params['currency'])

我希望默认情况下添加它(当然)。locale没有问题。Rails 正确地处理了这个问题。(也许是因为 globalize3 gem?)

感谢您的任何帮助!

4

1 回答 1

2

当您的路由被映射时,路​​由声明中的默认值存储在哈希中。当您调用路由助手foo_path时,这些默认值将作为选项哈希传递给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

现在,当我们收到一个散列时,它reverse_merge!带有url_options(声明您的默认覆盖的地方default_url_options!)。因为reverse_merge!它意味着 in 的值options优先于 inurl_options的值,所以currency无论您default_url_optionsApplicationController. 然后将这些默认值传递给一系列url_for方法等,并返回您的路径。

更重要的是,货币参数将从您返回的路径中完全删除,使用这些代码行

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

它确定您的path_options( 'eur') 中的默认值等于defaults选择它的位置(duhhh?),因此出于某种原因将其删除。

所以我们学到的是你的路由文件中的默认值总是优先于url_options.

因此,我的建议是defaults:从路由范围中删除键,然后您:currency的 URL 中将始终有一个参数,并且您可以在控制器中指定默认值。

于 2013-07-22T09:31:56.863 回答