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

dsc*_*her 30 routes ruby-on-rails

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

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

 def show
   @company = Company.find(params[:name])
 end
Run Code Online (Sandbox Code Playgroud)

由于url中没有任何其他参数,我希望rails能理解:name引用了我公司模型中的:name列.我认为这里的魔法将在路线中,但我仍然坚持这一点.

Mat*_*rix 72

Rails 4.0+的答案很好:

resources :companies, param: :name
Run Code Online (Sandbox Code Playgroud)

您可以选择使用only:except:列表来指定路线

如果要构造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"
Run Code Online (Sandbox Code Playgroud)

  • 优雅的解决方 (4认同)
  • 如果您希望在此资源中只为一个成员路由使用不同的参数,则可以再次将资源定义为:resources:companies,only:[],param :: name do; 会员; 得到:页面; 结束; 结束; (4认同)
  • @Jarred你也可以使用"除了"黑名单 (3认同)

Ric*_*eck 12

params

最重要的是你正在寻找错误的解决方案 - params哈希键相当无关紧要,你需要能够更有效地使用其中包含的数据.

您的路线将构建为:

#config/routes.rb
resources :controller #-> domain.com/controller/:id
Run Code Online (Sandbox Code Playgroud)

这意味着如果你申请这条航线:domain.com/controller/your_resource中,params[:id]哈希值将是your_resource(不一样,如果它被称为关系params[:name]params[:id])

-

friendly_id

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

#app/models/model.rb
Class Model < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: [:slugged, :finders]
end
Run Code Online (Sandbox Code Playgroud)

这允许您这样做:

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

  • 没有`find` - 如果你想这样做,你需要使用`find_by name:params [:id]`; 但这意味着你只能使用`name`属性 (3认同)

Azo*_*olo 11

老实说,我只想覆盖to_param模式.这将使company_path助手正常工作.

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

class Company < ActiveRecord::Base
  def to_param
    name
  end
end
Run Code Online (Sandbox Code Playgroud)

然后改变我的路线param以便于阅读.

# The param option may only be in Rails 4+,
# if so just use params[:id] in the controller
resources :companies, param: :name
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)


The*_*Log 7

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

 @company = Company.find(params[:id])
Run Code Online (Sandbox Code Playgroud)

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

 @company = Company.friendly.find(params[:id])
Run Code Online (Sandbox Code Playgroud)

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

 get '/companies/:name', to: "companies#show"
Run Code Online (Sandbox Code Playgroud)

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


Mau*_*res 5

实现这一点实际上没有什么神奇之处,你必须通过在你的模型上正确实现(不推荐)或者使用其中一个可用的宝石来自己构建它to_param:

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