0

In PHP, I can do this:

$a = 1;
$c = 'a';
$$c = 2;
//now $a == 2

Is there any equivalent in ruby? By which I mean, any simple way to have it dereference a variable during execution like this? I'd rather not use eval, because it looks messy - I've already determined that eval can't be called as a method of a string.

Benubird
  • 18,551
  • 27
  • 90
  • 141
  • 1
    http://stackoverflow.com/a/1077682/812912 – Ivaylo Strandjev Jun 17 '14 at 08:54
  • @IvayloStrandjev your link is about instance variable – Jaffa Jun 17 '14 at 08:56
  • 1
    @Geoffroy that is why I did not post an answer but a comment. The two questions are related and the link provides some insight on the question being asked. – Ivaylo Strandjev Jun 17 '14 at 09:00
  • 4
    An important point to make is, even though there are ways to use "variable variables" in ruby, you *really* shouldn't as it can lead to potentially grave security issues, is rather slow and is overall bad design, leading to unclear data access and promotes global variables (which are about the worst thing ever). Instead, you should put your data into a hash, i.e. `data = {:a => 1}` which you can then access as `data[:a]`. – Holger Just Jun 17 '14 at 09:21

2 Answers2

2

It is possible but it's a bit more complicated., and you actually have two possibilities:

Kernel#local_variables

Returns the names of the current local variables.

fred = 1
for i in 1..10
   # ...
end
local_variables   #=> [:fred, :i]

Binding#local_variable_get/set

Returns a value of local variable symbol.

def foo
  a = 1
  binding.local_variable_get(:a) #=> 1
  binding.local_variable_get(:b) #=> NameError
end

This method is short version of the following code.

binding.eval("#{symbol}")
Jaffa
  • 12,442
  • 4
  • 49
  • 101
0

if you just need this you can do

a = 1
c = 'a'
eval("#{c} = 2")
a == 2   # => true

... but this is moron way to do this

if you need this for instance variables

class Foo
  attr_reader :a

  def initialize
    @a = 1
  end
end

foo = Foo.new
foo.instance_variable_get(:a)       #=> 1
foo.a                               #=> 1
foo.instance_variable_set(:"@a", 2)
foo.a                               #=> 2

...you can also eval instance like this:

# ...
foo.instance_eval do
  @a = 'b'
end
foo.a    # => 'b'
equivalent8
  • 13,754
  • 8
  • 81
  • 109