I have an instance variable @foo
and I want to write some code so that I get string \'foo\'
any hint?
You can call the method instance_variables
to get the name of all instance variables of an object. Caution though that instance variables are only included in that list after they have been initialized.
>> class A; attr_accessor :foo; end
=> nil
>> a = A.new
=> #<A:0x103b310b0>
>> a.instance_variables
=> []
>> a.foo = 42
=> 42
>> a.instance_variables
=> ["@foo"]
If all you have is a reference to the object, you can't really do it cleanly.
def foo
bar @something
end
def bar(value)
value # no clean way to know this is @something
end
The only hack I can think of is to loop through ALL instance variables on self
, looking for matches. But its a very messy approach that's likely to be slow.
def bar(value)
instance_variables.each do |ivar_name|
if instance_variable_get(ivar_name) == value
return ivar_name.to_s.sub(/^@/, '') # change '@something' to 'something'
end
end
# return nil if no match was found
nil
end
@something = 'abc123'
bar @something # returns 'something'
# But passing the same value, will return a value it's equal to as well
bar 'abc123' # returns 'something'
This works because instance_variables
returns an array of symbols that are the names of instance variables.
instance_variables
#=> [:@something, :@whatever]
And instance_variable_get
allows you to fetch the value by it's name.
instance_variable_get :@something # note the @
#=> 'abc123'
Combine the two methods and you can get close to what you want.
Just use it wisely. Before using a solution based on this, see if you can refactor things a way so that it's not necessary. Meta-programming is like a martial art. You should know how it works, but have the discipline to avoid using it whenever possible.
In Ruby, you can only manipulate objects. Variables (including instance variables) aren't objects.
Besides, what do you want your magic method to return in this case:
foo = Object.new
bar = foo
@baz = bar
@qux = bar
magic_method(foo) # what should the return value be and how would it know?
class Object
def get_name
line_number = caller[0].split(':')[1].to_i
line_exectued = File.readlines( __FILE__)[line_number-1]
line_exectued.match(/(\S+).get_name/)[1]
end
end
inconceivable = true
p inconceivable.get_name