使用 Ruby on Rails ActiveSupport::Concern 功能时如何“嵌​​套”包含模块?

Posted

技术标签:

【中文标题】使用 Ruby on Rails ActiveSupport::Concern 功能时如何“嵌​​套”包含模块?【英文标题】:How to "nest" the inclusion of modules when using the Ruby on Rails ActiveSupport::Concern feature? 【发布时间】:2012-10-18 02:22:48 【问题描述】:

我正在使用 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

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

【问题讨论】:

请注意,这根本不是一个好习惯。您可能会在模块的包含顺序之间产生虚假的依赖关系。 【参考方案1】:

如果您在MyModuleA 的“主体”中包含MyModuleB,则扩展了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

【讨论】:

谢谢。我在方法上开了一个new related question。

以上是关于使用 Ruby on Rails ActiveSupport::Concern 功能时如何“嵌​​套”包含模块?的主要内容,如果未能解决你的问题,请参考以下文章

第一个CRUD的制作方法(Ruby on Rails 開發秘籍 | Ruby on Rails 快速入門)

思考Ruby On Rails的底层代码(Ruby on Rails 開發秘籍 | Ruby on Rails 快速入門)

Ruby on Rails Installation(Learn Rails5.2)

Ruby on Rails - 在 OSX 上使用 Ruby 2.4.4 而不是 rails 5.1.6 的配置问题/异常

Ruby on Rails Cron 作业示例

Ruby on Rails - Ruby 中的 KeyCode [关闭]