Rails模块范围

fir*_*dev 5 ruby inheritance ruby-on-rails

给定以下控制器结构:

# 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
Run Code Online (Sandbox Code Playgroud)

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

因此,我决定不冒险,并将所有控制器的声明更改/admin为特定目标Admin::ApplicationController

# admin/pages_controller.rb
module Admin
  class PagesController < Admin::ApplicationController; end
end
Run Code Online (Sandbox Code Playgroud)

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

Admin::PagesController 有时继承ApplicationController而不是Admin::ApplicationController尽管两者都是相同的module Admin

Fre*_*ung 4

这里的问题是rails的开发模式代码加载:一般来说,当您尝试使用常量(例如它的子类)执行某些操作并且该常量不存在时,就会加载代码。这会导致const_missing被调用,rails 使用它来尝试加载类(有关详细说明,请参阅指南)。

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

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

正如你所说的解决方案是明确你继承的内容。就我个人而言,我在自己的应用程序中使用它Admin::BaseController作为基类。