Ruby-on-rails 更改 Rails 路由资源中 :id 参数的名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6592038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:32:23  来源:igfitidea点击:

Change the name of the :id parameter in Routing resources for Rails

ruby-on-railsrubyruby-on-rails-3

提问by Autodidact

I looked around on how to change the dynamic params slot and found this post that does the exact thing. The post is https://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

我环顾四周,了解如何更改动态 params 插槽,并发现这篇文章做了确切的事情。帖子是https://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

Basically what it does is, if following is the routes:

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

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end

These routes create the following paths:

这些路由创建以下路径:

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title

One solution is to override the def to_parammethod in the model, but I want this without touching the model itself.

一种解决方案是覆盖def to_param模型中的方法,但我希望在不触及模型本身的情况下进行此操作。

But since its for Rails 2.x, how can I achieve the same for Rails 3?

但是由于它适用于 Rails 2.x,我如何才能为 Rails 3 实现相同的目标?

Update

更新

This app is using Mongoid. Not AR. So, the gem friendly cannot be used afaik.

这个应用程序正在使用 Mongoid。不是 AR。因此,不能使用 gem 友好的 afaik。

回答by joshhepworth

Rails 4 & 5

导轨 4 和 5

In Rails 4, the :paramoption was added, which seems to do exactly what you're looking for. You can take a look at the Rails 3 codecompared to the Rails 4 code.

在 Rails 4 中,:param添加了该选项,它似乎完全符合您的要求。您可以将Rails 3 代码Rails 4 代码进行比较

Details

细节

You can easily implement this in your routes.rbfile:

您可以轻松地在您的routes.rb文件中实现这一点:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...

As of the release of Rails 4, this functionality is documented in the Rails Guides.

随着 Rails 4 的发布,这个功能被记录在 Rails Guides 中

Rails 3

导轨 3

Unfortunately, in Rails 3, the :keyoption for resourceswas removed, so you can no longer easily change the name for routes created in this way by just passing in an extra option.

不幸的是,在 Rails 3 中,:keyfor的选项resources被删除了,所以你不能再通过传入一个额外的选项来轻松更改以这种方式创建的路由的名称。

Details

细节

I assume you've already somehow gotten the application working the way you want in the past year, but I will go into a way to get the effect you describe in Rails 3 in routes.rb. It will just involve a bit more work than the to_parammethod. You can still define custom parameters in routes defined using scopeand match(or it's cousins get, put, post, and delete). You simply write in the parameter name you want in the matcher:

我假设您已经在过去一年中以某种方式让应用程序以您想要的方式工作,但是我将深入研究一种方法来获得您在routes.rb. 它只涉及比to_param方法更多的工作。您还可以定义路由自定义参数使用定义scopematch(或它的表兄弟getputpost,和delete)。您只需在匹配器中输入所需的参数名称:

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

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end

You would have to manually add all the routes that resourcesautomatically creates for you, but it would achieve what you're looking for. You could also effectively use the :controlleroption with scopeand additional scopeblocks to take out some of the repetition.

您必须手动添加resources自动为您创建的所有路由,但它会实现您的需求。您还可以有效地使用:controller带有scope附加scope块的选项来消除一些重复。



EDIT (May 8, 2014):Make it more obvious the answer contains information for both Rails 3 & 4. Update the links to the code to go to exact line numbers and commits so that they should work for a longer period of time.

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

EDIT (Nov 16, 2014):Rails 4 should be at the top now and include relevant information as it's been the current version of Rails for quite some time now.

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

EDIT (Aug 9, 2016):Reflect that the solution still works in Rails 5, and update outdated links.

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

回答by bobzsj87

in Rails 4, pass param option to change the :id params. For example resources :photos, param: :photo_namewill generate /photos/:photo_name

在 Rails 4 中,传递参数选项来更改 :id 参数。例如 resources :photos, param: :photo_name将生成 /photos/:photo_name

回答by Mohit Jain

If I understand you correctly, what you want is to have the client_nameinstead of idin your url, right?

如果我理解正确,您想要的是在您的网址中使用client_name而不是id,对吗?

You can do that by overriding the to_parammethod in your model. You can get more information here.

您可以通过覆盖to_param模型中的方法来做到这一点。您可以在此处获取更多信息。

回答by Frost

There's a gem for that, just like there's a gem for everything ;)

有一个宝石,就像所有东西都有宝石一样 ;)

I've been using FriendlyIdfor this kind of behaviour in rails 3.

我一直在使用FriendlyId来处理 Rails 3 中的这种行为。

It will require you to add some code to your model though, like this:

不过,它会要求您向模型添加一些代码,如下所示:

class Client < ActiveRecord::Base
  has_friendly_id :name
end

...and if your clients don't have URI compatible names, you might want to use a slug for that, which you can do with has_friendly_id :name, :use_slug => true. When using slugs you'll obviously need to persist them to the database as well though.

...如果您的客户端没有与 URI 兼容的名称,您可能需要为此使用 slug,您可以使用has_friendly_id :name, :use_slug => true. 使用 slug 时,您显然也需要将它们保存到数据库中。

And as already mentioned, you can still use the to_paramtrick with rails 3, as documented here. I find FriendlyId a bit more versatile though.

正如已经提到的,您仍然可以在to_paramrails 3 中使用该技巧,如此处所述。不过,我发现 FriendlyId 更通用一些。

回答by Dominik Goltermann

In Rails 3 you can rename the id keys by using a combination of namespaces and scopes like this (not very nice though):

在 Rails 3 中,您可以使用像这样的命名空间和范围的组合来重命名 id 键(虽然不是很好):

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end