Borsunho
Borsunho

Reputation: 1157

Extract information about method receiver from stack

If we call caller method, we get something like:

prog.rb:3:in `a'
prog.rb:6:in `b'
prog.rb:9:in `c'

This is helpful for humans, but if I wanted to analyze the stack programmatically, not really, as two methods called :a may be entirely unrelated.

Is there any way/method to extract information about the receiver of the methods (like its class or object id) as well? For example:

prog.rb:3:in `Klass#a'
prog.rb:6:in `Modoole#b'
prog.rb:9:in `OtherKlass#c'

Formatting is only an example; this info might be an Array or anything.

I'm trying to emulate this with TracePoint, but forming a separate stack is a bad solution. Is there any Ruby way I missed in the docs?

Upvotes: 2

Views: 254

Answers (1)

Drenmi
Drenmi

Reputation: 8777

There's an alternative to Kernel#caller named Kernel#caller_locations, that returns an array of Thread::Backtrace::Location objects. According to the manual, these should in theory be able to give you this information through the #label method.

Returns the label of this frame.

Usually consists of method, class, module, etc names with decoration.

After trying this out however, I need to question the term usually in the docs, because it seems to only return the method name still. Unless usually means it works for you, there seems to be no way of accomplishing this as of now.

Edit:

As per comment, one case that satisfies the condition of usually is when the method call is coming from within a Class or Module body:

class A
  def trace
    puts caller_locations.first.label
  end
end

class B
  A.new.trace
end
#=> <class:B>

module C
  A.new.trace
end
#=> <module:C>

Upvotes: 1

Related Questions