10 things you should know about method_missing

Posted by amy on August 01, 2007

[update, 9:27 a.m., 8/1/2007: welcome, reddit readers. annoyed at me for calling this post "10 things"? Well, then you'll really hate me after reading this post!]

1. method_missing is a Ruby kernel method and everyone should know about it.

2. Rails implements some of its funkiest magic with method_missing. When you ask your model to find_by_freaky_column_name, and it does so, that’s because ActiveRecord::Base overrides the kernel’s method_missing method.

3. method_missing is the method of last resort. When you send a message to a Ruby object, Ruby looks for a method to invoke with the same name as the message you sent. (There are a bunch of different ways to send the message, but the most common one is just obj.method_name. But you can make the fact that you are sending a message explicit by using obj.send(:method_name)). First it looks in the current self object’s own instance methods. Then it looks in the list of instance methods that all objects of that class share, and then in each of the included modules of that class, in reverse order of inclusion. Then it looks in that class’s superclass, and then in the superclass’s included modules, all the way up until it reaches the class Object. If it still can’t find a method, the very last place it looks is in the Kernel module, included in the class Object. And there, if it comes up short, it calls method_missingYou can override method_missing anywhere along that method lookup path, and tell Ruby what to do when it can’t find a method.

4. Sometimes people use method_missing to implement some default behavior they want to occur; more often they seem to use it as a kind of method factory or dispatcher. They have a class or module that they want to have many methods that do generally the same kinds of things, they’re not sure in advance which methods people will actually want to call, or there are so many of them, and they’re all so similar, that it seems like a waste to implement them all by hand. So they just say, okay, if someone gives me a method that doesn’t exist, I’ll assume that they’re trying to do this general kind of thing, and I’ll make them a method based on their name that does the thing they probably want it to do.Sometimes they make a new method and add it to the class (factory); sometimes they just do what needs to be done in method_missing itself (dispatcher).

5. Basically, method_missing is one of the features of Ruby that make it remarkably easy to create your own DSL for fun and profit. DSLs are Domain Specific Languages, which, if you didn’t know — and of course, dear reader, you did, because you are oh-so-up on all the oh-so-fashionable programming paradigms, are the big thing that Martin Fowler is talking about a lot these days.

6. Here’s the kernel’s method_missing implementation. It’s in C, so I have no freakin’ clue what it’s doing, but I know what the result is: a NoMethod error:

irb(main):227:0> "thingy".invoke_method_missing_for_demo_purposes("arg", "other arg")
NoMethodError: undefined method `invoke_method_missing_for_demo_purposes' for "thingy":String from (irb):227

7. Now here’s Jamis Buck showing us how ActiveRecord::Base overrides method_missing. It’s a long but fascinating article that takes you step-by-step through some Rails source code. Go look at it now.

8. method_missing is said to be slower than calling an actually-already existing method, unsurprisingly, given that it’s by definition invoked only after Ruby’s looked everywhere else for your method. The speed issue may or may not matter for your intended use, and my impression is that it usually doesn’t. #{usual disclaimer about benchmarking, using profilers, and not prematurely optimizing your code.}

9. method_missing can also be a bit opaque to users of your code, since dynamically created methods are, of course, not documented in the API.

10. The use of method_missing falls under the general technique of metaprogramming, which is a big deal in Ruby, and not something ordinary folks ever fool around with in many other languages (like Java). At least, I never fooled around with it in Java. But hey, what do I know? What is metaprogramming? C’mon, people, it’s right up there with DSLs in the list of things the kewl kids know. But actually, it really is pretty cool, and it really is pretty much the way Ruby works. And it’s not as difficult as (but waaaay more useful than) say, Lacan, despite the poststructuralist-sounding name and the fact that the metaprogramming wikipedia article makes it sound very fancy.

Ignore the wikipedia article, listen to _why, in a discussion of method_missing: “I don’t think the idea here is to save memory or speed. The idea behind metaprogramming is to teach Ruby your conventions and let it do some guessing, in order to save you some code.”

Don’t trust that _why and all his chunky bacon? Here’s David Black, equally reassuring:

One of the great accomplishments of Ruby is that its object and class model bring about a wonderful unity and simplicity. Even things that might seem like they should be hard or obscure are actually very transparent, once you have the hang of how the model works.Unfortunately, there’s a trend toward drawing an increasingly sharp line between regular programming and “metaprogramming” in Ruby discussions, where metaprogramming is understood to mean… well, I’m not sure what it’s understood to mean, the way it’s getting used in connection with Ruby, and that’s the problem.There’s no natural separation between programming and metaprogramming in Ruby, and no reason to make life harder by breaking them apart. The thrust of Ruby’s design is to dissolve complexities, so that even things that appear to be “wizardly” or full of “dark magic” actually make perfect sense in terms of a relative small number of underlying language principles.

So here’s your takeaway #{max gagging sound}: method_missing is cool. It’s metaprogramming. It’s used to save programmer time and typing, and to make DSLs or provide default behavior. Most famously in ActiveRecord dynamic finders. Metaprogramming is not scary, and method_missing, like other cool Ruby features, may or may not float your boat. That’s cool, either way.

_why says: “I never use method_missing. Maybe twice. And both times I didn’t use it, regretted it, forcefully ejected the code from a moving vehicle, shed nary a tear.” Then he goes on to enumerate some of the very cool ways he’s seen method_missing used elsewhere, in non-_why code.

So: know it, love it, use it, hate it, kill it, eat it, break it, think it. As they say at Ari’s preschool: “Have fun, be safe, and USE YOUR IMAGINATION!” Matz wants you to.

Popularity: 58% [?]

Theoretically Related Posts
  • 10 things I didn’t know about Reddit
  • Rails Ninjas We Are Not
  • Choking on all the attention! And, Career Advice from Cary Tennis
  • Fearless Play. Or, What We Did in 2007
  • Trackbacks

    Use this link to trackback from your own site.

    Comments

    Leave a response

    1. reddit.com: programming - what's new online Thu, 02 Aug 2007 03:37:53 UTC

      Kramer auto Pingback[...] Ruby : 10 things you should know about method_missing (thirdbit.net) [...]

    2. Shane Celis Thu, 02 Aug 2007 04:27:41 UTC

      Another good one to know in conjunction with method_missing is define_method. Basically, if you know at compile-time, err, read-time, what methods you want to dynamically define, you can define them and not have to pay the penalty for them being dynamic. I had some code where I added some methods to the String class to check whether it was valid for a given regular expression. I implemented it first with method_missing, then my coworker showed me the define_method way to do it. I don’t know how well this code will show up in here, but here goes:

      valid_regexes = {
      :host => Regexp.new(/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}$/ix),
      :macaddr => Regexp.new(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/) # Insist on lowercase
      }

      class String
      # Define the valid_*? methods.
      valid_regexes.each { |type,regex|
      define_method(“valid_#{type}?”) { (self =~ regex) != nil }
      }
      end

      “gnufoo.org”.valid_host? -> true
      “blah”.valid_host? -> false

    3. はてなブックマーク - ruby Thu, 02 Aug 2007 06:09:20 UTC

      Kramer auto Pingback[...] Subversion Tim 1 users 2007年08月02日 book   Bookmark.push(‘entry-5458724′) 10 things you should know about method_missing | thirdbIT http://www.thirdbit.net コンピュータ   ActiveRecord API Bacon Domain Specific Language [...]

    4. ときどきの雑記帖 Thu, 02 Aug 2007 20:45:22 UTC

      Kramer auto Pingback[...] 10 things you should know about method_missing | thirdbIT [...]

    5. 10 Things To Know About "method_missing" Fri, 03 Aug 2007 05:42:42 UTC

      [...] method_missing is one of Ruby’s coolest bits of metaprogramming voodoo. Two years, Why wrote about it, and now Amy Newall, half of a Massachusetts-based husband-wife development team, writes about 10 things you should know about method_missing. [...]

    6. Kramer auto Pingback[...] http://feeds.feedburner.com/~r/RubyInside/~3/140262220/10-things-to-know-about-method_missing-569.htmlhttp://www.rubyinside.com/10-things-to-know-about-method_missing-569.html method_missing is one of Ruby’s coolest bits of metaprogramming voodoo. Two years, Why wrote about it, and now Amy Newall, half of a Massachusetts-based husband-wife development team, writes about 10 things you should know about method_missing. [...]

    7. StumbleUpon » Your page is now on StumbleUpon! Fri, 03 Aug 2007 09:44:09 UTC

      Kramer auto Pingback[...] Your page is on StumbleUpon [...]

    8. Giles Bowkett Fri, 03 Aug 2007 12:25:44 UTC

      Just a note – I believe that some of the stuff that Rails used to implement with method_missing is now handled with code generation instead, due to method_missing being expensive in terms of time.

    9. [...] 10 things you should know about method_missing [...]

    10. 10 Things To Know About "method_missing" | Phidz Fri, 03 Aug 2007 13:04:14 UTC

      Kramer auto Pingback[...] method_missing is one of Ruby’s coolest bits of metaprogramming voodoo. Two years, Why wrote about it, and now Amy Newall, half of a Massachusetts-based husband-wife development team, writes about 10 things you should know about method_missing. [...]

    11. doggdot.us Fri, 03 Aug 2007 17:57:11 UTC

      Kramer auto Pingback[...] 3, 2007 GGL – Comic-Con 2007: A Photo Blogsource: del.icio.usposted: Fri Aug 3, 2007 10 things you should know about method_missing | thirdbITsource: del.icio.usposted: Thu Aug 2, 2007 c4LPT: Top 100 Toolssource: del.icio.usposted: Tue [...]

    12. WebRss - Random - b r a y d e n . o r g Sat, 04 Aug 2007 05:36:18 UTC

      Kramer auto Pingback[...] 10 things you should know about method_missing | thirdbIT [...]

    13. ktheory.com » 2005 » February Sun, 05 Aug 2007 04:11:05 UTC

      Kramer auto Pingback[...] links: 10 things you should know about method_missing | thirdbIT in _toread ruby rails rubyonrails New Freedom Destroys Old Culture: A response to Nick Carr. [...]

    14. BuffaloFeeds » Ruby Inside Sun, 05 Aug 2007 13:11:31 UTC

      Kramer auto Pingback[...] method_missing is one of Ruby’s coolest bits of metaprogramming voodoo. Two years, Why wrote about it, and now Amy Newall, half of a Massachusetts-based husband-wife development team, writes about 10 things you should know about method_missing. [...]

    15. Duncan Beevers Wed, 08 Aug 2007 18:15:58 UTC

      Point 3, First it looks at local variables, then at instance methods.

    16. Kramer auto Pingback[...] 10 things you should know about method_missing by Max and Amy Newell from ThirdbIT 1. method_missing is a Ruby kernel method and everyone should know about it. [...]

    17. [...] performance problem with this is explained very well at thirdbIT’s post on method_missing. Every time you call method missing, you’re guaranteeing a full search through the [...]

    18. William Lindmeier's Bookmarks on Ma.gnolia Thu, 16 Aug 2007 14:31:55 UTC

      Kramer auto Pingback[...] 10 things you should know about method_missing [...]

    19. nhm tanveer hossain khan (hasan) Sat, 25 Aug 2007 14:54:46 UTC

      today i was working with this method_missing stuff, later i gave up, as because the end developer won’t get any hints about available methods.
      this feature is obviously great, similar feature found over php __set __get.

      i like active record except this part, though they have used “method_define”, but it seems odd, because i have to rapidly look on my table structure to know about the available fields on the domain object.

      anyway, thanks for nice stuff!

    20. [...] example, he emailed me the day that Ruby Inside flagged my method_missing article. Do I talk about that method_missing articleway too much, or what? I could talk about how I was the star quarterback on my high school football [...]

    21. CSC/ECE 517 Fall 2007/wiki1b 2 22 - PG_MediaWiki Sun, 30 Sep 2007 21:14:34 UTC

      Kramer auto Pingback[...] technique of metaprogramming. [edit] References 10 things you should know about method_missing.[4] [edit] Further reading Evaluation Options in Ruby. [5] IF YOU BUILD IT .. will they come [6] [...]

    22. Kramer auto Pingback[...] (rails ruby metaprogramming programming) Bookmark  [Discover] things you should know about method_missing | thirdbIT http://www.thirdbit.net/articles/2007/08/01/10-things-you-should-know-about-method_missing/ [...]

    23. [...] August I wrote a blog entry about method_missing which somehow got Reddited and then mentioned on Ruby Inside, which resulted in a huge spike in [...]

    24. metaprogramming | sehr beliebt | Mister Wong Sun, 15 Jun 2008 07:45:00 UTC

      Kramer auto Pingback[...] Bookmarks __utmSetVar(‘Tags’); metaprogramming sehr beliebt brandneu aktuell populär 10 things you should know about method_missing | thirdb … ruby metaprogramming method_missing vor >30 Tagen von janfri, 1 Benutzer, mehr Info [...]

    25. Moserware: OMeta#: Who? What? When? Where? Why? Mon, 23 Jun 2008 23:46:41 UTC

      Kramer auto Pingback[...] C# and then add 5 lines of code to make it work and then use it? What if you could add Ruby-like method_missing support in 20 lines?What if you could conceive of a new language and start experimenting with it in [...]

    26. Railstation - Artikel - Railstation Tracks 27 Mon, 21 Jul 2008 06:29:42 UTC

      Kramer auto Pingback[...] method_missing → Klik [...]

    27. Using ActiveRecord and JDBC with JRuby Sun, 27 Jul 2008 23:37:53 UTC

      [...] implements some of its funkiest magic with method_missing because ActiveRecord::Base overrides the Kernel’s method_missing [...]

    28. Kramer auto Pingback[...] been a lot of talk about method_missing lately. Let’s do a little example that leverages this freaky but neat [...]

    29. Kramer auto Pingback[...] 10 things you should know about method_missing เขียนง่ายดี และเป็นที่ที่ผมได้ลิงก์ของบทความ Jamis Buck ด้านบนครับ [...]

    30. jkahn117's Bookmarks on Delicious Wed, 24 Sep 2008 16:51:34 UTC

      Kramer auto Pingback[...] 10 things you should know about method_missing | thirdbIT SAVE [...]

    31. Kramer auto Pingback[...] You can read more about that and other uses of method_missing here. [...]

    32. [NWRUG] Re: belongs_to ate my method missing? Thu, 28 May 2009 13:16:09 UTC

      Kramer auto Pingback[...] a similar problem a while ago, this helped me sort it out: http://www.thirdbit.net/articles/2007/08/01/10-things-you-should-know-about-method_missing/ Basically you have to catch it after acriverecord is done with it. BTW we decided not to use [...]

    33. Kramer auto Pingback[...] really having a find_by_name method, thanks to Ruby’s method_missing. Now, with a few lines of code, you can write this in C# 4.0, thanks to [...]

    34. หัดเล่น method_missing « Jittat Wed, 22 Jul 2009 09:39:47 UTC

      [...] 10 things you should know about method_missing เขียนง่ายดี และเป็นที่ที่ผมได้ลิงก์ของบทความ Jamis Buck ด้านบนครับ [...]

    35. CSC/ECE 517 Fall 2007/wiki1b 2 22 - PG_MediaWiki Tue, 08 Sep 2009 19:21:54 UTC

      Kramer auto Pingback[...] module, included in the class Object. When a method does not exist, Ruby invokes method_missing. [1] [edit] Examples [edit] 1. Object [...]

    36. Kramer auto Pingback[...] example, he emailed me the day that Ruby Inside flagged my method_missing article. Do I talk about that method_missing articleway too much, or what? I could talk about how I was the star quarterback on my high school football [...]

    37. [...] 10 things you should know about method_missing [...]

    38. Blog Excilys » Les dynamic finders du pauvre Fri, 29 Jan 2010 01:11:22 UTC

      [...] les langages dynamiques1 se permettent de pratiquer la magie noire (au moyen du concept de method_missing popularisé par Ruby), je vous propose de mettre en œuvre notre meilleur vaudou pour obtenir, en [...]

    39. [...] Write comment After some looking around here is what i found and thought others would find useful as well Exception speed in Ruby Exceptions in general are really slow in ruby and should be thought of as exceptional. method_missing is not an exception but is actually a kernel method of ruby. When you invoke a method on ruby the runtime will search the entire class and module heirarchhy all the way to object, class and module and then as a last case call method_missing. Its more like it just calls this method and you can override this method at anypoint in the chain. Its definitely slower than calling a method that does exist because it has to search up the heirarchy but it is definitely faster than exceptions. Here are some other posts that i found useful during my review of this area: http://blog.hasmanythrough.com/2006/8/13/how-dynamic-finders-work http://www.thirdbit.net/articles/2007/08/01/10-things-you-should-know-about-method_missing/ [...]

    40. Kramer auto Pingback[...] 3.10 things you should know about … [...]

    41. Kramer auto Pingback[...] vote on links that you like or dislike and help decide what's popular, or submit your own! 1012Ruby : 10 things you should know about method_missing (thirdbit.net)submitted 3 years ago by linuxer4 commentssharecancelsorry, this [...]

    42. Kramer auto Pingback[...] also 10 things you should know about method missing that Max points out. Check it [...]

    Comments