I am writing something as follows
module Test
def self.print(*args)
p 'something'
p args
end
end
def print(*args)
p "print something"
p args
end
def method_caller(method_name, *args)
send(method_name, *args)
end
method_caller(:print, 2) # this works fine
method_caller("print", 2, 3) # this one also
method_caller("Test.print", 2) # this doesn't work
Basically, I pass method_caller the name of a method and some arguments and then I use the send method to actually invoke the method.
I usually pass in the name of the method as a symbol, but how would I deal with Test.print? I imagine at some point I might be passing in objects and having them call their own methods.
The method I would like to invoke could be literally anywhere.
UPDATE:
Trying out each suggestion, the explicit receiver looks like a good way to do it since it’s obvious what is happening, but what about christianblais’ idea. I changed it to avoid the eval call as such
def method_caller(method_name, *args)
if method_name.is_a?(String)
chain = method_name.split('.')
obj, method_name = Object.const_get(chain[0...-1].join('.')), chain[-1]
obj.send(method_name, *args)
else
send(method_name, args)
end
end
Which means I can just say method_caller("Test.print", 2), but maybe there are some gotchas…
Well, why don’t you give your method_caller a receiver argument?
The other calls need to use
selfas the receiver, which is implicit in your current implementation. But finally all this gives you is an incomplete ad hoc reimplementation ofsend, so one really wonders what you are trying to achieve with that.