Rails路由:name而不是:id url参数

我有一个名为’公司’的控制器,而不是每个公司的url用以下表示:id我想让url使用他们的:名称如: url/company/microsoft而不是url/company/3

在我的控制器中我假设我会

  def show @company = Company.find(params[:name]) end 

由于url中没有任何其他参数,我希望rails能理解:name引用了我公司模型中的:name列。 我认为这里的魔法会在路线上,但我在这一点上陷入困​​境。

params

最重要的是你正在寻找错误的解决方案 – params散列键是无关紧要的,你需要能够更有效地使用其中包含的数据。

您的路线将构建为:

 #config/routes.rb resources :controller #-> domain.com/controller/:id 

这意味着如果您请求此路由: domain.com/controller/your_resource params[:id]哈希值将是your_resource (如果它被称为params[:name]params[:id]则无关紧要)

friendly_id

你有几个答案推荐friendly_id的原因是因为这会覆盖ActiveRecordfind方法,允许你在查询中使用slug

 #app/models/model.rb Class Model < ActiveRecord::Base extend FriendlyId friendly_id :name, use: [:slugged, :finders] end 

这允许您这样做:

 #app/controllers/your_controller.rb def show @model = Model.find params[:id] #-> this can be the "name" of your record, or "id" end 

Rails 4.0+的答案很好:

 resources :companies, param: :name 

您可以选择only:使用only:except: list来指定路由

如果要构造URL,可以覆盖相关模型的ActiveRecord :: Base#to_param:

 class Video < ApplicationRecord def to_param identifier end # or alias_method :to_param, :identifier end video = Video.find_by(identifier: "Roman-Holiday") edit_videos_path(video) # => "/videos/Roman-Holiday" 

老实说,我只会覆盖模型中to_param 。 这将允许company_path帮助程序正常工作。

注意:我会为复杂的名称创建一个单独的slug列,但这只是我。 这是一个简单的案例。

 class Company < ActiveRecord::Base def to_param name end end 

然后更改我的路线param以便于阅读。

 # The param option may only be in Rails 4+, # if so just use params[:id] in the controller resources :companies, param: :name 

最后在我的控制器中,我需要以正确的方式查找它。

 class CompaniesController < ApplicationController def show # Rails 4.0+ @company = Company.find_by(name: params[:name]) # Rails < 4.0 @company = Company.find_by_name(params[:name]) end end 

我建议为此目的使用friendly_id。 请注意,friendly_id 4和5之间存在差异。在friendly_id 4中,您可以像这样使用

  @company = Company.find(params[:id]) 

但是,您将无法在friendly_id 5中执行此操作,您必须使用:

  @company = Company.friendly.find(params[:id]) 

如果您不想使用params [:id]但是params [:name],则必须覆盖routes.rb中的路由。 例如

  get '/companies/:name', to: "companies#show" 

希望这些信息对您有所帮助

实现这一点实际上没有任何魔力,您必须通过在您的模型上正确实现to_param (不推荐)或使用其中一个可用的gem来自己构建它 :

  • friendly_id
  • has_permalink

我使用friendly_id ,它很好地完成了工作。

Model.find(primary_key)
这里的默认参数是primary_key id。 如果你想使用其他列,你应该使用Model.find_by_xxx,所以它可以

 def show @company = Company.find_by_name(params[:name]) end