1

Frequently, the same method X gets called from different objects A, B, C. Is it possible to get a name of the caller object(A, B, C) from inside method X

eg :

class Sample def method # what needs to be done here? end end n1 = Sample.new n2 = Sample.new n1.method #=> expected output is to print n1 n2.method #=> expected output is to print n2 
5
  • 1
    Possible dup stackoverflow.com/questions/5100299/… Commented Sep 6, 2013 at 6:32
  • 1
    @YevgeniyAnfilofyev its not a duplicate of the link you specified. OP is asking for a way to print name of the calling object whereas link you have provided describes a way to print name of the calling method Commented Sep 6, 2013 at 6:56
  • @user2753200 you are actually asking for the variable name, caller refers to the execution stack. Commented Sep 6, 2013 at 7:11
  • Moreover, it is not the object name as objects have no name, just an ID. Commented Sep 6, 2013 at 12:23
  • @undur_gongor just one user considered it off-topic Commented Sep 6, 2013 at 12:37

4 Answers 4

5

No, this doesn't work. Imaging the following:

n1 = Sample.new n2 = n1 n2.method #=> ambiguous, both n1 and n2 would be valid 

You could assign a name to your instances instead:

class Sample attr_accessor :name end n1 = Sample.new n1.name = :n1 n2 = Sample.new n2.name = :n2 n1.name #=> :n1 n2.name #=> :n2 
Sign up to request clarification or add additional context in comments.

3 Comments

Technically n2.method is not ambiguous syntactically. Instead Ruby's internal structures make it unresolvable (and possible not advisable in any case) to find which pointer was used.
@NeilSlater is this possible in any language?
I'd hate to say "never", but no I cannot think of a language where you can discover the variable name programmatically. Probably a few can be hacked to do so via caller stack and code introspection - something that may work in a majority of cases. Still this would an abuse of variable names even in languages where it was possible, and the OP probably has other ways of achieving whatever the unstated higher-level goal is.
4

As others said, working with the object_id directly is most probably the much better approach.

Anyway, something along this line might work in your case:

class Sample def method(&b) eval("local_variables.select {|v| eval(v.to_s).object_id == #{object_id}}", b.binding) end end n1 = Sample.new n2 = Sample.new n3 = n2 p n1.method {} #=> [:n1] p n2.method {} #=> [:n2, :n3] p Sample.new.method {} #=> [] 

It returns all (local) variables in the current scope referencing the callee object. If each of your objects is referenced by exactly one variable, this might be what you are looking for.

Suggested by Neil Slater: you can also use the gem binding_of_caller to simplify transferring the binding:

require 'binding_of_caller' class Sample def method binding.of_caller(1).eval( "local_variables.select {|v| eval(v.to_s).object_id == #{object_id}}" ) end end n1 = Sample.new n2 = Sample.new n3 = n2 p n1.method #=> [:n1] p n2.method #=> [:n2, :n3] p Sample.new.method #=> [] 

(tested with version 0.7.2 of the gem).

1 Comment

Try to combine this with binding_of_caller gem :-)
3

Any object can be identified by its object_id:

class Sample def method puts self.object_id end end n1 = Sample.new n2 = Sample.new puts n1.object_id n1.method puts n2.object_id n2.method --output:-- 2152302060 2152302060 2152302040 2152302040 

Variable names...not so much.

Comments

0

Just returning self should work,

Here is an example:

class Sample attr_accessor :name def method puts self puts self.name end end n1 = Sample.new n1.name = "Bangalore" n2 = Sample.new n2.name = "Chennai" n1.method #=> expected output is to print n1 n2.method #=> expected output is to print n2 ------- Output: #<Sample:0x7f492f62c030> # n1 object Bangalore # n1.name #<Sample:0x7f492f62bec8> # n2 object Chennai #n2.name 

1 Comment

I think the OP is confusing variable name with object identity, and it is not 100% clear which is really required. Former is inadvisable to make use of (except perhaps in stack traces), latter is as per your answer, relatively straightforward.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.