Rails does a lot for you, including dynamically generating methods like
find_by_[attribute], for every attribute your model has. I had always assumed that rails generated the methods when you start it up. While it’s true that rails generates the methods for you, it’s the where and the how that’s interesting.
When you send an object a method in Ruby, it first looks for that method in the object itself, then it looks up the inheritance chain. What happens if it reaches the
Object class and still can’t find the method? It calls
method_missing, which is defined on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
So how can we take advantage of this? By overriding
method_missing, we can actually create dynamic methods on the fly. So before, we were adding the
[emotion]_sound manually, now we can add them dynamically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Now, as long as our Animal class has a particular emotion, we can call
[emotion]_sound without defining it ourselves.
Now we need to be able to tell that our Animal class has a method called
confused_sound but not
angry_sound. The way we do that is by overriding the
respond_to_missing? has the advantage in that it allows us to use
whiskers.method , such as
1 2 3 4 5 6 7 8 9 10
These are called ghost methods because if we call
confused_sound won’t show up.
Rails and Ghost methods
Coming back to Rails, we can see how
method_missing can be used to dynamically define finders such as
find_by_age, etc. However, going through
method_missing every time can be a little slow.
As a result, Rails gets even more meta and actually defines the finders as methods on the Model the first time they are called. This way, they are essentially cached, and the next call will no longer go through
Stay tuned for a future post on other details of metaprogramming in Rails with