可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a controller named 'companies' and rather than the urls for each company being denoted with an :id I'd like to have the url use their :name such as: url/company/microsoft
instead of url/company/3
.
In my controller I assumed I would have
def show
@company = Company.find(params[:name])
end
Since there won't be any other parameter in the url I was hoping rails would understand that :name referenced the :name column in my Company model. I assume the magic here would be in the route but am stuck at this point.
回答1:
params
The bottom line is you're looking at the wrong solution - the params
hash keys are rather irrelevant, you need to be able to use the data contained inside them more effectively.
Your routes will be constructed as:
#config/routes.rb
resources :controller #-> domain.com/controller/:id
This means if you request this route: domain.com/controller/your_resource
, the params[:id]
hash value will be your_resource
(doesn't matter if it's called params[:name]
or params[:id]
)
--
friendly_id
The reason you have several answers recommending friendly_id
is because this overrides the find
method of ActiveRecord
, allowing you to use a slug
in your query:
#app/models/model.rb
Class Model < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
This allows you to do this:
#app/controllers/your_controller.rb
def show
@model = Model.find params[:id] #-> this can be the "name" of your record, or "id"
end
回答2:
Good answer with Rails 4.0+ :
resources :companies, param: :name
optionally you can use only:
or except:
list to specify routes
and if you want to construct a URL, you can override ActiveRecord::Base#to_param of a related model:
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"
回答3:
Honestly, I would just overwrite the to_param
in the Model. This will allow company_path
helpers to work correctly.
Note: I would create a separate slug column for complex name, but that's just me. This is the simple case.
class Company < ActiveRecord::Base
def to_param
name
end
end
Then change my routes param
for readability.
# The param option may only be in Rails 4+,
# if so just use params[:id] in the controller
resources :companies, param: :name
Finally in my Controller I need to look it up the right way.
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
回答4:
I recommend using the friendly_id for this purpose.
Please be noted that there are differences between friendly_id 4 and 5. In friendly_id 4, you can use like this
@company = Company.find(params[:id])
However, you won't be able to do that in friendly_id 5, you have to use:
@company = Company.friendly.find(params[:id])
In case that you don't want to use the params[:id] but params[:name], you have to override the route in routes.rb. For example
get '/companies/:name', to: "companies#show"
Hope these info would be helpful to you
回答5:
There's actually no magic to implement this, you have to either build it yourself by correctly implementing to_param
at your model (not recommended) or using one of the gems available for this like:
- friendly_id
- has_permalink
I use friendly_id
and it does the job nicely.
回答6:
Model.find(primary_key)
The default parameter here is primary_key id.
If you want to use other columns, you should use Model.find_by_xxx
so here it could be
def show
@company = Company.find_by_name(params[:name])
end