Rails模块范围

时间:2015-04-15 05:05:57

标签: ruby-on-rails ruby inheritance

给出以下控制器结构:

# 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

2 个答案:

答案 0 :(得分:4)

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

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

但是如果已经加载了ApplicationController,那么ruby就不会激活const_missing,因为管理模块中的一个类完全合法地从顶层的东西继承。

您所说的解决方案是明确您继承的内容。我个人在自己的应用程序中使用Admin::BaseController作为基类。

答案 1 :(得分:1)

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

# admin/application_controller.rb

require_dependency 'admin/application_controller'

module Admin
  class PagesController < ApplicationController
  end
end