我有一个如下所示的文件夹结构:
app/models/
concerns/
quxable.rb
foo/
bar.rb
baz.rb
我在 Rails 3 中,所以我已经自动加载了我的担忧:
config.autoload_paths += Dir[Rails.root.join('app', 'models', "concerns", '**/')]
文件如下:
quxable.rb
module Quxable
extend ActiveSupport::Concern
module ClassMethods
def new_method
end
end
end
bar.rb
class Foo::Bar < ActiveRecord::Base
include Quxable
end
baz.rb
class Foo::Baz < ActiveRecord::Base
include Quxable
end
现在在控制台中,如果这样做,我会得到以下输出:
Foo::Bar.respond_to? :new_method #=> true
Foo::Baz.respond_to? :new_method #=> false
reload!
Foo::Baz.respond_to? :new_method #=> true
Foo::Bar.respond_to? :new_method #=> false
所以它似乎只正确地包含在第一次访问的模型中。然而,如果我运行以下命令:
ActiveRecord::Base.descendants.select{ |c| c.included_modules.include?(Quxable) }.map(&:name)
我明白了["Foo::Bar", "Foo::Baz"]
。
知道这里发生了什么吗?我猜想自动加载/急切加载,但我不确定为什么两个模型都没有获得新的类方法。
PS - 我尝试过重写模块而不使用ActiveSupport::Concern
(只是因为我使用的是旧的 Rails 版本并且我在黑暗中拍摄)使用:
def include(base)
base.send :extend, ClassMethods
end
但我仍然有同样的问题。
编辑
我最初忽略了这一点(只是试图提出最简单的问题),所以我向那些想早点提供帮助的人道歉。但quxable.rb
实际上看起来像这样:
module Quxable
extend ActiveSupport::Concern
LOOKUP = {
Foo::Bar => "something",
Foo::Baz => "something else"
}
module ClassMethods
def new_method
end
end
end
所以我猜我创建了某种循环依赖项,用 Class 对象定义了一个常量。任何人都可以确认吗?奇怪的是,它只是通过没有在第二个访问的类上定义类方法而静默失败。我不知道这是为什么?