就嵌套资源而言,我的应用程序对上下文变得非常敏感。
例如,假设我的应用程序是图书管理员应用程序,我可能有这样的路由:
resources :books
resources :libraries do
resources :books
end
我希望它是这样的,如果您访问 /books
,您会看到与您(登录用户)相关的书籍。无论是您已借出的书籍、您喜爱的书籍还是您拥有的其他书籍。
但是当您访问 /libraries/:id/books
时,您应该会看到与该图书馆相关的书籍。
现在,这在 Controller 中很容易做到:
def index
if params[:library_id]
@library = Library.find(params[:library_id])
@books = @library.books
else
@books = current_user.books
end
end
但是,这种模式在我的应用程序中重复了几次(想想如果我想将书籍嵌套在作者或出版商下!)我的 Controller 可能会变得非常复杂。如果我想对每个上下文有不同的看法,那就更难了。
所以,我想要两个书籍 Controller 。一个位于根命名空间,另一个命名空间位于库下。
没关系。我已经构建了 BooksController
和 Library::BooksController
。但是,我在设置合理的路线时遇到了问题。
我首先想到我可以只指定 namespace :
resources :books
resources :libraries do
namespace :library do
resources :books
end
end
但这破坏了现有的路线,看起来像 /libraries/:id/library/books
因此,我尝试将 path: false
传递给命名空间,这修复了路由,但使命名路由和多态路由变得非常麻烦。
我希望为了访问 /libraries/123/books
,我可以这样做:
link_to "See books", [@library, :books] # -or-
link_to "See books", library_books_path(@library)
但是,由于我们添加了命名空间,路由现在变得非常庞大:
link_to "See books", [@library, :library, :books] # -or-
link_to "See books", library_library_books_path(@library)
那么,是否有一种更传统的方法来构造对嵌套资源有意义的 Controller ?有更好的方法来构建我的路线吗?
更新
通过将 as: false
添加到命名空间声明中,我得到了预期的结果,如下所示:
resources :books
resources :libraries do
namespace :library, path: false, as: false do
resources :books
end
end
H-man 指出,您可以在每个资源上指定一个 Controller 。然而,这感觉不太好,因为大量路线的管理可能会失控。
所以这两种解决方案都可以工作,但是有没有更传统的方法来解决这个问题?
更新#2
我开始使用 ActionDispatch::Routing::Mapper::Scoping
中的 #defaults
,它允许您直接将参数发送到 #scope
没有一堆其他干扰逻辑。我更喜欢这个,因为我不是设置负数,而是设置正数配置:
resources :books
resources :libraries do
defaults module: :libraries
resources :books
end
end
但是,如果我遵循良好的惯例,问题仍然存在......这仍然感觉不是 100% 正确。
最佳答案
尝试使用作用域模块:
resources :books
scope module: :libraries do
resources :libraries do
resources :books
end
end
然后你应该有这些类型的帮助器可用于获取索引操作(例如):
books_path == [:books]
library_books_path(@library) == [@library, :books]
我对libraries
资源是否应该位于作用域模块下感到困惑,但大多数时候这样做是有意义的。假装您想稍后取出该 block 并将其放入 gem 中(即使这不是您的计划)。这有助于区分每个作用域模块中的内容。
关于ruby-on-rails - 如何构造 Controller 以匹配嵌套资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22078661/