Rails中的漂亮路径

时间:2011-01-19 07:31:45

标签: ruby-on-rails routing seo

我有一个类别模型,我使用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都有效吗?

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} }。