我的用户模型具有通常的id
主键,但它也有唯一的login
,可用作标识符。因此,我想定义路由,以便可以通过id或登录访问用户。理想情况下,路线将是这样的:
/users/:id (GET) => show (:id)
/users/:id (PUT) => update (:id)
...
/users/login/:login (GET) => show (:login)
/users/login/:login (PUT) => update (:login)
...
这样做的最佳方法是什么(或类似的东西)?
答案 0 :(得分:1)
到目前为止,我能想到的最好的是:
map.resources :users
map.resources :users_by_login,
:controller => "User",
:only => [:show, :edit, :update, :destroy],
:requirements => {:by_login => true}
为用户创建了常用的RESTful路由,最重要的是,users_by_login
资源添加了以下路由(仅限于那些路径):
GET /users_by_login/:id/edit
GET /users_by_login/:id/edit.:format
GET /users_by_login/:id
GET /users_by_login/:id.:format
PUT /users_by_login/:id
PUT /users_by_login/:id.:format
DELETE /users_by_login/:id
DELETE /users_by_login/:id.:format
这些路线实际上也映射到UserController
(仅适用于show
/ edit
/ update
/ destroy
方法)。添加了额外的by_login
参数(等于true
):这样,UserController
方法可以判断id
参数是表示登录还是id。
它完成了这项工作,但我希望有更好的方法。
答案 1 :(得分:1)
只需检查传递给控制器方法的ID是否为整数。
if params[:id].is_a?(Integer)
@user = User.find params[:id]
else
@user = User.find_by_login params[:id]
无需添加特殊路线。
答案 2 :(得分:1)
实际上Kyle Boon在这里有正确的想法。但它有点偏。当params变量出现时,所有值都存储为字符串,因此他的示例每次都会返回false。你能做的是:
if params[:id].to_i.zero?
@user = User.find_by_login params[:id]
else
@user = User.find params[:id]
end
这样,如果:id是一个实际的字符串Ruby只是将它转换为0.你可以通过使用ruby-debug gem查看params hash来测试它。
(我刚刚评论过,但我没有足够的经验来做到这一点;)
答案 3 :(得分:0)
不完全确定你在这里做了什么,但这可能会有所帮助。
您可以通过添加:member or :collection选项来定义rails提供的自动RESTful路由之外的操作。
map.resources :users, :member => { :login => [:post, :get] }
这将生成如下所示的路线:
/users/:id (GET)
...
/users/:id/login (GET)
/users/:id/login (POST)
你可以做的另一件事就是使用login作为你查找的属性(假设它是唯一的)。查看Ryan Bates screencast。在您的控制器中,您将拥有:
def show
@user = User.find_by_login(params[:id])
...
end
他还有另一个screencast可以帮到你。第二个讨论自定义命名路由。