41

I have a string, which has been created at runtime. I want to use this string as a variable to store some data into it. How can I convert the string into a variable name?

Ry-
  • 218,210
  • 55
  • 464
  • 476

6 Answers6

56

If you can forgive an @ sign in front of the variable name, the following will work:

variable_name = ... # determine user-given variable name
instance_variable_set("@#{variable_name}", :something)

This will create a variable named @whatever, with its value set to :something. The :something, clearly, could be anything you want. This appears to work in global scope, by declaring a spontaneous Object instance which binds everything (I cannot find a reference for this).

The instance_variable_get method will let you retrieve a value by name in the same manner.

instance_variable_get("@#{variable_name}")
Andres Jaan Tack
  • 22,566
  • 11
  • 59
  • 78
  • I get `is not allowed as an instance variable name` for `instance_variable_set`. Rails 3.0.7. – B Seven Mar 08 '12 at 02:07
  • 3
    FTR, you can also use `binding.local_variable_get("variable_name")` if you're on Ruby 2.1, but I wouldn't recommend it. – clem Feb 08 '14 at 18:10
  • 1
    Little gotcha re B Seven's comment up there ^^, this can come about if you don't prepend the string with an `@` symbol – SRack Nov 20 '15 at 12:01
15

You can use eval() for this provided that you've declared your variable first:

>> foo = []
>> eval("foo")[1] = "bar"
>> foo[1]
=> "bar"

Here are the docs.

Gordon Wilson
  • 26,244
  • 11
  • 57
  • 60
13

Rather than do that directly, why not consider using a hash instead. The string would be the key, and the value you want to store would be the value. Something like this:

string_values = { }
some_string = params[:some_string]       # parameter was, say "Hello"
string_values[some_string] = 42
string_values                            # { 'Hello' => 42 }
some_number = string_values[some_string]
some_number                              # 42

This has a couple of benefits. First, it means you're not doing anything magic that might be hard to figure out later. Second, you're using a very common Ruby idiom that's used for similar functionality throughout Rails.

Tim Sullivan
  • 16,808
  • 11
  • 74
  • 120
  • Huh? What if you just want to store "Hello" as a variable to use later. Where does the 42 come in? This seems overly complex...although admittedly I'm a Ruby newb. – Southerneer Dec 31 '14 at 03:01
  • That isn't what the questioner is asking. They are receiving a string value from somewhere at *runtime*, and wish to associate that string with a value. Sure, you could hack the system to create a variable with that string name (with the related caveat of error checking the string to ensure it's a valid identifier), but what I am suggesting is you use Ruby's simple, widely understood, and safe `Hash` to associate the string and the value together. – Tim Sullivan Dec 31 '14 at 16:59
6

Now simply using instance_variable_set method, you can create a instance variable at runtime.

instance_variable_set('@' + 'users', User.all)
uma
  • 2,932
  • 26
  • 20
5

I don't mean to be negative, but tread carefully. Ruby gives you a lot of features for highly dynamic programming such as define_method, storing blocks as Proc objects to be called later, etc. Generally these are cleaner code and far safer. 99% of the time using eval() is a mistake.

And absolutely never use eval() on a string that contains user submitted input.

Jason Watkins
  • 2,702
  • 17
  • 18
0

As Jason Watkins says, a lot of people might be quick to use eval() first thing and this would be a serious mistake. Most of the time you can use the technique described by Tack if you've taken care to use a class instance variable instead of a local one.

Local variables are generally not retrievable. Anything with the @ or @@ prefix is easily retrieved.

tadman
  • 208,517
  • 23
  • 234
  • 262