185

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
Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
jrichardlai
  • 3,317
  • 4
  • 21
  • 24
  • 1
    possible duplicate of [Get the name of the currently executing method in Ruby](http://stackoverflow.com/questions/199527/get-the-name-of-the-currently-executing-method-in-ruby) – Darshan Rivka Whittle Feb 25 '13 at 08:37
  • get calling object: http://stackoverflow.com/questions/2703136/any-way-to-determine-which-object-called-a-method – Ciro Santilli OurBigBook.com Sep 10 '14 at 21:54
  • 5
    Not a duplicate of "Get the name of the currently executed method in Ruby." This question asks for the name of the calling method, not the name of the current method. – Wayne Conrad Sep 26 '19 at 02:18

8 Answers8

237
puts caller[0]

or perhaps...

puts caller[0][/`.*'/][1..-2]
Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • 5
    Yes, see Kernel#caller, aka http://www.ruby-doc.org/core-1.8.7/classes/Kernel.html#M001073 – DigitalRoss Feb 24 '11 at 04:29
  • 11
    That gives the name of the calling method, but it doesn't give any indication to which module or class the method belongs to. Is that possible? – thomthom Nov 10 '12 at 16:39
  • 1
    @thomthom Yes that is possible you can call self.class.name to see the class name – Thorin Apr 27 '17 at 06:25
  • Excellent use of regex as a string index! Can also use `caller[0][/\`(.*)'/,1]` – aks Dec 23 '17 at 05:36
  • 2
    This doesn't seem to work in Rails 5.2.1. In Rails controller this returns `"block in make_lambda"`. I guess this is for Ruby only. – dcangulo Nov 14 '18 at 04:59
188

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!).

Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
  • It's worth noting that this is not available in Rubinius. – Max May 04 '14 at 22:29
  • 1
    if ur using pry, you have to ignore the pry stacktrace it seems...there doesn't seem to be a default solution for that. – dtc Sep 24 '15 at 06:18
  • 9
    Now it seems to be `caller_locations[0].label` on Ruby 2.2.0 else you always have `send_action` result – brcebn Feb 16 '16 at 15:25
  • 2
    how can we get only call app method and ignore frameworks call ? – Matrix Sep 27 '17 at 09:31
40

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.

Dave Powers
  • 2,051
  • 2
  • 30
  • 34
Dorian
  • 22,759
  • 8
  • 120
  • 116
21

I use

caller[0][/`([^']*)'/, 1]
Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
Héctor García
  • 738
  • 4
  • 9
  • 4
    What's the advantage of this over DigitalRoss' approach? – Andrew Grimm Jun 19 '12 at 06:36
  • 2
    Cleaner and more precise. Rather than doing the search, then using an array method to split of unwanted characters based on position (which could be incorrect). – New Alexandria Jul 09 '12 at 21:12
  • 2
    Why not simply use caller[0][/`(.*)'/, 1] ? I'm not a guru about regular expressions, but it seems to work. – collimarco Jul 18 '12 at 09:56
  • 7
    @collimarco As long as the String doesn't contain a `'` beyond the one you're looking for (and I assume it can't), the result will be the same, sure. However, `[^']*` will perform better as the regex engine will stop trying to match that part the expression the moment it reaches a `'` (your version will go to the end, then backtrack because it didn't find a `'` at the end). The difference is pretty negligible in this case of course, but it's a good habit to avoid `.` in regexes where possible. – Vala Nov 14 '12 at 13:11
4

How about

caller[0].split("`").pop.gsub("'", "")

Much cleaner imo.

thrice801
  • 1,671
  • 5
  • 23
  • 31
3

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

code reference from

Dorian
  • 22,759
  • 8
  • 120
  • 116
amit karsale
  • 740
  • 5
  • 14
  • 1
    A link to a potential solution is always welcome, but please [add context around the link](http://meta.stackoverflow.com/a/8259/169503) so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. Take into account that being _barely more than a link to an external site_ is a possible reason as to [Why and how are some answers deleted?](http://stackoverflow.com/help/deleted-answers). – Xavi López Apr 29 '14 at 12:16
  • @XaviLópez have updated the answer, plz rectify if am doing wrong or somthing mistaken...thnx for the kind suggestion :) – amit karsale May 02 '14 at 05:08
  • 1
    Thanks for improving your answer. Unfortunately, I don't have enough knowledge about Ruby to be able to properly comment about this post, but the answer looks alright now. I've removed my downvote. Best luck :-) – Xavi López May 02 '14 at 07:35
0

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

0

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
Mike Slinn
  • 7,705
  • 5
  • 51
  • 85