I've read stackoverflow posts on this topic as well as several articles which include A Primer on Ruby Method Lookup, What is the method lookup path in Ruby. In addition, I checked out the object model chapter in Ruby Metaprogramming 2, asked in a few chat rooms, and made this reddit thread. Short of learning C, I've done what I can to figure this out.
As described by the resources above, these 6 places are checked (in order) during method lookup on a receiving object like fido_instance:
- singleton class of fido_instance
- IClass (from an extended module)
- IClass (from a prepended module)
- class
- IClass (from an included module)
- superclass (if method isn't found here, repeat steps 4-6)
Obviously, the diagram is incomplete, and all of these singleton classes might not have been created in the real world. Still, those 6 steps leave a lot to be desired, and don't cover the following scenario. If there were no extended/prepended IClass above the singleton class of fido_instance
, then there's no explanation of whether step 4 is executed on the singleton class of fido_instance
. I have to assume not since the whole method lookup would short circuit.
If I were to guess a set of steps that could explain ruby's method lookup behavior, it might look like:
- check
fido_instance.class
for the method. (obviously, ruby isn't going to use its own #class method to do the method lookup, but it conveys the logic of the process) - check
fido_instance.class.superclass
for the method. Keep adding.superclass
and checking for the method until no superclasses are left. (again, ruby isn't going to use its own #superclass method) - method wasn't found. Start at step 1, looking for #method_missing this time.
I also recall reading that there's a separate method lookup process if the receiving object is a class, but I can't recall where.
So what's the correct, detailed explanation that doesn't involve knowing C?