使用 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 的配置问题/异常