Get caller of method

Hi,

Does there exist a method to get the object or type of object that calls this method?

for example:

class Foo
  do
end
class Bar
  do
end

do
  if caller.kind_of?(Foo)
    puts "Foo"
  elsif caller.kind_of?(Bar)
    puts "Bar"
  end
end

Thanks!

Thomas

I'm assuming you meant something like:

   class Foo
     def do_stuff
       do_something
     end
   end
   class Bar
     def do_stuff
       do_something
     end
   end

   def do_something
     if caller.kind_of?(Foo)
       puts "Foo"
     elsif caller.kind_of?(Bar)
       puts "Bar"
     end
   end

since "do" is a reserved word in Ruby.

In this case you can do the following:

def do_something(b = binding)
   case eval("self", b)
     when Foo then "Called by Foo"
     when Bar then "Bar told me to do it"
   end
end

Then you get:
   Foo.new.do_stuff
   => "Called by Foo"

   Bar.new.do_stuff
   => "Bar told me to do it"

Note however that it would be possible for a method to "lie" and pass in another binding when the method is called. And also it won't work in this case:

   class Foo
     do_something
   end

because the calling object is an instance of Class, but you could use:

   def do_something(b = binding)
     case eval("self.name", b)
       when "Foo" then "Called when building Foo"
       when "Bar" then "Bar's creator told me to do it"
     end
   end

and you get:
   class Foo
     do_something
   end
   => "Called when building Foo"

Maybe there is a better way to do this but it's a starter for 10.

Ashley

···

On Jul 23, 2006, at 8:06 pm, thomas coopman wrote:

Hi,

Does there exist a method to get the object or type of object that calls this method?

for example:

class Foo
  do
end
class Bar
  do
end

do
  if caller.kind_of?(Foo)
    puts "Foo"
  elsif caller.kind_of?(Bar)
    puts "Bar"
  end
end

Thanks!

Although others may suggest fancier techniques, I suggest a very simple approach -- just have the caller identify itself. For example:

#! /usr/bin/ruby -w

class Foo

    def connect
       @server = Server.new
       @server.connect(self)
    end

end

class Bar < Foo
end

class Server

    def connect(sender)
       @client = sender
       puts @client.class.name
    end

end

Foo.new.connect
Bar.new.connect

# --- end of code ----

Regards, Morton

···

On Jul 23, 2006, at 3:06 PM, thomas coopman wrote:

Hi,

Does there exist a method to get the object or type of object that calls this method?

for example:

class Foo
  do
end
class Bar
  do
end

do
  if caller.kind_of?(Foo)
    puts "Foo"
  elsif caller.kind_of?(Bar)
    puts "Bar"
  end
end

thomas coopman wrote:

Hi,

Does there exist a method to get the object or type of object that calls this method?

The same question was asked just a few days ago. It's generally a good
rule of thumb to do a search first before asking --just FYI.

Anyhow, the #binding turns the current context/closure into an object
that you can pass around an reuse. You can evaluate any code against a
binding via:

  Kernel.eval( "code here", aBinding)

If you pass a block, btw, you can't get it's binding and via it the
caller.

T.

Thanks for the quick answer, I didn't think about do.

I think I understand your explanation but I don't completly understand what
eval does.
I checked the documentation but I still don't really get it, could you
explain it?

Thomas

···

On 7/23/06, Ashley Moran <work@ashleymoran.me.uk> wrote:

On Jul 23, 2006, at 8:06 pm, thomas coopman wrote:

> Hi,
>
> Does there exist a method to get the object or type of object that
> calls this method?
>
> for example:
>
> class Foo
> do
> end
> class Bar
> do
> end
>
> do
> if caller.kind_of?(Foo)
> puts "Foo"
> elsif caller.kind_of?(Bar)
> puts "Bar"
> end
> end
>
> Thanks!
>

Thomas

I'm assuming you meant something like:

   class Foo
     def do_stuff
       do_something
     end
   end
   class Bar
     def do_stuff
       do_something
     end
   end

   def do_something
     if caller.kind_of?(Foo)
       puts "Foo"
     elsif caller.kind_of?(Bar)
       puts "Bar"
     end
   end

since "do" is a reserved word in Ruby.

In this case you can do the following:

def do_something(b = binding)
   case eval("self", b)
     when Foo then "Called by Foo"
     when Bar then "Bar told me to do it"
   end
end

Then you get:
   Foo.new.do_stuff
   => "Called by Foo"

   Bar.new.do_stuff
   => "Bar told me to do it"

