This guest post is contributed by Paolo Perrotta, a freelance geek, currently coaching agile teams for a large phone company. He also wrotes the Metaprogramming Ruby book for the Prags. He lives in Northern Italy with his girlfriend and a cat. He loves Ruby.
method_missing() method is a wonderful tool for every Ruby
programmer. I love it. There, I said it!
Do YOU know Ruby’s ‘Chainsaw’ method?
Some Rubyists are
when I declare my love for
method_missing(). They do have a point. As
far as tools go,
method_missing() is a chainsaw: it’s powerful, but
it’s also potentially dangerous.
In case you don’t know about
method_missing(), here is how it works.
Imagine that you’re calling a method on a Ruby object. For example, you
duck.sing("Quacking in the Rain"). Usually, at this point one of
two things happens: if
duck has a
sing() method that takes one
argument, then Ruby executes the method; if
duck doesn’t have that
method, then Ruby raises an error. But wait: there is a third
duckdoesn’t have a method named
sing(), but it does
have a method named
method_missing(), then Ruby executes
method_missing() instead. Ruby also tells to
method you originally called, with arguments and all. Here is an
You can say that
duck.dance() are Ghost
Methods: they aren’t defined anywhere,
but you can call them anyway.
method_missing()does. The difficult part is deciding when
and how to use it. Let’s see an example of Ghost Methods in action.
Imagine that you have an
InformationDesk object with many complex
methods that provide some kind of tourist information or service:
To give a break to people working at the
InformationDesk, you can wrap
InformationDesk in a
DoNotDisturb forwards method calls to the wrapped
unless it’s lunchtime. During lunch breaks,
DoNotDisturb responds to
calls by raising an exception – unless you’re calling
that works at any hour. (If you think that two hours are too much for a
lunch, then you’ve probably never lived in Italy!)
The problem with the above code is that
DoNotDisturb contains a lot of
look-alike methods. This is a form of duplication, and duplication
sucks. If a programmer adds methods to
InformationDesk, she also needs
to remember to add matching methods to
DoNotDisturb, most likely by
copy-pasting the existing look-alike methods and then modifying them.
One misstep in this procedure, and you have a brand new bug.
When I work with Java or C#, I accept this kind of code duplication as
a fact of life. In Ruby, I can be more aggressive and replace all the
calls with a single
DoNotDisturb is now a Dynamic Proxy:
it forwards each method call to its inner
InformationDesk, and it also
wraps additional logic around each call. If you add methods to
InformationDesk, you needn’t worry about
DoNotDisturb: it will work
for the new methods without any change.
This kind of trickery is useful, but it does have a dark side. If you
method_missing(), you can end up with code that’s difficult to
read and maintain. I’m still intimidated by some of the wildest
that abound the Ruby ecosystem. Even if you take care to keep your
method_missing()small and maintainable, Ghost Methods are still
inherently less explicit than regular methods. You can easily discover
the regular methods in a class by looking at the auto-generated
documentation, but you have to look at the source code (or the author’s
documentation) to spot Ghost Methods.
Also, if you’re not careful around
method_missing(), sneaky bugs can
creep into your code. For example, an overly tolerant
might accept a mistyped method call without flinching. Chainsaws are
meant to be handled with care!
So, what kind of tree should you use the
method_missing() chainsaw on?
Here are my simple rules of thumb:
- I use
method_missing()to remove duplication. A well placed
method_missing()allows me to remove duplicated code at a level that wouldn’t otherwise be possible.
- On the other hand, I usually think twice about using
method_missing()for cosmetic reasons, like getting cool method names such as
- I always try to evaluate whether
method_missing()is worth the extra reading effort. I dislike duplicated code because it’s hard to read and modify. If I replace that code with a
method_missing()that’s even harder to read and modify, then I’ve defeated
It’s a balancing act: with some experience you can strike the sweet spot
between shortness and clarity in your Ruby code. To do that, you’ll
likely use the
method_missing() chainsaw to cut out unnecessary
branches from your forest of methods.
There are many more neat tricks, caveats and interesting details around
method_missing(). In Metaprogramming
I devoted most of the Methods chapter to it (you can check the first few
pages from that chapter
here). You can
also find a lot of information on
method_missing() on the Web,
including some pretty crazy bug
With this information, and some experience, you’ll be able to make up
your own mind about the pros and cons of
Me, I already made up my mind. Yes, I use
Yes, I keep it as short as I can. Yeah, I triple-check it for bugs… But
when the duplication begins to sting, I put on my evil grin and grab my
Have you used
method_missing() before? Why don’t you share your
experiences with us? Let us know in the comments section of this post.
Post supported by Tupalo.com: Tupalo.com is a privately-held internet startup located in Vienna, Austria. Their social yellow-pages app is developed using Ruby on Rails and also uses many of the other exciting tools like Cucumber, RSpec, Capistrano and Puppet, Ruby developers came to appreciate.
Do read these awesome Guest Posts:
- Gem Sawyer, Modern Day Ruby Warrior
- An Introduction to Outside-in Development
- Ruby Forensics
- An introduction to eventmachine, and how to avoid callback spaghetti
- The Testing Mindset
- An Introduction to Desktop Apps with Ruby
- The Ruby movement
- Almost everything is an object (and everything is almost an object!)
- So… you’re new to Ruby!
- Incorporating Web APIs to spark computer programming exercises
- 14 Ways To Have Fun Coding Ruby
- Writing modular web applications with Rack
- How to Learn Ruby (or any programming language)