Dynamic method invocation in Rubyon Jan 14, 2011 in Tech Talks by Jonathan Paul
This year at Caplin we are having a series of Tech Talks based on Bruce A. Tate’s Seven Languages in Seven Weeks. This is a great book and I would highly recommend it to any coders out there. Whether you are interested in picking up a new language or not, this book will definitely get you thinking about how we are constrained by the languages we develop with.
This Week’s Talk on Ruby
During this week’s talk on Ruby we all really loved one of the little examples from the book about how Ruby can give you some incredible functionality.
Ruby supports open classes. This means that at any time you may override any method in any class. As Ruby is a scripting language, you may call any method at any time, even a non-existant one.
While in a compiled languge this error would be caught at compile-time, in Ruby (or any other interpreted language) a Runtime exception is thrown when this problem is encountered. Now interestingly, there is a method which handles this occurance, “method_missing”. As this is a method it too can be overridden by a daring programmer.
Think about the possiblities!
One area this is cool is making a network transparent proxy object. You don’t need to know what methods exist on the remote object, you just let your client code call whatever method it wants, marshal it up and send it across, which allows the proxy object to be just as dynamic as the remote object. This is impossible even with reflection in Java. Let me give you a very simple example.
Consider that you want to create a program in which you may refer to numbers by their Roman numerals. So that X + 5 = 15. Normally we would need to create a method such as Roman.toInt(“X”) to do the conversion, but in Ruby there is a cooler way.
If we create a class Roman and simply call Roman.X the method_missing will be invoked as we have no defined a method named “X”. We can then override method_missing and do the calculations on the fly as we would have done in the Roman.toInt() method using the method name.
This allows us to do this:
Roman.X + Roman.CVI + Roman.IV
rather than this:
Roman.toInt(X) + Roman.toInt(CVI) + Roman.toInt(IV)
Of course this is not without its dangers, overriding method_missing can be reckless in the extreme. You will no longer get any method_missing errors in the future, possibly leading to much frustration and annoyance. And while this is a rather simple example, there are definite advantages for some to create domain specific languages on the fly that can make Ruby an ideal language to use.
If you want to find out more about, it may be worth checking out http://www.alfajango.com/blog/method_missing-a-rubyists-beautiful-mistress/, which has a great blog about how method_missing can be used to make your life and your code, a little bit better.