Note however that it would be possible for a method to "lie" and pass
in another binding when the method is called. And also it won't work
in this case:

   class Foo
     do_something
   end

because the calling object is an instance of Class, but you could use:

   def do_something(b = binding)
     case eval("self.name", b)
       when "Foo" then "Called when building Foo"
       when "Bar" then "Bar's creator told me to do it"
     end
   end

and you get:
   class Foo
     do_something
   end
   => "Called when building Foo"

Maybe there is a better way to do this but it's a starter for 10.

Ashley

--
Thomas Coopman
Thomas.coopman@gmail.com

I didn't know about this b=binding trick.
Quiet interesting... ;]

Thanks,

gegroet,
Erik V.

Hi,

It's not clear to me what you're doing with the binding. You don't
need it for your example and it won't work the way you seem to think.

The example below shows you don't need to do anything fancy to get hold of self:

def do_something
  case self
  when Foo
    puts "Called by Foo"
  when Bar
    puts "Bar told me to do it"
  when Class
    case self.name
    when "Foo"
      puts "Class Foo did it"
    end
  end
end

class Foo
  def do_stuff
    do_something
  end
end
class Bar
  def do_stuff
    do_something
  end
end

Foo.new.do_stuff
Bar.new.do_stuff
class Foo
  do_something
end
__END__
Called by Foo
Bar told me to do it
Class Foo did it

