Ruby’s Ancestors Method

The ancestors method returns an ordered list of classes and modules that corresponds with the method lookup sequence. In the following example, instances of the class A will search for methods in A, Object, Kernel, and BasicObject before calling A#method_missing.

class A; end
A.ancestors # => [A, Object, Kernel, BasicObject]

Before Ruby 2.1, the ancestors method behaved oddly when the receiver was a singleton_class. The ancestors method is now fixed and the interesting method lookup process for singleton methods is on full display.

class A; end
A.singleton_class.ancestors # => [#<Class:A>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]

When messages are sent to to A, Ruby looks for corresponding methods in A’s singleton class, Object’s singleton class, and BasicObject’s singleton_class. BasicObject.singleton_class.superclass == Class, so the method lookup process continues all the way up to BasicObject, just like regular instance methods. This surprisingly causes A to respond to instance methods defined in Class, Module, Object, and BasicObject.

class A; end
class Module
  def hi; 'hi'; end
end
A.hi # => 'hi'

As 7stud mentioned on StackOverflow, “the lookup path of any method called on a class has to include Class somewhere because ALL classes inherit from Class”.

In any case, Ruby 2.1’s ancestors method is a major improvement because it gives accurate results when the receiver is a singleton class.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s