Let’s get meta: missing method

Share this article

If you are coming from PHP, or C# you might not find yourself thinking in terms of meta programming – although both languages can do meta programming, it doesn’t seem to be heavily used. This isn’t the case in Ruby – quite the opposite – meta programming is a HUGE part of Ruby.

So what is meta programming? It is basically a way of modifying programs dynamically, like adding or changing methods AFTER the program has started running (or at runtime as we like to call it).

A great example of this is the find_by_* methods in rails. If you have a model called “User” that has a column called “age” you can search your records by age using the magic method User.find_by_age. This is accomplished using the method_missing method.

If you call a method that doesn’t exist, Ruby will call the method_missing method, and pass the name of the method and any arguments you supplied, which means you can dynamically handle the method.

class MyClass
  def find(name, value)
    puts "You want results from #{name} with a value of #{value}"
  end

  def method_missing(id, *args)
    return self.find(Regexp.last_match(1),  args[0]) if id.id2name =~ /find_by_(.+)/
    raise NoMethodError
  end
end

m = MyClass.new
m.find('name', 'madpilot')
> You want results from name with a value of madpilot
m.find_by_name('madpilot')
> You want results from name with a value of madpilot
m.search_by_name('madpilot')
> NoMethodError: NoMethodError

As you can see, there is definitely no “find_by_name” method, yet Ruby is smart enough to call the find method with the correct parameters. What we have done is to run a regular expression against the name of the method, and if it matches the pattern find_by_[string] then it calls the find method with the [string] part as the first parameter and the first argument as the second parameter. Pretty powerful, don’t you think?

Just a tip though – be careful of endless loops – if your method_missing method doesn’t terminate and you call a method that doesn’t exists inside method_missing, you’ll be in all sorts of trouble!

Myles EftosMyles Eftos
View Author

Myles a Perth-based web developer who has worked in all the major web languages, his weapon of choice being Ruby on Rails—although he’s found himself doing more and more front-end development in JavaScript, HTML, and CSS.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form