I want to prepend Kernel.rand like this:
# I try something like
mod = Module.new do
def rand(*args)
p "do something"
super(*args)
end
end
Kernel.prepend(mod)
# And I expect this behaviour
Kernel.rand #> prints "do something" and returns random number
rand #> prints "do something" and returns random number
Object.new.send(:rand) #> prints "do something" and returns random number
Unfortunately, the code above does not work as I want to. Prepending Kernel.singleton_class does not work too
It's not required to use prepend feature, any suggestiion that will help to achieve the desired behaviour is welcome
Kernelmethods likerandorMathmethods likecosare defined as so-called module functions (seemodule_function) which makes them available as both,... (public) singleton methods:
... and (private) instance methods:
To achieve this,
Math's singleton class doesn't simply includeMath(which would turn all its methods into singleton methods). Instead, each "module function" method gets defined twice, in the module and in the module's singleton class:As a result, prepending another module to
Mathor patchingMathin general will only affect the (private) instance method and thus only classes includingMath. It won't affect thecosmethod which was defined separately inMath's singleton class. To also patch that method, you'd have to prepend your module to the singleton class, too:Which gives:
As well as:
However, as a side effect, it also makes the instance method public:
I've picked
Mathas an example because it's less integrated thanKernelbut the same rules apply to "global functions" fromKernel.What's special about
Kernelis that it's also included intomainwhich is Ruby's default execution context, i.e. you can callrandwithout an explicit receiver.