7

我正在使用 Ruby 1.9.2 和 Ruby on Rails v3.2.2 gem。鉴于我正在使用 RoR ActiveSupport::Concern功能,我想“嵌套”包含模块,但我怀疑应该在哪里说明该include方法。也就是说,我有以下内容:

module MyModuleA
  extend ActiveSupport::Concern

  # include MyModuleB

  included do
    # include MyModuleB
  end
end

应该include MyModuleB在“正文”/“上下文”/“范围”中说明MyModuleA还是应该在included do ... end块中说明?有什么区别,我应该从中得到什么?

4

1 回答 1

22

如果您包含MyModuleB在 的“正文”中MyModuleA,则扩展了 B 的功能的是模块本身。如果您将它包含在included块中,那么它将包含在混入的类中MyModuleA

那是:

module MyModuleA
  extend ActiveSupport::Concern
  include MyModuleB
end

产生类似的东西:

MyModuleA.send :include, MyModuleB
class Foo
  include MyModuleA
end

尽管

module MyModuleA
  extend ActiveSupport::Concern
  included do
    include MyModuleB
  end
end

产生类似的东西:

class Foo
  include MyModuleA
  include MyModuleB
end

其原因ActiveSupport::Concern::included类似于:

def MyModuleA
  def self.included(klass, &block)
    klass.instance_eval(&block)
  end
end

块中的代码在included包含类的上下文中运行,而不是在模块的上下文中运行。因此,如果 MyModuleB 需要访问它正在混入的类,那么您需要在included块中运行它。否则,它实际上是同一件事。

通过演示:

module A
  def self.included(other)
    other.send :include, B
  end
end

module B
  def self.included(other)
    puts "B was included on #{other.inspect}"
  end
end

module C
  include B
end

class Foo
  include A
end

# Output:
# B was included on C
# B was included on Foo
于 2012-10-28T16:06:49.697 回答