Reputation: 3357
is there a way in Ruby to find the calling method name inside of a method?
For example:
class Test
def self.foo
Fooz.bar
end
end
class Fooz
def self.bar
# get Test.foo or foo
end
end
Upvotes: 188
Views: 95671
Reputation: 8403
The answer from @amitkarsale works, but private
does not do anything in a module since modules are not instantiated. Here is call_chain.rb
, rewritten according to Rubocop's suggestions:
module CallChain
def self.caller_method(depth = 1)
parse_caller(caller(depth + 1).first).last
end
def self.parse_caller(at)
return unless /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
if __FILE__ == $PROGRAM_NAME
caller = CallChain.caller_method
puts caller
end
Upvotes: 1
Reputation: 23939
Use caller_locations(1,1)[0].label
(for ruby >= 2.0)
Edit: My answer was saying to use __method__
but I was wrong, it returns the current method name.
Upvotes: 40
Reputation: 79562
In Ruby 2.0.0, you can use:
caller_locations(1,1)[0].label
It's much faster than the Ruby 1.8+ solution:
caller[0][/`([^']*)'/, 1]
Will get included in backports
when I get the time (or a pull request!).
Upvotes: 194
Reputation: 146073
puts caller[0]
or perhaps...
puts caller[0][/`.*'/][1..-2]
Upvotes: 240
Reputation: 11
In order to see the caller and callee information in any language, whether it be ruby or java or python, you would always want to look at the stack trace. In some languages, such as Rust and C++, there are options built into the compiler to turn on some sort of profiling mechanism you can view during run time. I do belive one exists for Ruby called ruby-prof.
And as mentioned above, you could look into the execution stack for ruby. This execution stack is an array containing backtrace location objects.
Essentially all you need to know about this command is as follows:
caller(start=1, length=nil) → array or nil
Upvotes: 0
Reputation: 755
Instead you can write it as library function and make a call wherever needed. The code goes as follows :
module CallChain
def self.caller_method(depth=1)
parse_caller(caller(depth+1).first).last
end
private
# Copied from ActionMailer
def self.parse_caller(at)
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
end
To trigger the above module method you need to call like this:
caller = CallChain.caller_method
Upvotes: 4
Reputation: 1671
How about
caller[0].split("`").pop.gsub("'", "")
Much cleaner imo.
Upvotes: 4