Determine where a method is being called from?

Is it possible to determine if a public instance method is being called
from an object or within the class?

Thanks for your help.

On Jan 22, 2008 4:47 PM, Ben J. [email protected] wrote:

Is it possible to determine if a public instance method is being called
from an object or within the class?

I think you might need to be a little more specific with your
question. A class is also an object.

irb(main):001:0> Class.ancestors
→ [Class, Module, Object, Kernel]

I don’t think it’s possible to grab a method’s owner, because methods
can be created in any context on the fly (somebody please correct me
if I’m wrong). So, really what you are probably looking for is the
binding scope.

Just a thought,

Todd

On Jan 22, 2008 9:00 PM, Todd B. [email protected] wrote:

I don’t think it’s possible to grab a method’s owner, because methods
can be created in any context on the fly (somebody please correct me
if I’m wrong). So, really what you are probably looking for is the
binding scope.

Just a thought,

Todd

You can also do…

irb(main);001:0> class C
irb(main):002:1> def self.foo
irb(main):003:2> puts “in class”
irb(main):004:2> end
irb(main):005:1> def foo
irb(main):006:2> puts “in instance”
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> c = C.new
=> #<C:0x2dcadf0>
irb(main):010:0> C.method(:foo)
=> #<Method: C.foo>
irb(main):011:0> c.method(:foo)
=> #<Method: C#foo>

Todd

On Jan 22, 2008 4:47 PM, Ben J. [email protected] wrote:

Is it possible to determine if a public instance method is being called
from an object or within the class?

If I understood correctly, you want to look into the call stack. If
so, you must resort to an hack.

You might want to look into Kernel#caller. To see a practical example,
look into the source code for Deep End:

gem install deepend

(Disclaimer: Deep End is just an half-baked thing I released some time
ago, and it basically sucks).

Paolo Perrotta
Bologna, Italy

On Jan 23, 2:08 pm, Robert K. [email protected] wrote:

I do not see how using #caller is a hack.

This is probably in the eye of the beholder. To me, having the call
stack as a single long string and parsing it to fish out the caller
looks a bit hack-ish. It feels like #caller is supposed to be read by
a human, not by code.

I was under the impression that Ben rather wanted a static analysis,
i.e. determine code coverage. This is next to impossible with a
dynamic language such as Ruby.

Agreed.


Paolo Perrotta
Bologna, Italy

2008/1/23, Paolo Nusco P. [email protected]:

On Jan 22, 2008 4:47 PM, Ben J. [email protected] wrote:

Is it possible to determine if a public instance method is being called
from an object or within the class?

If I understood correctly, you want to look into the call stack. If
so, you must resort to an hack.

I do not see how using #caller is a hack.

I was under the impression that Ben rather wanted a static analysis,
i.e. determine code coverage. This is next to impossible with a
dynamic language such as Ruby. A simple approach would be to grep all
involved source files and look for the method’s name. But if that is
a common name or overloaded a lot you’re out of luck.

Kind regards

robert

2008/1/25, Paolo Nusco P. [email protected]:

On Jan 23, 2:08 pm, Robert K. [email protected] wrote:

I do not see how using #caller is a hack.

This is probably in the eye of the beholder. To me, having the call
stack as a single long string

???

$ ruby -e ‘p caller.class’
Array

and parsing it to fish out the caller
looks a bit hack-ish. It feels like #caller is supposed to be read by
a human, not by code.

That’s true. But then again, this is not for code execution but
rather analysis.

I was under the impression that Ben rather wanted a static analysis,
i.e. determine code coverage. This is next to impossible with a
dynamic language such as Ruby.

Agreed.

I am still waiting for Ben to chime in again.

Cheers

robert

Robert K. wrote:

I am still waiting for Ben to chime in again.

Cheers

robert

I have not chimed in because I found another solution to my problem and
I realized what I was asking was nearly impossible. I also agree that
caller seems to be used for a human to read and analyze vs using it in
your code.

On Jan 25, 11:44 am, Robert K. [email protected] wrote:

2008/1/25, Paolo NuscoPerrotta[email protected]:

To me, having the call stack as a single long string

???

Sorry, you’re right. It’s not a single long string, but it’s still one
string per call frame. My point is that you have to parse these
strings if you want to do anything other than just print them
somewhere. For example, to solve Ben’s original problem, I’d rather
have an alternate #caller that returns a chain of calling Objects, or
maybe Methods.
Again, that’s assuming he wasn’t talking about static analysis.


Paolo Perrotta
Bologna, Italy

On Jan 25, 2008 1:59 PM, Paolo Nusco P.
[email protected] wrote:

For example, to solve Ben’s original problem, I’d rather
have an alternate #caller that returns a chain of calling Objects, or
maybe Methods.

Preach on! I would love to have caller return an array of Methods, or
even ExecutionContexts, with #file, #line, and #binding methods.

On Jan 25, 2008 2:28 PM, Ben J. [email protected] wrote:

I have not chimed in because I found another solution to my problem and
I realized what I was asking was nearly impossible. I also agree that
caller seems to be used for a human to read and analyze vs using it in
your code.

For the adventurous (or just foolhardy, I’m still not sure which:)

caller.map do |line|
/([^:]+):(\d*)(?::in `([^‘]+)’)?/.match(line)[1,3]
end

will return a series of arrays: [file, line, method name] (as strings)

You know, until the format of caller’s strings changes…

Judson