How do you access a Ruby instance variable/method dynamically? I'm basically after the Ruby equivalent of the following PHP code...
$foo = new Foo;
$bar = 'bar';
echo $foo->$bar;
echo $foo->$bar();
The #send
method takes a method name. You can call #intern
on a string to make a Symbol from it. So this is the equivalent:
foo = Foo.new
bar = 'bar'
puts foo.send(bar.intern)
Instance variables are private by default. To expose them, the normal thing to do is to add a attr_reader
call to the class definition:
class Foo
attr_reader :bar
def initialize(value_of_bar)
@bar = value_of_bar
end
end
bar = 'bar'
foo = Foo.new("bar_value")
puts foo.bar # => "bar_value"
puts foo.send(:bar) # => "bar_value"
puts foo.send(bar.intern) # => "bar_value"
To reach in and access instance variables that don't have reader methods, #instance_variable_get
will work, though it's often better to avoid it.
class Foo
def initialize
@x = 10
end
def test
@x
end
end
foo = Foo.new
foo.instance_variables
# => [:@x]
foo.instance_variable_get(:@x)
# => 10
Foo.instance_methods(false)
# => [:test]
Foo.instance_methods(false).map{|i| foo.method(i).call}
# => [10]
Foo.instance_methods(false).map{|i| foo.send(i)}
# => [10]
instance_variable_get
(Don't forget the @
).
class Foo
def initialize
@ivar = "hello"
end
end
foo = Foo.new
foo.instance_variable_get :@ivar
#=> "hello"
Alternatively provide an accessor on the class
class Bar
attr_reader :ivar
def intialize
@ivar = "hey"
end
end
Bar.new.ivar
#=> "hey"