Filip Bartuzi
Filip Bartuzi

Reputation: 5931

How to find where method is defined when it's created via define_method

Some modules are adding methods to my class, probably via meta-programming:

class MyClass
  include SomeMetaProgrammedModule
  include SomeMetaProgrammedModule1
  include SomeMetaProgrammedModule2
  include SomeMetaProgrammedModule3
end

I want to find where a method named mysterious is defined. I can't just grep def mysterious or alias :mysterious, because mysterious is defined using

  def self.included(klass)
    klass.send(:define_method,"#{maybe_some_interpolation.gsub(...)}"
  end

How do I find where it is defined? How do I track down its source?

Upvotes: 0

Views: 122

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

If I understand the question correctly, you could use Module#instance_method and Method#owner:

module Cat
  def self.included(klass)
    klass.send(:define_method, :kitten) do
      puts "mew"
    end
  end
  def cat
    puts "meow"
  end
end
module Dog
  define_method(:dog) { puts "woof" }
end
Dog.send(:define_method, :pup) { puts "wuf" }

class C
  include Cat
  include Dog
end

Cat.instance_methods                             #=> [:cat] 
Dog.instance_methods                             #=> [:dog, :pup] 
C.instance_methods(false)                        #=> [:kitten] 
C.instance_methods & [:cat, :dog, :pup, :kitten] #=> [:kitten, :dog, :pup, :cat] 

c = C.new
c.cat                                   # "meow"
c.kitten                                # "mew"
c.dog                                   # "woof"
c.pup                                   # "wuf"   

C.instance_method(:cat).owner           #=> Cat 
C.instance_method(:kitten).owner        #=> C
C.instance_method(:dog).owner           #=> Dog 
C.instance_method(:pup).owner           #=> Dog 

Edit: I may have misunderstood what was meant by "where it is defined". Using Filip's answer, I obtain:

C.instance_method(:kitten).source_location
  #=> ["t.rb", 3]

Upvotes: 1

Filip Bartuzi
Filip Bartuzi

Reputation: 5931

You can check where method is defined with the UnboundMethod class.

.instance_method called on Class initialises a new UnboundMethod instance.

To find where mysterious is defined you can use:

  MyClass.instance_method(:mysterious).source_location

which returns:

["/Users/filip/crazy_project/SomeMetaProgrammingModule.rb", 21]

where "21" is the number of the line

Upvotes: 1

Related Questions