The next example shows that the binding you create in the argument
list is local to the method definition, not to the caller (which I
think is what you're thinking).

def test_binding(str, b = binding)
  x = 2
  p eval(str, b)
end

class Foo
  x = 1
  test_binding "x", binding
  test_binding "x"
end
__END__
1
2

Please feel free to correct me if I've gotten hold of the wrong end of
the stick (it has been known :wink:

Regards,
Sean

···

On 7/23/06, Ashley Moran <work@ashleymoran.me.uk> wrote:

On Jul 23, 2006, at 8:06 pm, thomas coopman wrote:

> Hi,
>
> Does there exist a method to get the object or type of object that
> calls this method?
>
> for example:
>
> class Foo
> do
> end
> class Bar
> do
> end
>
> do
> if caller.kind_of?(Foo)
> puts "Foo"
> elsif caller.kind_of?(Bar)
> puts "Bar"
> end
> end
>
> Thanks!
>

Thomas

I'm assuming you meant something like:

   class Foo
     def do_stuff
       do_something
     end
   end
   class Bar
     def do_stuff
       do_something
     end
   end

   def do_something
     if caller.kind_of?(Foo)
       puts "Foo"
     elsif caller.kind_of?(Bar)
       puts "Bar"
     end
   end

since "do" is a reserved word in Ruby.

In this case you can do the following:

def do_something(b = binding)
   case eval("self", b)
     when Foo then "Called by Foo"
     when Bar then "Bar told me to do it"
   end
end

Then you get:
   Foo.new.do_stuff
   => "Called by Foo"

   Bar.new.do_stuff
   => "Bar told me to do it"

Note however that it would be possible for a method to "lie" and pass
in another binding when the method is called. And also it won't work
in this case:

   class Foo
     do_something
   end

because the calling object is an instance of Class, but you could use:

   def do_something(b = binding)
     case eval("self.name", b)
       when "Foo" then "Called when building Foo"
       when "Bar" then "Bar's creator told me to do it"
     end
   end

and you get:
   class Foo
     do_something
   end
   => "Called when building Foo"

Maybe there is a better way to do this but it's a starter for 10.

Ashley

Hi,

It's not clear to me what you're doing with the binding. You don't
need it for your example and it won't work the way you seem to think.

The example below shows you don't need to do anything fancy to get hold of
self:

< SNIP bit that shows me up as clueless :slight_smile: >

Please feel free to correct me if I've gotten hold of the wrong end of
the stick (it has been known :wink:

Regards,
Sean

Hi Sean

Seems I misunderstood the scope of "self". I assumed that since a Food
instance was calling a method in another object (the application instance of
Object) that self would be the global "main" object. IE:

irb(main):003:0> class Foo
irb(main):004:1> def test
irb(main):005:2> global_test
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> def global_test
irb(main):009:1> puts self.class
irb(main):010:1> puts self.inspect
irb(main):011:1> end
=> nil
irb(main):012:0> Foo.new.test

I expected:
Object
main

But you actually get:
Foo
#<Foo:0x8143b18>

I have to say, I don't understand this behaviour. Maybe I am missing
something. I assume it is to do with class nesting?

Ashley

···

On Sunday 23 July 2006 22:55, Sean O'Halpin wrote:

--
"If you do it the stupid way, you will have to do it again"
  - Gregory Chudnovsky

> Hi,
>
> It's not clear to me what you're doing with the binding. You don't
> need it for your example and it won't work the way you seem to think.
>
> The example below shows you don't need to do anything fancy to get hold of
> self:
>

< SNIP bit that shows me up as clueless :slight_smile: >

Don't take it so hard - we're all still learning :slight_smile:

>
> Please feel free to correct me if I've gotten hold of the wrong end of
> the stick (it has been known :wink:
>
> Regards,
> Sean

Hi Sean

Seems I misunderstood the scope of "self". I assumed that since a Food
instance was calling a method in another object (the application instance of
Object) that self would be the global "main" object. IE:

irb(main):003:0> class Foo
irb(main):004:1> def test
irb(main):005:2> global_test
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> def global_test
irb(main):009:1> puts self.class
irb(main):010:1> puts self.inspect
irb(main):011:1> end
=> nil
irb(main):012:0> Foo.new.test

I expected:
Object
main

But you actually get:
Foo
#<Foo:0x8143b18>

I have to say, I don't understand this behaviour. Maybe I am missing
something. I assume it is to do with class nesting?

Ashley

self is dynamically scoped to always return the current receiver.

It is not lexically scoped, i.e. it does not depend on ~where~ the
definition is but on how it is called.

Look at this example:

@name = "I'm main"
def name
  @name
end

def m1
  p [self, name]
  @name = name.reverse
end

m1 # called in scope of self == main

class Foo
  attr_accessor :name
  def initialize(name)
    @name = name
  end
  def name
    @name
  end
  def m2
    m1 # called in scope of self == instance of Foo
  end
end

f = Foo.new("I'm foo")
f.m2
__END__
[#<Object:0x27f91f8 @name="I'm main">, "I'm main"]
[#<Foo:0x2867598 @name="I'm foo">, "I'm foo"]
[#<Foo:0x2867598 @name="oof m'I">, "oof m'I"]

HTH

Regards,
Sean

···

On 7/26/06, Ashley Moran <work@ashleymoran.me.uk> wrote:

On Sunday 23 July 2006 22:55, Sean O'Halpin wrote:

Sean O'Halpin schrieb:

< SNIP bit that shows me up as clueless :slight_smile: >

Don't take it so hard - we're all still learning :slight_smile:

And some actually enjoy it :slight_smile:

Seems I misunderstood the scope of "self". I assumed that since a Food
instance was calling a method in another object (the application instance of Object) that self would be the global "main" object. IE:

irb(main):003:0> class Foo
irb(main):004:1> def test
irb(main):005:2> global_test
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> def global_test
irb(main):009:1> puts self.class
irb(main):010:1> puts self.inspect
irb(main):011:1> end
=> nil
irb(main):012:0> Foo.new.test

Ashley, in addition to Sean's answer, remember that the methods you define at the toplevel, outside of any class, aren't singleton methods of the "main" object. Instead, they are private methods of class Object. Since every class is a subclass of Object, they inherit these "toplevel" methods. In your method Foo#test, you're actually calling

   self.global_test

so you're not calling a method of a different object. The following is based on your code above:

   f = Foo.new

   f.test
   # => #<Foo:0x2b84b80>

   f.global_test rescue puts $!
   # => private method `global_test' called for #<Foo:0x2b84b80>

You see from the error message, that global_test is a private method, and I'm calling it for my Foo instance. Now I'm going to make the method public:

   class Object
     public :global_test
   end

   f.global_test
   # => #<Foo:0x2b84b80>

Regards,
Pit

···

On 7/26/06, Ashley Moran <work@ashleymoran.me.uk> wrote:

Thanks for the replies people

···

On Wednesday 26 July 2006 10:44, Pit Capitain wrote:

Ashley, in addition to Sean's answer, remember that the methods you
define at the toplevel, outside of any class, aren't singleton methods
of the "main" object. Instead, they are private methods of class Object.
Since every class is a subclass of Object, they inherit these "toplevel"
methods. In your method Foo#test, you're actually calling

self.global_test

so you're not calling a method of a different object. The following is
based on your code above:

I think I get it now. I assumed that top-level methods were singleton
methods. I'll have to watch this - I've been busy writing DSLs lately so my
code is apparently littered with methods added to Object, I didn't realise
they could be called anywhere.

Ashley

--
"If you do it the stupid way, you will have to do it again"
  - Gregory Chudnovsky