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.