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.

Math and Programming

Posted by amy on May 01, 2007

Sometimes Max worries that he must not be naturally technical because he always hated his math classes, and his brother and his father are both brilliant math people. ( I have a powerful memory of sitting in the garden on a brilliantly sunny day, idly reading a book, while my father-in-law sat next to me and worked through some multivariable calculus problems for the fun of it.) Max is not as bad at math as he insists on believing, but I also don’t think math really has much to do with run-of-the-mill software development. Sure, it’s helpful to know when a problem you’re working on can’t be solved by a brute force algorithm because it’s mathematically ridiculous, but not everyone is writing algorithms.

Anyway, here’s my new favorite person (well, Al Gore still comes first), _why, on his new supercool programming learning tool for kids, and why he doesn’t start his programming lessons with math.

Obviously there is a ton of math in a ton of different kinds of programming. But you can be a great, successful software developer and never get deeper into math than knowing that floats don’t come out of the database exactly the same as they went in. (No, we don’t quite get why either.. But we know not to use floats in situations where you’d like things to add up the same every time you add them. And we know it without ever having written our own compilers. Does this mean we aren’t hard-core? Then so be it. What’s wrong with a little airbrushing, anyway?

Why We’re Learning Ruby on Rails

Posted by amy on April 28, 2007

Why are we learning Ruby on Rails? Let’s ask _why.

_why: his very existence, his poignant guide, his utter bizzare-itude. His hackety-hack project. Having come across _why, how could we turn down his invitation to learn ruby?

Now, apparently, some people have a very different reaction to _why. Some people think _why is what’s wrong with Ruby. _why thinks that is funny:

The problem here is: the author of the article is trying to do academics, to gain knowledge, to build a career. And my cartoons and stories have patronized him, belittled him, by treating him as if he wasn’t a real professional. This is a terrible breach of conduct. He has accolades innumerable. He has done no small deed. His peers are all gathered around him, wishing him the best and swelling with nothing but respect and esteem for him. NOW WHAT IS THIS CARTOON BOOK DOING HERE??Programming is for world commerce. It is like agriculture or fossil fuels. It is lot a like baling hay. I’ll give you an example: You wouldn’t write a cartoon book with a plot and running narrative just to show a guy how to bale hay! That would frustrate the guy! He would throw that book in the pig’s pen! He just wants to get straight to the nitty-gritty and, for once in his life, just bale hay, straightway!

It’s not just _why, of course. We’d be pretty pathetic if we decided to devote lots of time and effort to a new programming language just because of a cartoon book. I mean, we have to have serious, professional, career-oriented reasons for learning ruby. And Rails, of course. Not that ruby doesn’t exist without rails. Ruby doesn’t need rails to justify its existence. Matz is not DHH, after all. Matz came first. And then, presumably, came _why. 37signals was later.

Learning a new language takes a lot of effort. I’m trying, lackadaisically, to learn french, since Max speaks French and Ari is learning it, primarily by having Barbapapa books read to him over and over again. And we have a bunch of french friends, and it’s really depressing at dinner parties how I’m never quite sure what people are saying. It’s hard, though, and what would make it even harder is if I didn’t like french culture.

Learning a new programming language is a lot like learning a new human language. It comes with a culture. You have to like the culture to want to put in the effort.

So, you know, we have a friend who’s making fistfuls of money because he’s a crack ActionScript 3 developer. Every time we turn around he gets another promotion, and another raise, and he says the world is desperate for ActionScript 3 programmers. We hear this from other people we know, people with jobs. We don’t have jobs right now. Well, Max consults. And I consult to Max on his consulting. But not a 401(k) plan between us. So I keep thinking “fine, let’s learn actionscript”. Except that it’s like trying to have sex with someone you’re just not attracted to. close your eyes and think of Ruby. Oh wait, I swore I wasn’t going to mention sex on this blog. Note to self: blog is for professional presence. Sex: not professional. Well, except for sex workers, for whom sex is professional. But I’m not a sex worker. Am I calling my actionscript friend a sex worker? Not sure. We love you, actionscript friend! And I will be quiet now.

What I’m trying to say here is that we like the Ruby culture. No doubt we’ve come to it too late, and in about two weeks it won’t be cool anymore and people will be all ‘ewww, you’re a ruby person? Rails is soooo 2006. Didn’t you know that Twitter proved it wasn’t scalable? And it’s s…l….o….w.” But that’s okay. When I first started programming, it was because I fell in love with a heapsort. Heapsort had been around for a pretty long time then, but I felt like I was the first person who’d discovered how cool it was. (Kind of like teenagers and sex. Oh wait, there I go again. Shut. Up. Amy.)

Anyway, here we are, immersing ourselves in Ruby culture. We’re gonna go to a Boston Ruby Meeting, where Hackety Hack will be demo-d. I’m subscribed to all these Ruby blogs. We’re studying the idioms and learning about the people and the projects in the Ruby world. And, of course, learning the language. We’d like to contribute to the conversation at the Ruby table.

As for Rails, we’re learning it because we need to write our own web-based to-do list. I’m joking, I promise. Rails comes along with Ruby because most of our experience in IT has been web-related. So we’re leveraging our experience with web technologies and increasing our skillset with Rails, an agile Ruby-based framework that dramatically increases the speed and ease of web app development. See: serious and professional. Ignore the cartoon foxes and sex workers.