Method invocation introspection with Kernel#caller and friends
Continuing the theme of introspection, Ruby also provides the ability to inspect the call stack and get information about the caller of a method. This can be done using the caller method:
def who_called_me
caller
end
def caller_one
who_called_me
end
def caller_two
caller_one
end
def caller_three
caller_two
end
puts caller_one
# scratchpad.rb:6:in 'Object#caller_one'
# scratchpad.rb:18:in '<main>'
puts caller_two
# scratchpad.rb:10:in 'Object#caller_two'
# scratchpad.rb:6:in 'Object#caller_one'
# scratchpad.rb:18:in '<main>'
puts caller_three
# scratchpad.rb:14:in 'Object#caller_three'
# scratchpad.rb:10:in 'Object#caller_two'
# scratchpad.rb:6:in 'Object#caller_one'
# scratchpad.rb:18:in '<main>'
A sibling method to caller is caller_locations, which returns an array of Thread::Backtrace::Location objects instead of strings, providing a more structured way to access the caller information.
Both methods also accept an optional argument to specify which indices of the stack to return.
So what do we use this for?
It can generally be useful for debugging and logging purposes, but a concrete use-case could be a helpful deprecation warning:
def deprecated_method
warn "deprecated_method is deprecated and will be removed in the future. Called from: #{caller_locations(1..1).first}"
# method implementation...
end
Finally, there is callee which returns the name by which the current method was invoked. This can be helpful in cases where a method is aliased or when using method_missing to handle multiple method names with the same implementation.
History
Kernel#caller has been available in Ruby since its inception.
#caller_locations and #__callee__ were added in Ruby 2.0, released in 2013.