I have a couple of modules that extend method missing:
module SaysHello
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^hello/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^hello/)
puts "Hello, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
module SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^goodbye/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^goodbye/)
puts "Goodbye, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
class ObjectA
include SaysHello
end
class ObjectB
include SaysGoodbye
end
This all works well, eg ObjectA.new.hello_there
outputs "Hello, hello_there"
. Likewise, ObjectB.new.goodbye_xxx
outputs "Goodbye, xxx"
. respond_to?
also works, eg ObjectA.new.respond_to? :hello_there
return true.
However, this doesn't work very well when you want to use both SaysHello
and SaysGoodbye
:
class ObjectC
include SaysHello
include SaysGoodbye
end
While ObjectC.new.goodbye_aaa
works correctly, ObjectC.new.hello_a
acts strange:
> ObjectC.new.hello_aaa
Hello, hello_aaa
NoMethodError: private method `method_missing' called for nil:NilClass
from test.rb:22:in `method_missing' (line 22 was the super.method_missing line in the SaysGoodbye module)
It outputs correctly, then throws an error. Also respond_to?
doesn't correctly, ObjectC.new.respond_to? :hello_a
returns false.
Finally, adding this class:
class ObjectD
include SaysHello
include SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^lol/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^lol/)
puts "Haha, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
Also acts strangely. ObjectD.new.lol_zzz
works, however ObjectD.new.hello_aand ObjectD.new.goodbye_t
both throw a name exception after outputting the correct string. respond_to?
also fails for hello and goodbye methods.
Is there a way to get this all working correctly? An explanation of how method_missing
, Modules and super
are interacting would also be really useful.
EDIT: coreyward solved the problem, if I use super instead of super.<method-name>(args...)
in all the methods I define, the program works correctly. I don't understand why this is though, so I asked another question about this at What does super.<method-name> do in ruby?