Method Missing

August 15th, 2007

For the last year I’ve been having a love affair with Ruby’s method_missing. Ryan Heneise was the first to show me the power of this method, when working on Moral Metric together. I’m going to show you a very simple example, and perhaps in future snips more complicated uses, of method_missing.

Let’s say we have an application that keeps track of all the super-heroes and villains. We have one table for the super-heroes and villains and a join table for super powers. We want to have clean syntax to return a boolean value for a hero/villain when check if they have a certain power. e.g.

wolverine.has_claws? wolverine.can_heal?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def check_powers(power)
  self.powers.detect { |power| power.name == power } ? true : false
end


def method_missing(method, *args)
  if find = method.to_s.match(/^has_(\w*)\?$/)
    self.check_powers(find[1])
    
  elsif find = method.to_s.match(/^can_(\w*)\?$/)
    self.check_powers(find[1])

  else
    super
  end
end

The first method does our basic check to see if that power exists and returns a boolean value.

method_missing does two matches here. The first checks to see if there is a match for has_something? and the second does a match for can_something? Both take the “something” and send it to our check_powers method to do our detect. Yes, it is that simple, but oh so cool! And, if method_missing doesn’t find what we were looking for, it sends it on up the chain for rails to handle. Neat, huh?

We can get really nice syntax by using method_missing and DRY up our code, quite a bit as well. Definitely a great little nugget to use.

2 Responses to “Method Missing”

  1. Ryan Says:

    I’m somewhat new to method_missing, but I think it’s among the nicest features of Ruby.

    I’m working on a golf application and wanted to be able to access individual holes, without using a finder or declaring 18 methods corresponding to the 18 holes. So I used method_missing, which allowed me to do course.holes._18 and so forth. Although, I later changed it to course.holes18 instead, using :[] as an alias_method for find.

    It seems like it’s always a good idea to resort back to super when using method_missing… do you think so?

    Also, is it hard to get line numbers to show up in your Ruby syntax highlighting?

  2. Robert Says:

    Ryan: Yes, I’d always, always else back to super so that specific rails functionality will remain open to being used. The Rails core does use method_missing.

    It’s really easy to get numbers to show up, do a google search for Dan Webb’s syntax highligher. It’s a great JS piece to use – which is what I use.

Sorry, comments are closed for this article.