I noticed something odd while I was adding methods to Kernel to make them available globally. It's interesting, and I'm looking for some documentation or good explanation.
Let's look at the code:
file: ./demo.rb
# example 1
module Kernel
def foo
puts "I'm defined inside the module!"
end
end
# example 2
module Bar
def bar
puts "I'm included! (bar)"
end
end
Kernel.send :include, Bar
# example 3
module Baz
def baz
puts "I'm included! (baz)"
end
end
module Kernel
include Baz
end
Then, in bash and IRB
$ irb -r ./demo.rb
> foo
# I'm defined inside the module!
> bar
# NameError: undefined local variable or method `bar' for main:Object
> baz
# NameError: undefined local variable or method `baz' for main:Object
>
> self.class.ancestors
# => [Object, Kernel, BasicObject]
>
> include Kernel
>
> self.class.ancestors
# => [Object, Kernel, Baz, Bar, BasicObject]
>
> foo
# I'm defined inside the module!
> bar
# I'm included! (bar)
> baz
# I'm included! (baz)
foo works as expected, and is available for all objects that include Kernel. bar and baz, on the other hand, are not immediately available.
I imagine it's because the evaluation context of IRB (an Object) already includes Kernel, and including a module A inside a module B will not "reload" all previous inclusions of B.
Ok, it makes perfect sense, and in fact re-including Kernel will add the other two methods.
Then, my questions are:
- Why does opening
Kernelwork? (example 1) - if opening the module is treated differently, why isn't the 3rd example working as well?