Why does the order of inclusion of modules matter in Ruby?
This question is best summarized with a code example:
module TestOne
module Foo
def foo
42
end
end
module Bar
include Foo
end
class Quux
include Bar
end
end
TestOne::Bar.ancestors # => [TestOne::Bar, TestOne::Foo]
TestOne::Quux.ancestors # => [TestOne::Quux, TestOne::Bar, TestOne::Foo, Object, Kernel]
TestOne::Quux.new.foo # => 42
module TestTwo
class Quux
end
module Bar
end
module Foo
def foo
42
end
end
end
TestTwo::Quux.send :include, TestTwo::Bar
TestTwo::Bar.send :include, TestTwo::Foo
TestTwo::Bar.ancestors # => [TestTwo::Bar, TestTwo::Foo]
TestTwo::Quux.ancestors # => [TestTwo::Quux, TestTwo::Bar, Object, Kernel]
TestTwo::Quux.new.foo # =>
# ~> -:40: undefined method `foo' for #<TestTwo::Quux:0x24054> (NoMethodError)
I thought that when you include a module ( Bar
inside a class , for example Foo
), whatever Ruby stores is the fact that it Foo
includes Bar
. So when you call a method on Foo, it looks in Bar
for the method.
If this is true, by the time it TestTwo::Quux.new.foo
is called, I mixed the method Foo
in TestTwo::Bar
to make it work, right?
source to share
The docs say append_features (which is called by include) mixes methods with the caller. Therefore, when TestTwo::Quux
includes TestTwo::Bar
, no methods are added to TestTwo::Quux
. The next line adds methods to TestTwo::Bar
, but not to TestTwo::Quux
.
source to share