嵌套或不嵌套资源

cab*_*ret 5 rest routes ruby-on-rails ruby-on-rails-3

在过去的几天里,我一直在玩Rails.

我不确定是否应该嵌套资源,以及如何确定它.

让我假装我有一个应用程序,用户可以注册并制作待办事项列表.他们可以选择将这些列表公开或私有.

我遇到麻烦的地方是我是否应该在用户资源下嵌套列表:

如果我这样做,我最终得到的结果如下:

/users/:id/lists /users/:id/lists/:list_id

但是,如果我想说,请查看所有公开名单/lists?这会干扰路线的宁静,不是吗?

我无法嵌套列表并为用户和列表分别设置路径,但至少在我的脑海中再次遇到麻烦.

/users/:id # some profile page /lists # should this link to all lists or all the current user's lists?

但是,如果我想显示特定用户的列表,我不知道我的路线是什么.

有没有办法以某种方式结合这个?将列表嵌套在用户资源下,但仍然有/listslists_path?或者那只是一个自定义的命名路线?

我对Rails中比我更熟练的人如何解决这个问题感兴趣.

Chr*_*ris 1

您可以同时拥有嵌套列表和非嵌套列表。

resources :lists将创建所有安静的路线。

resources :users do
  resources :lists
end
Run Code Online (Sandbox Code Playgroud)

然后将创建所有嵌套路由和关联的助手。在这种情况下我不会使用嵌套路由,因为你的控制器将是一个狗屎秀。

嵌套路由(假设 users/7/lists)默认路由到ListsController#index,但您也有 /lists 将会路由到ListsController#index。因此,您可以向控制器添加一些逻辑:

ListsController < ApplicationController
  def index
    if params[:user_id].present?
      # I'm in a user_list
    else
      # I'm in a public list
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

啊。

好吧,before_filter 怎么样?

ListsController < ApplicationController
  before_filter :unjankify_nested_routes

  private      

  def unjankify_nested_routes
    if params[:user_id].present?
      # I'm in a user_list
      render "users_#{@action}"
    else
      # I'm in a public list
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在我们基本上可以通过 users_show、users_index 等来确定控制器方法的范围。但是 @action 变量是什么?我们需要抓住这一点。

class ApplicationController     
  def process_action(name, *args)
    @action_name = name
    super rescue false #no super in tests
  end
end
Run Code Online (Sandbox Code Playgroud)

我们刚刚重写了 Rails 内部方法来捕获操作名称。这很有趣,但我们似乎做错了什么。

正确的方法(tm)

没有“正确的方法”,但范围是一个不错的选择

scope 'privates' do
  resources :lists
end
Run Code Online (Sandbox Code Playgroud)

现在我们可以有一个Privates::ListsControllerin app/controllers/privates/lists_controller. 您可以在查询参数中添加 user_id ,或在范围下嵌套路由:

scope 'privates' do
  resources :users do  
    resources :lists
  end
end
Run Code Online (Sandbox Code Playgroud)