Sha256: c8f9e390c67d127751e317a45b0f2a6809ae142c20dcb6383957cbbfc57cc6a8

Contents?: true

Size: 1.36 KB

Versions: 1

Compression:

Stored size: 1.36 KB

Contents

require "method_locator/version"

# MethodLocator finds all method definitions in an object instance, class, or
# module ancestor chain. This code will make more sense if you understand Ruby's
# object model and method lookup path. A great explanation of this can be found in:
# "Ruby's Eigenclasses Demystified" - http://blog.madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html

module MethodLocator
  def methods_for(meth)
    method_lookup_path.each_with_object([]) do |clazz, matches|
      matches << clazz.instance_method(meth) if instance_methods_for(clazz).include?(meth)
    end
  end

  def method_lookup_path
    module_or_regular_object? ? nonclass_lookup_path : class_lookup_path
  end

  private

  def module_or_regular_object?
    self.class == Module || !is_a?(Class)
  end

  def nonclass_lookup_path
    self.class.ancestors.unshift(singleton_class)
  end

  def class_lookup_path
    lookup_path = ancestors.grep(Class).map(&:singleton_class) + Class.ancestors
    # reverse is used here since included_modules contains all modules defined in
    # the current class as well as in its ancestors.
    lookup_path.reverse.map do |clazz|
      [clazz.included_modules, clazz]
    end.flatten.uniq.reverse
  end

  def instance_methods_for(clazz)
    clazz.instance_methods(false) + clazz.private_instance_methods(false)
  end
end

Object.send(:include, MethodLocator)

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
method_locator-0.0.1 lib/method_locator.rb