Using the Value of a Variable as Another Variables Name in Ruby

Using the value of a variable as another variables name in Ruby

Use instance_variable_set (rubydoc)

instance_variable_set("@" + varname, value)

In most cases though, you should separate your normal Ruby variables from the variables your user is interacting with. How about creating a Hash of user variables, e.g.

@uservars = { 'one' => 1, 'two' => 2 }
two = @uservars['two'] # Look up 'two' variable

varname = "myvar"
@uservars[varname] = 5 # Set a variable by name
value = @uservars[varname] # Get a variable by name

Ruby -- use a string as a variable name to define a new variable

There is no way to define new local variables dynamically in Ruby.

It was possible in Ruby 1.8 though with eval 'x = 2'.

You can change an existing variable with eval or binding.local_variable_set.

I would consider using hash to store values.

How to create and use variables dynamically named by string values in Ruby?

Instance variables are used define properties of an object.

Instead you can achieve through the method send and string interpolation.

Try the below:

def click_colour_cell(colour)
send("has_#{colour}_colour_cell?")
send("#{colour}_colour_cell").click
end

About Send:

send is the method defined in the Object class (parent class for all the classes).

As the documentation says, it invokes the method identified by the given String or Symbol. You can also pass arguments to the methods you are trying to invoke.

On the below snippet, send will search for a method named testing and invokes it.

class SendTest
def testing
puts 'Hey there!'
end
end

obj = SendTest.new
obj.send("testing")
obj.send(:testing)

OUTPUT

Hey there!
Hey there!

In your case, Consider the argument passed for colour is blue,

"has_#{colour}_colour_cell?" will return the string"has_blue_colour_cell?" and send will dynamically invoke the method named has_blue_colour_cell?. Same is the case for method blue_colour_cell

Access variables programmatically by name in Ruby

What if you turn your problem around? Instead of trying to get names from variables, get the variables from the names:

["foo", "goo", "bar"].each { |param_name|
param = eval(param_name)
if param.class != Array
puts "#{param_name} wasn't an Array. It was a/an #{param.class}"
return "Error: #{param_name} wasn't an Array"
end
}

If there were a chance of one the variables not being defined at all (as opposed to not being an array), you would want to add "rescue nil" to the end of the "param = ..." line to keep the eval from throwing an exception...

Ruby- read the value of a variable in another class?

Quick answer, for if you actually understand Classes, Inheritance and Objects : replace @var (an instance variable, and therefore different in a and b) with @@var (a class variable, and therefore the same in all instances of class A).

Otherwise, your question indicates you have a fundamental misunderstanding of what's going on with classes, objects and inheritance.

Your code does the following:

  • Defines a class, called A. This is essentially a blueprint from which you can create objects.
    • Declares that when an object of type A is created, that object should be given it's own private copy of an attribute, called var, which is set to 0.
    • Declares that objects of type A can be asked to dosomething, which increases the value of that object's var by 1.
  • Defines a class called B, which is a special case of an A

Therefore, in your second snippet, you create an object a, which is an A. It has its own attribute called var, which is set to 0 and then incremented. You then create b, which is a B (and is therefore also an A). b has its own attribute called var, separate from a's var, which is set to 0.

Get the value of an instance variable given its name

The most idiomatic way to achieve this is:

some_object.instance_variable_get("@#{name}")

There is no need to use + or intern; Ruby will handle this just fine. However, if you find yourself reaching into another object and pulling out its ivar, there's a reasonably good chance that you have broken encapsulation.

If you explicitly want to access an ivar, the right thing to do is to make it an accessor. Consider the following:

class Computer
def new(cpus)
@cpus = cpus
end
end

In this case, if you did Computer.new, you would be forced to use instance_variable_get to get at @cpus. But if you're doing this, you probably mean for @cpus to be public. What you should do is:

class Computer
attr_reader :cpus
end

Now you can do Computer.new(4).cpus.

Note that you can reopen any existing class and make a private ivar into a reader. Since an accessor is just a method, you can do Computer.new(4).send(var_that_evaluates_to_cpus)

How to create a variable name from the value of a string in Ruby on Rails?

This instance_variable_set("#{foo}", "cornholio") needs to read instance_variable_set("@#{foo}", "cornholio")

Based on this post. Just tried it in my irb for Ruby 1.93; the post is from 2009.

Using loop counter as part of a variable's name in Ruby

As others have pointed out it is not possible to create local variables dynamically in Ruby, you could set up a binding as well if you're looking for another method of achieving this.

With eval

b = binding
10.times do |i|
eval("var#{i} = 'foo'", b)
end

> eval("var1", b)
=> "foo"

> eval("local_variables", b)
=> [:var9, :var8, :var7, :var6, :var5, :var4, :var3, :var2, :var1, :var0, :b, :_]

Without eval

b = binding
10.times do |i|
b.local_variable_set("var#{i}", 'foo')
end

> b.local_variable_get('var1')
=> "foo"

> b.local_variables
=> [:var9, :var8, :var7, :var6, :var5, :var4, :var3, :var2, :var1, :var0, :b, :_]

@ variables in Ruby on Rails

title is a local variable. They only exists within its scope (current block)

@title is an instance variable - and is available to all methods within the class.

You can read more here:
http://strugglingwithruby.blogspot.dk/2010/03/variables.html

In Ruby on Rails - declaring your variables in your controller as instance variables (@title) makes them available to your view.



Related Topics



Leave a reply



Submit