【问题标题】:Why do my Rails 2 routes have query strings?为什么我的 Rails 2 路由有查询字符串?
【发布时间】:2011-04-06 21:36:21
【问题描述】:

有时我需要通过 URL 向页面传递额外的参数。过去,我在路由文件中使用了几个通用占位符,我称之为“属”和“种”。这曾经可以工作,但现在它已经开始生成带有查询字符串的 URL。

Rails 版本是 2.3.8。

路由文件是:

ActionController::Routing::Routes.draw do |map|
  map.root :controller => 'main', :action => 'index'
  map.connect ':controller', :action => 'index'
  map.connect ':controller/:action'
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:genus/:id'
  map.connect ':controller/:action/:genus/:species/:id'
end

索引页面是:

<p>
<%= url_for :controller => 'main', :action => 'test', :genus => 42, :id => 1 %>
</p>

测试页面是

<p>
<%= params.inspect -%>
</p>

索引页显示 /main/test?genus=42&id=1,这是我预期的 /main/test/42/1

但是,如果我转到 /main/test/42/1,我会看到正确的参数:

{"controller"=>"main", "action"=>"test", "genus"=>"42", "id"=>"1"}

任何想法我做错了什么?

【问题讨论】:

    标签: ruby-on-rails configuration routing query-string


    【解决方案1】:

    你的路线是颠倒的;您首先需要更具体的路线,然后才是更通用的路线。 Rails 将采用它可以用来匹配给定参数集的第一个路由。

    ActionController::Routing::Routes.draw do |map|
      map.connect ':controller/:action/:genus/:species/:id'
      map.connect ':controller/:action/:genus/:id'
      map.connect ':controller/:action/:id'
      map.connect ':controller/:action'
      map.connect ':controller', :action => 'index'
      map.root :controller => 'main', :action => 'index'
    end
    

    也就是说,您可以非常轻松地为此使用命名路由。

    ActionController::Routing::Routes.draw do |map|
      map.with_options(:path_prefix => ":controller/:action") do |con|
        con.species ":genus/:species/:id"
        con.genus   ":genus/:id"
        con.connect ":id"
        con.connect ""
      end   
    end
    

    这将为您提供以下路线:

    species /:controller/:action/:genus/:species/:id
      genus /:controller/:action/:genus/:id
            /:controller/:action/:id
            /:controller/:action
    

    那么,你可以使用:

    <%=genus_path("main", "test", 42, 1) %>
    

    获得:

    "/main/test/42/1"
    

    【讨论】:

    • 谢谢,克里斯,但这实际上并没有帮助。颠倒顺序会产生更好看的 URL,但是当您导航到它们时,这些 URL 不会被正确解释。路径 "/main/test/42/1" 给出 {"controller"=>"main", "action"=>"test", "genus"=>"42", "species"=>"1"}但我们希望“1”匹配 :id 而不是 :species。即使缺少某些组件,Rails 似乎也在匹配第一条路线。使用命名路由将使 routes.rb 文件更整洁,但它不会对 URL 解释产生任何影响。问题依然存在...
    • 我想我需要一些额外的信息;如果您想要一条带有属/种/ID 的路线,则需要 3 条信息。我在最初的回复中犯了一个错误(我已经更正了),但我试图理解问题的本质——Rails 应该只在满足所有条件时匹配路由。上述路由中,species_path 取 5 个参数,genus_path 取 4 个,其他取 3/2。
    • 我同意。 Rails 应该只在满足所有条件时匹配路由,但似乎情况并非如此。路径“/main/test/42/1”有四个信息。但是当我导航到那条路径时,Rails 告诉我“species”=>“1”。这是错误的,因为 :species 只存在于包含五条信息的路径中。所以我的问题是这样的。使用未命名的更具体的第一组路由(来自您答案的第一个代码块),我不明白为什么 Rails 将 URL“/main/test/42/1”与第一行匹配。它应该只匹配第二行。
    【解决方案2】:

    这是一个相当愚蠢的解决方案,但这应该可行:

    ActionController::Routing::Routes.draw do |map|
      map.connect ':controller/:action/:genus/:species/:id', :genus => /\d+/,
        :species => /\d+/, :id => /\d+/
      map.connect ':controller/:action/:genus/:id', :genus => /\d+/, :id => /\d+/
      map.connect ':controller/:action/:id'
      map.connect ':controller/:action'
      map.connect ':controller', :action => 'index'
      map.root :controller => 'main', :action => 'index'
    end
    

    问题是在 Rails 2 中路由的所有组件都是可选的。幸运的是这在 Rails 3 中更好。我的猜测是路由的优先级在 2.3.5-2.3 版本左右发生了变化。 8.

    【讨论】:

    • 太棒了,它有效!我认为您对 2.3.8 版本的某些更改是正确的,因为我确信我在很久以前就使用过类似的东西。在我升级到 Rails 3 之前,提出具体要求将解决它。非常感谢。
    猜你喜欢
    • 2010-09-18
    • 2011-01-16
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    • 1970-01-01
    相关资源
    最近更新 更多