I'm trying to understand ruby metaprogramming a bit better and while I have workarounds for what I want to do, I would like to make it as clean as possible.
Simply put I would like to check if the class that includes a module has defined a given method:
irb(main):058:1* module A
irb(main):059:2* def self.included(base)
irb(main):060:2* puts base.singleton_method(:singleton_test)
irb(main):061:1* end
irb(main):062:0> end
:included
irb(main):063:1* class B
irb(main):064:1* include A
irb(main):065:2* def self.singleton_test
irb(main):066:2* puts "hi"
irb(main):067:1* end
irb(main):068:0> end
I would expect this to output something like the following:
#<Method: B.singleton_test() (irb):95>
However, it does not:
(irb):60:in `singleton_method': undefined singleton method `singleton_test' for `B' (NameError)
puts base.singleton_method(:singleton_test)
^^^^^^^^^^^^^^^^^
I suspect it's because the singleton methods are not bound to base yet when the included hook is called.
How would I go about checking for singleton_test being defined in this pattern?
PS Maybe also worth noting this seems to happen with any method definitions on base at the time Module A is included, singleton or instance.
It's a simple ordering issue.
Ruby is (mostly) evaluated left-to-right top-to-bottom.
As you can see, the
includecomes before the method definition. You need to swap the two around: