代码之家  ›  专栏  ›  技术社区  ›  MiniQuark

如何在Rails中为具有多个关键字段的资源定义RESTful路由?

  •  4
  • MiniQuark  · 技术社区  · 17 年前

    我的用户模型 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 回复  |  直到 17 年前
        1
  •  1
  •   MiniQuark    17 年前

    到目前为止,我能想到的最好的办法是:

    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 ):这边 用户控制器 方法可以判断 id

    它能完成任务,但我希望有更好的方法。

        2
  •  1
  •   paxdiablo    17 年前

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

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

        3
  •  1
  •   vrish88    17 年前

    事实上凯尔·布恩有正确的想法。但有点不对劲。当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调试gem查看params散列来测试这一点。

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

        4
  •  0
  •   vrish88    17 年前

    不太清楚你在这里做什么,但这可能有帮助。

    您可以通过添加 :member or :collection 选择。

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

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

    另一件事,您可以使用登录名作为您查找的属性(假设它是唯一的)。看看瑞安·贝茨 screencast 在上面。在控制器中,您将拥有:

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

    他还有一个 screencast

    推荐文章