I got this question from this discussion. A method call like object.m does not always mean the class of "object" has a "m" method, just like the find method to a Array object is not directly originated from Array object, but from the mixed-in Enumerable module. My question is, given a method, how can we determine the class from which the method originated?
-
maybe you use caller() to give you the backtrace see:
-
I'm thinking something like this could work
def print_ancestor_definitions(cl,method) ancestors = cl.ancestors p ancestors.join(' < ') #Print heirarchy p "Searching..." ancestors.each do |c| if c.instance_methods.include? method p "#{c} defines #{method} as an instance method!" elsif c.singleton_methods.include? method p "#{c} defines #{method} as a singleton method" else p "#{c} doesn't define #{method}" end end end print_ancestor_definitions(Array,'find') # >> "Array < Enumerable < Object < Kernel" # >> "Searching..." # >> "Array defines find as an instance method!" # >> "Enumerable defines find as an instance method!" # >> "Object doesn't define find" # >> "Kernel doesn't define find"I suppose the last one to have the method is the one who defines it?
-
I'm not sure we can precisely find where a method come from, when you include a mixin, all the methods become part of your class as if you did put them there. See answer from dylanfm for an approx.
Toby Hede : method.inspect will tell you if a method is attached to a Mixin -
Any class/object method is an object in Ruby, and has some methods of it's own.
So you can do this:
[].method(:count).inspect => "#<Method: Array#count>" [].method(:detect).inspect => "#<Method: Array(Enumerable)#detect>"Quick bit of RegEx and you're done.
dylanfm : Sweet, thats great -
tobyhede's answer is awesome, but I just did a bit of digging in
irband there's no need to slice up the output of#inspect. TheMethodclass>> Object.new.method(:inspect) => #<Method: Object(Kernel)#inspect>has some useful methods of its own:
>> Object.new.method(:inspect).methods - Object.methods => ["owner", "call", "to_proc", "unbind", "arity", "receiver", "[]"]In particular the
#ownermethod, which returns the owner as a proper object:>> [].method(:count).owner => Array >> [].method(:detect).owner => Enumerablebjeanes : awesome find, this will definitely come in handy.Toby Hede : of course! that's very cool.
0 comments:
Post a Comment