24 | Chapter 1: Foundational Techniques
def method_missing(method_id, *args, &block)
...
end
There are several drawbacks to usingmethod_missing:
- It is slower than conventional method lookup. Simple tests indicate that method
dispatch withmethod_missingis at least two to three times as expensive in time
as conventional dispatch. - Since the methods being called never actually exist—they are just intercepted at
the last step of the method lookup process—they cannot be documented or
introspected as conventional methods can. - Because all dynamic methods must go through themethod_missingmethod, the
body of that method can become quite large if there are many different aspects
of the code that need to add methods dynamically. - Usingmethod_missingrestricts compatibility with future versions of an API.
Once you rely onmethod_missingto do something interesting with undefined
methods, introducing new methods in a future API version can break your users’
expectations.
A good alternative is the approach taken by ActiveRecord’sgenerate_read_methods
feature. Rather than waiting formethod_missingto intercept the calls, ActiveRecord
generates an implementation for the attribute setter and reader methods so that they
can be called via conventional method dispatch.
This is a powerful method in general, and the dynamic nature of Ruby makes it pos-
sible to write methods that replace themselves with optimized versions of them-
selves when they are first called. This is used in Rails routing, which needs to be very
fast; we will see that in action later in this chapter.
Generative Programming: Writing Code On-the-Fly
One powerful technique that encompasses some of the others is generative
programming—code that writes code.
This technique can manifest in the simplest ways, such as writing a shell script to
automate some tedious part of programming. For example, you may want to popu-
late your test fixtures with a sample project for each user:
brad_project:
id: 1
owner_id: 1
billing_status_id: 12
john_project:
id: 2
owner_id: 2
billing_status_id: 4
...