Why a module's singleton method is not visible in downstream eigenclasses where it gets mixed?

eigenclass, inheritance, mixins, ruby

Solution

First of all, `include` does not include eigenclass methods as you might expect. Consider:

module Foo
  class << self
    def do_something
      puts "Foo's eigenclass method does something"
    end
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)

Note that this is consistent with the behavior of classically defined class methods:

module Foo
  def self.do_something
    puts "Foo's class method does something"
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)

A common idiom is to define the class methods in a submodule and then trigger a call to `extend` when the module is included:

module Foo
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def do_something
      puts "Foo::ClassMethod's instance method does something"
    end
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# Foo::ClassMethod's instance method does something

The second thing to note is, that you are really including the instance methods of `Automobile` into the eigenclass of `Vehicle`, thus the instance methods of `Automobile` turn into (eigen)class methods of `Vehicle`.

Your `Car` class basically has nothing to do with all this. The only thing to note here is, that class inheritance also makes class methods available, whereas `include` does not. Example:

class Foo
  def self.do_something
    puts "Foo's class method does something"
  end
end

class Bar < Foo
end

puts Bar.do_something
# "Foo's class method does something"

Problem

I understand the regular method lookup path i.e. `class, superclass/module, all the way up to BasicObject`. I thought it was true for singleton version of the chain also but doesn't seem the case when you mixin a module in the meta-chain. I'd appreciate if someone can explain why in the following example `Automobile` module's `banner` method is called instead of its singleton version when I have included this module in Vehicle's eigenclass. ``` module Automobile def banner "I am a regular method of Automobile" end class << self def banner "I am a class method of Automobile" end end end class Vehicle def banner "I am an instance method of Vehicle" end class << self include Automobile def banner puts "I am a class method of Vehicle" super end end end class Car < Vehicle def banner "I am an instance method of Car" end class << self def banner puts "I am a class method of Car" super end end end puts Car.banner # I am a class method of Car # I am a class method of Vehicle # I am a regular method of Automobile ```

Original source