【问题标题】:Using defaults values for scoped route in Rails 4 always overrides default_url_options在 Rails 4 中使用范围路由的默认值总是覆盖 default_url_options
【发布时间】:2015-04-22 07:47:22
【问题描述】:

我正在尝试在我现有应用的网址中实现一个可选“区域”参数:

现有: /博客

新: /se/博客 要么 /zh/博客

这条路线应该是可选的(它只会用作过滤器,没有区域意味着全球),并且参数值应该是'ww'(全球)或nil(或其他,只要我知道没有提供)。

我想出的路线是这样的:

scope "(:region)", region: /en|se|dk|no|ww/, defaults: {region: 'ww'} 

我在 ApplicationController 中使用 default_url_options 将 :region 参数设置为与 param[:region] 相同,以便在存在时将其保留并应添加到页面上的所有 url。

def default_url_options(options={})
  { region: params[:region] }
end

问题是,当我使用 url /se/blogs 时,参数被正确设置为“se”,但它不会自动添加到页面上的任何 url。如果我删除范围路由的默认选项,它会起作用并预先添加参数“se”,但是由于没有默认值,许多 url 失败并显示“ActionController::UrlGenerationError: No route matches”,因为在 url helper 中,对象由于没有默认值,因此正在取区域值。

关于如何解决这个问题的任何想法?它可能与这个(仍未解决的)问题有关吗? https://github.com/rails/rails/issues/12178

【问题讨论】:

    标签: ruby-on-rails routes scope


    【解决方案1】:

    以这种方式设置默认区域似乎不起作用;但是,根据指南,它应该:

    http://guides.rubyonrails.org/routing.html#defining-defaults

    如果nil 是可接受的值,为什么不放弃默认值?

    config/routes.rb

    scope "(:region)", region: /en|se|dk|no|ww/ do
      resources :blogs
    end
    

    作为一种解决方法,您可以像这样设置默认区域:

    app/controllers/application_controller.rb

    def default_url_options(options={})
      { region: params[:region] || "ww" }
    end
    

    更新:

    没有默认区域:

    config/routes.rb

    scope "(:region)", region: /en|se|dk|no/ do
      resources :blogs do
        resources :posts
      end
    end
    

    app/controllers/application_controller.rb

    def default_url_options(options={})
      { region: params[:region] }
    end
    

    在你看来:

    <% @blog.posts.each do |post|
      <%= link_to post.title, blog_post_path(@blog, post) %>
    <% end %>
    

    未指定区域时的 URL:

    /blogs/1/posts/1
    

    指定en 区域时的URL:

    /en/blogs/1/posts/1
    

    更新 #2:

    好的,我能够重现您失败的测试。这是由 Rails 错误引起的,与您在问题中提到的相同。您可以在此处阅读有关此问题和一些解决方法的更多信息:

    https://github.com/rspec/rspec-rails/issues/255

    为了让您的测试通过,一种方法是使用before(:all) 块初始化default_url_options 中的region 选项。尝试将以下内容添加到您的 RSpec 配置中:

    spec/rails_helper.rb

    RSpec.configure do |config|
      config.before(:each) do
        default_url_options[:region] = nil
      end
    end
    

    您可能希望将该块限制为 featurecontroller 组类型。

    希望对您有所帮助。

    【讨论】:

    • 谢谢乔丹的回答!不向区域提供默认值的问题似乎是我当前的路由,例如 blog_post_path(@blog, @post) 将 @blog 放在区域参数中并且基本上缺少一个参数(一个被咀嚼:地区似乎)。不知道是否有办法解决这个问题,但即便如此,我也不想在路由中显示“ww”,只要在请求时隐式地将它放在参数中,如果没有提供重定向或类似的东西,如果提供一个,它应该按预期覆盖默认值。
    • 我也认为根据指南这应该是可能的。问题是如果这不能以任何其他方式实现,我会提交错误报告吗?我开始查看 Rails 代码以进行某种修复,但我对代码库的经验并不丰富,因此不会冒险破坏其他东西。
    • 我似乎无法重现您的问题。我已经更新了我的答案,展示了如何避免使用默认区域。 params[:region] 中的值如果不显示在您的路线中,您将无法获得该值。为什么需要“ww”?
    • 如果您觉得这是一个错误,您可以在github.com/rails/rails/issues 上打开一个新问题。在这种情况下,这可能是获得反馈的最佳方式。
    • 我可能会这样做,但您在此处的编辑似乎可以解决问题,这正是我想要的。我首先有这个解决方案,它看起来很好,但现在大量的测试因我原来的帖子中的错误而失败。也许 rspec 是这里的真正问题。叹息。
    【解决方案2】:

    我希望保留您现有的路线/blogs,只需添加一个名为region 或其他名称的可选参数。

    所以网址应该是/blogs?region=se/blogs?region=en

    然后在你的controller中,你只需要根据params[:region]应用不同的代码

    更简单、更稳定的 url 结构。

    【讨论】:

    • 抱歉,必须是上述 URL 的第一部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2011-07-19
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多