Reputation: 138210
This question is best summed up 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 (e.g. Bar
inside a class Foo
) all that Ruby stores is the fact that Foo
includes Bar
. So, when you call a method on Foo it looks in Bar
for the method.
If that was true, by the time TestTwo::Quux.new.foo
is called I've mixed the foo
method into TestTwo::Bar
so it should work, right?
Upvotes: 2
Views: 2021
Reputation: 3326
The docs say that append_features (which is called by include) mixes the methods into the caller. So 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
.
Upvotes: 5