You probably read about how easy it was to implement the Proxy design pattern in Ruby.
Thanks to the Ruby method_missing method, you can pass messages to underlying objects. See the previous article Local resource available in the wild, thanks to DRb for a fully described example.
But there’s one caveat, you have to be very careful when implementing your method_missing method.
Take this code for example:
def method_missing(name, *args, &block) # Get the first arg, which contain information about which underlying # object to call. id = arg[0] # Call the corresponding underlying object with the first argument removed my_underlying_objects[id].__send__(name, *args[1..-1], &block) end
If you execute this code, you’ll be stuck in an infinite loop. Why ? There’s a typo, one typo which will cause a segmentation fault. I wrote arg[0] instead of args[0].
To detect this problem before it happens, we can take advantage of the Kernel#caller method. It generates the current execution stask. Here is how we can use it to detect that the current object is calling himself:
def method_missing(name, *args, &block) # Check that we're not calling 'method_missing' recursively if caller.first.include?(__FILE__) raise "#{self.class} is calling itself -method #{name}-. Verify that you do not call a non existing method !!" end # Get the first arg, which contain information about which underlying # object to call. id = args[0] # Call the corresponding underlying object with the first argument removed my_underlying_objects[id].__send__(name, *args[1..-1], &block) end
That’s all, we just check that the caller method is not in the current file. If your method_missing code become more and more complex, especially if it includes some meta-programming tricks, you’ll feel A LOT safer!
One last thing: Kernel#caller is not what we could call a non-expensive method, you should only use it in development.
September 26th, 2008 at 9:43 pm
Hello Noob,
How are you?
When is the next update of your blog? I’m really interested in reading a news about Ruby and Spring.
Venkata