我有一个类Ryte :: Theme。如果我在类上调用included_modules,我会回来(缩写):
[Ryte :: Bundleable :: Core,Ryte :: Bundleable :: Validators, Ryte :: Bundleable :: Builder,ActiveModel :: Validations :: HelperMethods, ActiveModel :: Validations,ActiveSupport :: Callbacks,Ryte :: Bundleable]
Ryte :: Theme通过单个模块Ryte :: Bundleable引入嵌套模块。以下是相关的类和模块定义:
class Ryte::Theme
include Ryte::Bundleable
end
module Ryte::Bundleable
extend ActiveSupport::Concern
included do
include ActiveModel::Validations
include Ryte::Bundleable::Builder
include Ryte::Bundleable::Validators
include Ryte::Bundleable::Core
end
end
鉴于此,为什么我收到以下回复:
Ryte::Theme.include?(Ryte::Theme::Validators)
=> true
我还没有包含这个额外的模块..这在included_modules响应中很明显。这与ActiveSupport关注有关吗?我希望能够包含Ryte :: Theme :: Validators并将它混合在一起,但因为它认为它已经被包含在内,所以它不会再次包含它(因为它不应该包含它)。因此,当我将include添加到类定义时,它会被遗忘,如下所示:
class Ryte::Theme
include Ryte::Bundleable
include Ryte::Theme::Validators # <- Does not load
end
为什么这个附加模块Ryte :: Theme :: Validators也没有混入?
好的,刚刚意识到:
1.9.3p194 :005 > Ryte::Bundleable::Validators == Ryte::Theme::Validators
=> true
奇怪..这是为什么?
答案 0 :(得分:5)
更新:此 与ActiveSupport :: Concern相关(见下文)。
尝试以下方法:
# initialize constants
class A; end # class Ryte
module A::B; end # module Ryte::Bundleable
module A::B::C; end # module Ryte::Bundleable::Validators
module A::B # module Ryte::Bundleable
def self.include(base)
base.class_eval do
include A::B::C # include Ryte::Bundleable::Validators
end
end
end
class D # class Ryte::Theme
include A::B # include Ryte::Bundleable
end
A::B::C == D::C #=> true
这是因为模块和类被命名空间的方式:当你从A::B::C
内部包含A::B
时,模块名称是相对于模块本身引用的,它只是{{1 (在你的情况下,只是C
)。因此,当您在其他类Validators
中包含A::B
时,而不是包含名为D
的模块(即A::B::C
),ruby包含一个名为Ryte::Bundleable::Validators
的模块(即C
)。这就是Validators
评估为真的原因。
但是,通过上面的例子:
Ryte::Bundleable::Validators == Ryte::Theme::Validators
所以这就是D.include?(A::B::C) #=> false
开始的地方。重新定义上面的模块ActiveSupport::Concern
,如下所示:
A::B
你会发现module A::B # module Ryte::Bundleable
extend ActiveSupport::Concern
included do
include A::B::C # include Ryte::Bundleable::Validators
end
end
现在评估为真。老实说,我不确定为什么会这样,但它必须与上面的命名空间有关。