Coming from a background in compiled languages, the idea of metaprogramming is fascinating to me. In the world of C, writing and running programs are distinct actions. At runtime, a program cannot be altered. However, in Ruby, the actual code can be modified while it is executing. To those who only know Ruby or similar interpreted languages, it may not seem like a big deal, but to me, it’s the coolest thing ever. At a hackathon I went to once a guy wrote a self-modifying program in Python, and I thought it was black magic. I didn’t realize it was just a gift that comes with the language, and you didn’t have to do any serious hacking to dynamically alter the code.
Let’s just look at eval. Maybe this isn’t so exciting:
1
|
|
But then, consider this ditty:
1 2 3 4 5 6 7 8 9 |
|
That’s pretty cool. You just wrote a little program on the fly. What else can you do? You can write a program that writes programs.
Yeah dawg. I’m for real. This is all of the code it takes (Adapted from The Book of Ruby by Huw Collingbourne):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
If you run this, you kind of have a REPL, but it’s significantly dumber than IRB:
1 2 3 4 5 6 7 8 9 |
|
Cool. So what other applications does metaprogramming have in Ruby besides writing REPL’s? As it turns out, it’s one of my favorite things I’ve learned about in Ruby thus far: ActiveRecord. When you define associations between models, whether it be belongs_to or has_many or anything else, the methods that you get for free are all generated on the fly. It does this using eigen or singleton classes. This is having the ability to define methods for specific instances of a class, after the class has already been defined. For example, say you define a class like so:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Then you would instantiate it as
1
|
|
But say you got the newer model, which knows how to unclog itself. Then you could do something like
1 2 3 4 5 6 7 |
|
There’s also this other fancy syntax you can use:
1 2 3 4 5 6 |
|
It looks mysterious, but it’s doing the same thing, I swear.
You can actually define singleton methods for classes as well, and they’re simply called class methods. You can do this in a number of ways:
1 2 3 4 5 |
|
This is the syntax we’re familiar with. But there’s more:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
ActiveRecord creates new singleton methods for instances and classes when you define associations. It may seem like magic, but that magic is just metaprogramming.