ruby-on-rails - 如何构造 Controller 以匹配嵌套资源

标签 ruby-on-rails routes

就嵌套资源而言,我的应用程序对上下文变得非常敏感。

例如,假设我的应用程序是图书管理员应用程序,我可能有这样的路由:

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 。一个位于根命名空间,另一个命名空间位于库下。

没关系。我已经构建了 BooksControllerLibrary::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/

相关文章:

asp.net - 在 ASP.Net Web 应用程序中使用来自 Rails 应用程序的用户/身份验证信息

ruby-on-rails - 使用 Rails 哈希数组转义引号

asp.net-mvc - 如何配置 ASP.NET MVC 路由以隐藏 "home"页面上的 Controller 名称?

node.js - 使用 express.js 动态加载路由

ruby-on-rails - 如何在Rails应用程序中实现虚名URL?

ruby-on-rails - 我可以使用Rails API执行INSERT-SELECT操作吗?

ruby-on-rails - Tailwind CSS 响应类不适用于 Rails ViewComponent gem

javascript - 快速路线不再加载

node.js - 如何在 Express 应用程序上查找中间件的路径

ruby-on-rails - 更新属性而不改变 updated_at 字段