Cuando Ruby evalúa una expresión de invocación de un método (este proceso
es conocido como method lookup o method resolution), por ejemplo
o.m
ocurren los siguientes pasos:
o
la existencia de un método m
o
por un método m
o
.
Si la clase incluye mas de un módulo se buscan en orden inverso al orden en el que fueron incluídos
El módulo Kernel provee una implementación por defecto de
method_missing
por lo que queda garantizado
el éxito de esta segunda pasada.
Let’s consider a concrete example of this algorithm. Suppose we have the following code:
message = "hello" message.worldWe want to invoke a method named
world
on the String instance "hello"
.
[1] pry(main)> String.ancestors => [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]Name resolution proceeds as follows:
String
class. There is no instance method named world
.
Comparable
module of the String
class for an instance method named world
.
String
, which is Object
. The Object
class does not define a method named world
, either.
Object
.
The world
method is not found here either,
so we now switch to looking for a method named method_missing
.
method_missing
in each of the spots above:
String
object,
String
class,
Comparable
module,
Object
class, and the Kernel module
method_missing
we find is in the Kernel module, so this
is the method we invoke. What it does is raise an exception:
NoMethodError: undefined method `world' for "hello":String
In typical implementations, however, successful method lookups will be cached so that subsequent lookups of the same name (with no intervening method definitions) will be very quick.
Casiano Rodriguez León 2015-01-07