如何在Rails的map.resources()中重命名默认标识符参数"id"?

12

我喜欢Rails的map.resources生成的所有默认路由。但是,有些情况下我想在我的路由中使用非数字标识符。例如,如果我有一个嵌套路由包含用户和他们的文章,一个标准的路由可能被写成这样:

map.resources :users, :has_many => [:articles] # => e.g. '/users/:id/articles/:id'

然而,有许多优点/理由不使用Rails生成的默认数字标识符。是否有一种方法可以将默认的:id参数替换为我选择的另一个规范标识符,而不必编写每个标准操作的自定义路由?比如说,如果我想要以下格式的路由:

'/users/:login/articles/:id'

使用 map.resources 能否实现这种类型的路由?


我之所以问这个问题,主要是因为Merb的路由系统具备这种能力。 - newtonapple
2个回答

13

从 Rails 2.3 开始,无法更改参数名称并仍然使用 #resources 提供的自动路由。

作为解决方法,您可以使用 :path_prefix:name_prefix 映射 articles:

map.resources :articles, :path_prefix => "/users/:login",
                         :name_prefix => "user_"

:path_prefix 影响 URL,而 :name_prefix 影响生成的命名路由,因此您将得到以下这些路由:

    user_articles GET    /users/:login/articles(.:format)          {:controller=>"articles", :action=>"index"}
                  POST   /users/:login/articles(.:format)          {:controller=>"articles", :action=>"create"}
 new_user_article GET    /users/:login/articles/new(.:format)      {:controller=>"articles", :action=>"new"}
edit_user_article GET    /users/:login/articles/:id/edit(.:format) {:controller=>"articles", :action=>"edit"}
     user_article GET    /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"show"}
                  PUT    /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"update"}
                  DELETE /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"destroy"}

总的来说,在你提供的路由中,我建议遵循Rails的默认规则,使用:user_id。通常人们理解:id:user_id并不一定意味着“数字标识符”,而是指“资源标识符”,具体指哪个资源并不重要。如果遵循默认规则,任何熟悉Rails资源路由的人都能更容易地理解你的代码。

如果想要为资源使用非数字标识符,只需在模型中重新定义#to_param。然后,在控制器中使用一个按此标识符查找的查找器(而不是数字ID),如User#find_by_login!


12

通过在你的模型中重写to_param方法,你可以更改在URL中使用ID的默认行为。例如:

class User < ActiveRecord::Base
  def to_param
    login
  end
end

user_articles_path(@user) => "/users/:login/articles"

你需要做的另一个修改是在你的控制器中通过登录名而不是ID查找用户。


to_param用于路由生成的尝试。但是在识别时,它仍然将其作为:user_id传递。是否有重命名为:login的方法? - newtonapple
这是一篇写得很好的回答,但与此问题无关 :/ 这里的问题是关于路由器以及如何重命名 :id 路由参数。 - Matchu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接