Feb 1, 2009

Ruby and Recursive Send

Some dynamic languages have the ability to call an arbitrary method of an object. The name of the method to be called is usually stored inside a string.

Ruby is no different. You use Object#send to call a method:
"5".send(:to_i)   # => 5
This isn't that useful for a small thing like that example there, but for more sophisticated applications this can save you a lot of typing.

For something I'm working on, I have some code that gets repeated a lot on different return results of an object. So I figured I'd just stick all the things I had to do in a string, iterate over the string calling send. However some of the properties I wanted were a little complex, as in they were calling the methods of a return result of a method. For example (something I may have used on my freegamage site):
["genre", "user.name"].each do |method|
game.send(method)
end
Unfortunately the "user.name" property is not actually a method of game, so it fails.

We have a solution though:
class Object
def send_r(method)
method.split(".").inject(self) { |ob, meth| ob.send(meth) }
end
end
This little method assumes you're using something like "method1.method2.method3..." when you call it, and then recursively calls each method on the previous method's return value.

No comments: