在路由资源中为Rails更改:id参数的名称

Aut*_*act 101 ruby ruby-on-rails ruby-on-rails-3

我环顾四周如何改变动态params插槽,并发现这篇文章确实完成了.该帖子是http://robots.thoughtbot.com/post/159809070/rails-patch-change-the-name-of-the-id-parameter-in

基本上它的作用是,如果以下是路线:

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end
Run Code Online (Sandbox Code Playgroud)

这些路由创建以下路径:

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title
Run Code Online (Sandbox Code Playgroud)

一种解决方案是覆盖def to_param模型中的方法,但我希望这不触及模型本身.

但是自从它为Rails 2.x以来,我怎样才能为Rails 3实现相同的功能呢?

更新

这个程序是使用Mongoid.不是AR.所以,友好的宝石不能用于afaik.

jos*_*rth 187

Rails 4和5

在Rails 4中,:param添加了选项,这似乎完全符合您的要求.与Rails 4代码相比,您可以查看Rails 3 代码.

细节

您可以在routes.rb文件中轻松实现此功能:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...
Run Code Online (Sandbox Code Playgroud)

自Rails 4发布以来,Rails指南中记录了此功能.

Rails 3

不幸的是,在Rails 3中,删除了:key选项resources,因此您无法再通过传递额外选项轻松更改以这种方式创建的路由的名称.

细节

我假设你已经以某种方式让应用程序在过去的一年中按照你想要的方式运行,但是我将采用一种方法来获得你在Rails 3中描述的效果routes.rb.它只涉及比to_param方法更多的工作.您还可以定义路由自定义参数使用定义scopematch(或它的表兄弟get,put,post,和delete).您只需在匹配器中写入所需的参数名称:

get 'clients/:client_name', :to => 'clients#show', :as => client

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end
Run Code Online (Sandbox Code Playgroud)

您必须手动添加resources自动为您创建的所有路线,但它可以实现您所需的目标.您还可以有效地使用:controller选项scope和其他scope块来取消一些重复.


编辑(2014年5月8日):更明显的答案包含Rails 3和4的信息.更新代码的链接以转到确切的行号和提交,以便它们应该工作更长的时间.

编辑(2014年11月16日): Rails 4现在应该位于顶部并且包含相关信息,因为它已经是Rails的当前版本已经有一段时间了.

编辑(2016年8月9日):反映该解决方案仍然适用于Rails 5,并更新过时的链接.

  • 仅供参考,如果您使用嵌套资源,父资源的参数将是`post_slug`,这可能会令人困惑. (8认同)
  • 这真的很好但是如果我不想要嵌套资源的post_post_id的父id的参数名,我该怎么办? (4认同)

bob*_*j87 44

在Rails 4中,传递param选项来改变:id params.例如, resources :photos, param: :photo_name将生成/ photos /:photo_name


Moh*_*ain 1

如果我理解正确的话,你想要的就是在你的网址中使用client_name代替,对吗?id

您可以通过重写to_param模型中的方法来做到这一点。您可以在这里获取更多信息。