Работаем с ним как с обычным caller, но на выходе получаем удобноваримые результаты:
# extensions.rb
def fcallers(start=1)
chain = caller start + 1
(chain || []).map { |it|
if it[/(.*):(\d+)(?::in `(.+)')?/]
{
:file => Regexp.last_match[1],
:line => Regexp.last_match[2].to_i,
:method => Regexp.last_match[3]
}
else
raise 'Undefined format of caller'
end
}
end
# foo.rb
require 'extensions'
def foobar
p fcallers
end
# bar.rb
require 'foo'
def barfoo() foobar end
barfoo
Output:
[{:method=>"barfoo", :file=>"/Users/brainopia/ruby_apps/extensions/bar.rb", :line=>3}, {:method=>nil, :file=>"/Users/brainopia/ruby_apps/extensions/bar.rb", :line=>5}]
Но обычно при работе с caller нам достаточно проследить один вызов и вся цепочка нам не нужна, поэтому пишем еще маленькую обертку:
def fcaller(start=1)
fcallers(start+1).first
end