【问题标题】:Rails 5 - nested routes - uninitialised constants for controllersRails 5 - 嵌套路由 - 控制器的未初始化常量
【发布时间】:2016-10-07 23:30:33
【问题描述】:

我正在尝试弄清楚如何在 Rails 5 中嵌套路由(以便将相关的控制器放在一起。

我的控制器文件树设置为:

 app/controllers/users

在该文件夹中,我有以下控制器:

identities_controller.rb
app_roles_controller.rb

每个控制器都保存为:

class Users::IdentitiesController < ApplicationController
class Users::AppRolesController < ApplicationController

我的路线文件有:

resources :app_roles,
    :controllers => {
      :app_roles => 'users/app_roles'
    }

  devise_for :users,
             :controllers => {
                :sessions => 'users/sessions',
                :registrations => "users/registrations",
                :omniauth_callbacks => 'users/omniauth_callbacks'
              }

  resources :identities, 
    :controllers => {
        :identities => 'users/identities'
    }

  resources :users

在我的视图文件夹中,所有文件都是顶级文件。我不清楚是否需要以与我的控制器相同的方式对它们进行分组。

当我保存所有这些并尝试导航到 http://localhost:3000/app_roles#index 时,我希望转到我的 app/views/app_roles/index。

相反,我收到一条错误消息:

app_roles
uninitialized constant AppRolesController

当我 rake 路线时,我得到:

rake routes | grep app_roles
                       app_roles GET      /app_roles(.:format)                    app_roles#index {:controllers=>{:app_roles=>"users/app_roles"}}
                                 POST     /app_roles(.:format)                    app_roles#create {:controllers=>{:app_roles=>"users/app_roles"}}
                    new_app_role GET      /app_roles/new(.:format)                app_roles#new {:controllers=>{:app_roles=>"users/app_roles"}}
                   edit_app_role GET      /app_roles/:id/edit(.:format)           app_roles#edit {:controllers=>{:app_roles=>"users/app_roles"}}
                        app_role GET      /app_roles/:id(.:format)                app_roles#show {:controllers=>{:app_roles=>"users/app_roles"}}
                                 PATCH    /app_roles/:id(.:format)                app_roles#update {:controllers=>{:app_roles=>"users/app_roles"}}
                                 PUT      /app_roles/:id(.:format)                app_roles#update {:controllers=>{:app_roles=>"users/app_roles"}}
                                 DELETE   /app_roles/:id(.:format)                app_roles#destroy {:controllers=>{:app_roles=>"users/app_roles"}}

对我来说,我认为这些路由表明 app_roles#index 应该通过 app/controllers/users/app_roles_controller.rb 中的控制器进入 app/views/app_roles/index.html.erb

我对身份资源有同样的问题。

猜测 我尝试将 app/views/app_roles 文件夹移动到嵌套在用户文件夹下(即 app/views/users),但是当我尝试转到 http://localhost:3000/app_roles#index 以检查它是否有效时,我得到了同样的错误。

我也尝试将路由文件修改为:

resources :app_roles,
        :resources => {
          :app_roles => 'users/app_roles'
        }

我的意思是,我将对 :controllers 的引用更改为 :resources。它不起作用 - 我得到了同样的错误。

谁能看出我做错了什么?

【问题讨论】:

  • 也许可以尝试将您的文件放在命名空间文件夹中,即app/controllers/users/&lt;my_controller&gt;.rb。
  • 他们在:app/controllers/users
  • 你也有app/controllers/user_controller 吗?它可以只包含class UsersController &lt; ApplicationController; end
  • 我愿意 - 我的 UsersController 是顶级的(不嵌套在 app/controllers/users 文件夹中)

标签: ruby-on-rails ruby routes nested-routes


【解决方案1】:

路由到命名空间控制器

要将资源路由到“命名空间”控制器,您可以使用module 选项:

resources :identities, module: :users

或scope module:,这在声明多个资源时很有用:

scope module: :users do
  resources :app_roles, module: :users
  resources :identities, module: :users
end

这比手动指定控制器要干净得多,这实际上仅在您覆盖 Devise 之类的库或控制器和路由名称不对齐时才完成。

这里的术语可能有些混乱。请记住,路由所做的唯一事情就是将传入请求与控制器匹配。它不会影响控制器的工作方式。

查找视图

对我来说,我认为这些路线表明 app_roles#index 应该去 app/views/app_roles/index.html.erb 通过控制器 app/controllers/users/app_roles_controller.rb

这不是它的工作原理。 Rails 根据控制器类的嵌套查找视图。因此,rails 将在views/users/indentities/ 中寻找Users::IdentitiesController 的视图。

如果您想打破惯例,您可以显式渲染视图或prepend/append the view paths。但是,在打破约定之前先了解它们,它们实际上非常聪明。

请注意,您的路由不会影响控制器查找视图的方式。这取决于模块嵌套——这就是对象的组成方式。并且与嵌套路由的概念完全无关。

“命名空间”和嵌套路由

您生成的路线不是嵌套的。例如,嵌套路由是:

POST /users/:user_id/identities

清楚地描述了意图。要为indentities 设置嵌套路由,您可以:

resources :users, shallow: true do
  scope module: :users do
    resources :identities
  end
end

shallow: true 生成不带users/:used_id/ 前缀的单个路由。

           Prefix Verb   URI Pattern                              Controller#Action
  user_identities GET    /users/:user_id/identities(.:format)     users/identities#index
                  POST   /users/:user_id/identities(.:format)     users/identities#create
new_user_identity GET    /users/:user_id/identities/new(.:format) users/identities#new
    edit_identity GET    /identities/:id/edit(.:format)           users/identities#edit
         identity GET    /identities/:id(.:format)                users/identities#show
                  PATCH  /identities/:id(.:format)                users/identities#update
                  PUT    /identities/:id(.:format)                users/identities#update
                  DELETE /identities/:id(.:format)                users/identities#destroy
            users GET    /users(.:format)                         users#index
                  POST   /users(.:format)                         users#create
         new_user GET    /users/new(.:format)                     users#new
        edit_user GET    /users/:id/edit(.:format)                users#edit
             user GET    /users/:id(.:format)                     users#show
                  PATCH  /users/:id(.:format)                     users#update
                  PUT    /users/:id(.:format)                     users#update
                  DELETE /users/:id(.:format)                     users#destroy

【讨论】:

  • 嗨,Max,非常感谢您的解释。当我进行浅嵌套时,是否意味着我应该将身份视图文件夹嵌套在用户视图文件夹中?我想这样做是为了在我的文件结构中保持整洁,但我并不直观地理解视图文件结构中关闭的浅层开关。
  • 路由不影响控制器如何查找视图。他们只是调用匹配的控制器#action
  • 视图查找仅由控制器类的声明方式决定。如果它被包装在一个模块中,那么 rails 将在查找中使用该模块。
  • 好的,但是当您说“封装在模块中”时,您的意思是我编写嵌套控制器的方式符合“模块封装”格式吗?我的嵌套控制器的开头行是:class Users::IdentitiesController
  • 非常感谢您的解释。我很难理解行话,我找不到好的、简单的 ruby​​ 文档英文翻译。
猜你喜欢
  • 2021-10-04
  • 2018-08-25
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
相关资源
最近更新 更多