I used the following hook to check the module that is doing the including when I do include Foo:
module Foo
def self.included(includer)
puts includer
end
end
Module#include behaves differently in a module (where it is usually used) vs. at the top level. Inside a module, self is the module, which is an instance of Module. When I call include, the module doing the including is what self is:
module Bar
puts self # => Bar
include Foo # => includer: Bar
end
At the top level of a ruby script, self is main, which is an instance of Object. When I call include at the top level, the module doing including is Object, the class of what self is:
puts self # => main
include Foo # => includer: Object
Can someone explain why?
The top-level object must be special; If I call to_s or inspect on it, it just says main, but if I create another object with Object.new and call to_s or inspect on it, I get the usual object notation: #<Object:0x007fae0a87ac48>.
main is special, and has its own definition of include. That is, its singleton_class has its own definition of include. To prove it:
irb(main):017:0> method(:include).owner
=> #<Class:#<Object:0x007fc0398c6468>>
irb(main):018:0> self.singleton_class
=> #<Class:#<Object:0x007fc0398c6468>>
The include you're thinking of is defined on Module:
MyClass.method(:include).owner
=> Module
So, include acts different at the "top level", aka on the object we're calling main for the simplest possible reason: it's just a completely different method than Module#include.
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