我有一个类别模型,我使用resources :categories
的默认脚手架来路由它。我想知道是否有办法将路径从/category/:id
更改为/category/:name
。我补充说:
match "/categories/:name" => "categories#show"
在routes.rb
中的资源行上方并更改了控制器中的show
操作:
@category = Category.find_by_name(params[:name])
它有效,但link_to some_category
之类的“魔术路径”仍然使用:id
格式。
有办法做到这一点吗?如果这是一个坏主意(由于rails内部工作的一些可能方式),还有另一种方法可以实现吗?例如,/categories/music
和/categories/3
都有效吗?
答案 0 :(得分:5)
Rails有一个名为to_param
的漂亮模型实例方法,它是路径使用的方法。默认为id
,但您可以覆盖它并生成类似:
class Category < ActiveRecord::Base
def to_param
name
end
end
cat = Category.find_by_name('music')
category_path(cat) # => "/categories/music"
有关详细信息,请查看Rails documentation for to_param。
编辑:
对于不适合网址的类别名称,您有多种选择。正如你所说,一个是gsub
带有连字符的空格,反之亦然,当找到记录时。但是,更安全的选择是在类别表上创建名为name_param
(或类似)的另一列。然后,您可以使用它代替名称,以及所有路径和URL相关的业务。使用parameterize
变形器创建URL安全字符串。我就是这样做的:
class Category < ActiveRecord::Base
after_save :create_name_param
def to_param
name_param
end
private
def create_name_param
self.name_param = name.parameterize
end
end
# Hypothetical
cat = Category.create(:name => 'My. Kewl. Category!!!')
category_path(cat) # => "/categories/my-kewl-category"
# Controller
@category = Category.find_by_name_param(param[:id]) # <Category id: 123, name: 'My. Kewl. Category!!!'>
答案 1 :(得分:2)
如果您不想破坏依赖于型号ID的现有代码,您可以像这样定义您的to_param:
def to_param
"#{id}-#{name}"
end
所以您的网址将是:http://path/1-some-model,您仍然可以使用Model.find(params [:id])加载模型,因为:
“123-你好世界” .to_i =&GT; 123
答案 2 :(得分:1)
虽然可能超出了您的需要,但您可能还需要查看“人类可读网址”支持,例如friendly_id或其中一个支持(例如,如果您需要unicode支持等),这些支持将被描述为{{3} }。