J
Jamis Buck
I've been wishing there were an easy to way to access Ruby's call
stack. I mean, you can use "caller", but that just gives you an array
of strings. Sometimes it would be nice to know the file, line, method
and object that invoked a particular method, without having to parse the
caller strings. The object and/or class cannot even be obtained that
way.
Is there an easy way? I wound up adding a trace function that
"listened" for call and return events, and then added them to a custom
stack. This worked very well, but is not very robust since if anyone
sets a new trace function, the "call stack" is no longer accurate.
Here's my solution:
#-------------------------------------------------
def invoker
Thread.current[:callstack] ||= []
( Thread.current[:callstack][-3] || Object )
end
set_trace_func proc { |event,file,line,obj,bind,klass|
if event == "call"
Thread.current[:callstack] ||= []
Thread.current[:callstack].push klass
elsif event == "return"
Thread.current[:callstack].pop
end
}
#-------------------------------------------------
All it tells you is the class of object that invoked the method, but it
could easily be extended. What I really want to know is: have I
reinvented the wheel? If not, perhaps something like this would be a
candidate for Rite...?
- Jamis
stack. I mean, you can use "caller", but that just gives you an array
of strings. Sometimes it would be nice to know the file, line, method
and object that invoked a particular method, without having to parse the
caller strings. The object and/or class cannot even be obtained that
way.
Is there an easy way? I wound up adding a trace function that
"listened" for call and return events, and then added them to a custom
stack. This worked very well, but is not very robust since if anyone
sets a new trace function, the "call stack" is no longer accurate.
Here's my solution:
#-------------------------------------------------
def invoker
Thread.current[:callstack] ||= []
( Thread.current[:callstack][-3] || Object )
end
set_trace_func proc { |event,file,line,obj,bind,klass|
if event == "call"
Thread.current[:callstack] ||= []
Thread.current[:callstack].push klass
elsif event == "return"
Thread.current[:callstack].pop
end
}
#-------------------------------------------------
All it tells you is the class of object that invoked the method, but it
could easily be extended. What I really want to know is: have I
reinvented the wheel? If not, perhaps something like this would be a
candidate for Rite...?
- Jamis