Is there a built-in Ruby method or a well-known library that returns the entire method lookup chain for an object? Ruby looks through a confusing sequence of classes (as discussed in this question) for instance methods that correspond with a message and calls method_missing
on the receiver if none of the classes respond to the message.
I put together the following code, but am sure it is missing certain cases or if it's 100% right. Please point out any flaws and direct me to some better code if it exists.
def method_lookup_chain(obj, result = [obj.singleton_class])
if obj.instance_of? Class
return add_modules(result) if result.last == BasicObject.singleton_class
r = result.last.superclass
method_lookup_chain(obj, result << r)
else
return result + obj.class.ancestors
end
end
def add_modules(klasses)
r = []
klasses.each_with_index do |k, i|
r << k
next if k == klasses.last
r << (k.included_modules - klasses[i+1].included_modules)
end
r.flatten
end
# EXAMPLES
module ClassMethods; end
module MoreClassMethods; end
class A
extend ClassMethods
extend MoreClassMethods
end
p method_lookup_chain(A) # => [#<Class:A>, MoreClassMethods, ClassMethods, #<Class:Object>, #<Class:BasicObject>]
module InstanceMethods; end
class Object
include InstanceMethods
end
module X; end
module Y; end
class Dog
include X
include Y
end
d = Dog.new
p method_lookup_chain(d) # => [#<Class:#<Dog:0x007fcf7d80dd20>>, Dog, Y, X, Object, InstanceMethods, Kernel, BasicObject]