4

我的用户模型具有通常的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)
...

执行此操作(或类似方法)的最佳方法是什么?

4

4 回答 4

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///方法editupdatedestroy添加了一个额外的by_login参数(等于true):这样,这些UserController方法可以判断该id参数是代表登录名还是 id。

它可以完成工作,但我希望有更好的方法。

于 2009-03-03T01:42:36.863 回答
1

只需检查传递给控制器​​方法的 ID 是否为整数。

if params[:id].is_a?(Integer)
    @user = User.find params[:id]
else
    @user = User.find_by_login params[:id]

无需添加特殊路线。

于 2009-03-03T02:31:35.403 回答
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 哈希来测试这一点。

(我本来只是发表评论,但我还没有足够的经验来做这件事;)

于 2009-03-03T02:47:49.827 回答
0

不完全确定您在这里做什么,但这可能会有所帮助。

您可以通过添加:member 或 :collection选项来定义 rails 提供的自动 RESTful 路由之外的操作。

map.resources :users, :member => { :login => [:post, :get] }

这将生成如下所示的路由:

/users/:id (GET)
...
/users/:id/login (GET)
/users/:id/login (POST)

您可以做的另一件事是使用登录作为您查找的属性(假设它是唯一的)。查看 Ryan Bates的截屏视频。在您的控制器中,您将拥有:

def show
@user = User.find_by_login(params[:id])
...
end

他还有另一个截屏视频可以帮助你。第二个谈论自定义命名路线。

于 2009-03-03T01:32:48.527 回答