Rails 模块范围

Rails module scope

给定以下控制器结构:

# application_controller.rb
class ApplicationController < ActiveController::Base; end

# pages_controller.rb
class PagesController < ApplicationController; end

# admin/application_controller.rb
module Admin
  class ApplicationController < ::ApplicationController; end
end

# admin/pages_controller.rb
module Admin
  class PagesController < ApplicationController; end
end

人们会期望 Admin::PagesController 继承自 Admin::ApplicationController,它的确如此。但我注意到有时它继承自 ::ApplicationController.

所以我决定不冒险,并更改了 /admin 中所有控制器的声明,以专门针对 Admin::ApplicationController

# admin/pages_controller.rb
module Admin
  class PagesController < Admin::ApplicationController; end
end

好的,但据我所知,它首先是正确的。为什么 Rails 有时会从错误的控制器继承?

Admin::PagesController 有时 继承自 ApplicationController 而不是 Admin::ApplicationController 尽管两者都在同一个 module Admin

这里的问题是 rails' 开发模式代码加载:通常,当您尝试使用常量(例如 subclass 从中执行某些操作)时会加载代码,而该常量不会'不存在。这导致 const_missing 被调用并且 rails 使用它来尝试加载 class(有关详细说明,请参阅 the guide)。

如果 ApplicationController 和 Admin::ApplicationController 都不存在,那么当您访问您的管理页面控制器时 ruby 将点击 const_missing 并尝试加载 admin/application_controller.rb

但是,如果 ApplicationController 已经加载,那么 ruby 将不会触发 const_missing,因为管理模块中的 class 从顶层继承是完全合法的。

如您所说,解决方案是明确说明您继承自什么。我个人在自己的应用程序中使用 Admin::BaseController 作为基础 class.

另一种选择是使用 require_dependency 将 Rails 指向正确的文件:

# admin/application_controller.rb

require_dependency 'admin/application_controller'

module Admin
  class PagesController < ApplicationController
  end
end