Hack of the day: Find all classes that define a method with a given name

Updated . Posted . Visible to the public.

If (for some reason that you don't want to ask yourself) you need to know all classes that define a method with a given name, you can do it like this:

def classes_defining_method(method_name)
  method_name = method_name.to_sym
  ObjectSpace.each_object(Module).select do |mod|
    instance_methods = mod.instance_methods.map(&:to_sym) # strings in old Rubies, symbols in new Rubies
    (instance_methods & [method_name]).any? && mod.instance_method(method_name).owner == mod
  end
end

So, when we want to know all classes that define a to_s on a plain IRB, this is what the result looks like:

>> classes_defining_method(:to_s)
=> [IRB::Context, UnboundMethod, Method, Proc, Process::Status, Time, Range, MatchData, Regexp, Struct, Hash, Array, Bignum, Float, Fixnum, NameError, Exception, String, FalseClass, TrueClass, Symbol, NilClass, Kernel, Module] 

All those classes implement their own to_s, note how we don't see any subclasses that inherit to_s from a parent. This is what our second condition in the code above does.

You can now go ahead and monkey-patch the hell out of all those classes implementing the method you are looking for.

Arne Hartherz
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2012-09-07 08:27)