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