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?

0


source to share


1 answer


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

.



+3


source







All Articles