12

我喜欢 Rail 的map.resources生成的所有默认路线。但是,在某些情况下,我想在我的路线中使用非数字标识符。例如,如果有一个由用户及其文章组成的嵌套路由,则标准路由可以这样编写:

map.resources :users, :has_many => [:articles] # => e.g. '/users/:id/articles/:id'

但是,不使用 Rails 生成的默认数字标识符有很多优点/理由。有没有办法将默认的 :id 参数替换为我选择的另一个规范标识符,而不会导致为每个标准操作编写自定义路由?假设我想要以下格式的路线:

'/users/:login/articles/:id'

使用map.resources可以实现这种路线吗?

4

2 回答 2

13

从 Rails 2.3 开始,无法更改参数名称并仍然使用#resources提供的自动路由。

作为一种解决方法,您可以articles使用 a:path_prefix和进行映射:name_prefix

map.resources :articles, :path_prefix => "/users/:login",
                         :name_prefix => "user_"

:path_prefix影响 URL,并影响生成的:name_prefix命名路由,因此您最终会得到这些路由:

    user_articles GET    /users/:login/articles(.:format)          {:controller=>"articles", :action=>"index"}
                  POST   /users/:login/articles(.:format)          {:controller=>"articles", :action=>"create"}
 new_user_article GET    /users/:login/articles/new(.:format)      {:controller=>"articles", :action=>"new"}
edit_user_article GET    /users/:login/articles/:id/edit(.:format) {:controller=>"articles", :action=>"edit"}
     user_article GET    /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"show"}
                  PUT    /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"update"}
                  DELETE /users/:login/articles/:id(.:format)      {:controller=>"articles", :action=>"destroy"}

不过,作为一般经验法则,我会坚持使用 Rails 默认约定:user_id,以及您在问题中发布的路由。人们普遍理解,:id并不:user_id一定暗示“数字标识符”——它们暗示“资源标识符”,不管它可能是什么。通过坚持默认约定,任何在 Rails 中使用资源路由的人都更容易理解您的代码。

要为资源使用非数字标识符,只需#to_param在模型中重新定义。然后,确保在控制器中使用查找器,该查找器将通过此标识符(而不是数字 ID)查找,例如User#find_by_login!.

于 2009-05-03T00:05:30.800 回答
12

您可以通过覆盖模型中的 to_param 来更改在 URL 中使用 ID 的默认值。例如

class User < ActiveRecord::Base
  def to_param
    login
  end
end

user_articles_path(@user) => "/users/:login/articles"

您需要做的唯一其他更改是通过登录而不是通过控制器中的 ID 来查找用户。

于 2009-05-01T10:18:35.103 回答