I am using Ruby 1.9.2 and the Ruby on Rails v3.2.2 gem. I would like to "nest" the inclusion of modules given I am using the RoR ActiveSupport::Concern feature, but I have a doubt where I should state the include
method. That is, I have the following:
module MyModuleA
extend ActiveSupport::Concern
# include MyModuleB
included do
# include MyModuleB
end
end
Should I state include MyModuleB
in the "body" / "context" / "scope" of MyModuleA
or I should state that in the included do ... end
block? What is the difference and what I should expect from that?
If you include MyModuleB
in the "body" of MyModuleA
, then it is the module itself that is extended with B's functionality. If you include it in the included
block, then it is included on the class that mixes in MyModuleA
.
That is:
module MyModuleA
extend ActiveSupport::Concern
include MyModuleB
end
produces something like:
MyModuleA.send :include, MyModuleB
class Foo
include MyModuleA
end
while
module MyModuleA
extend ActiveSupport::Concern
included do
include MyModuleB
end
end
produces something like:
class Foo
include MyModuleA
include MyModuleB
end
The reason for this is that ActiveSupport::Concern::included
is analogous to:
def MyModuleA
def self.included(klass, &block)
klass.instance_eval(&block)
end
end
The code in the included
block is run in the context of the including class, rather than the context of the module. Thus, if MyModuleB needs access to the class it's being mixed-in to, then you'd want to run it in the included
block. Otherwise, it's effectively the same thing.
By means of demonstration:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With