嵌套或不嵌套资源

时间:2012-12-02 18:49:41

标签: ruby-on-rails ruby-on-rails-3 rest routes

过去几天我一直在玩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?

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

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

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

1 个答案:

答案 0 :(得分:1)

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

resources :lists将创建所有其余的路线。

resources :users do
  resources :lists
end
然后

将创建所有嵌套路由和关联的帮助程序。我不会在这种情况下使用嵌套路由,因为你的控制器将是一个shitshow。

嵌套路由(假设用户/ 7 /列表)默认路由到ListsController#index,但您也有/列表将转到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

呃。

那么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

现在我们基本上可以通过说users_show,users_index等来调整控制器方法的范围。但那个@action变量是什么?我们需要抓住它。

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

我们只是覆盖内部Rails方法来捕获操作名称。这很有趣,但有点似乎我们做错了。

正确的方式(tm)

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

scope 'privates' do
  resources :lists
end

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

scope 'privates' do
  resources :users do  
    resources :lists
  end
end