Get the value of an instance variable given its name

RubyMetaprogramming

Ruby Problem Overview


In general, how can I get a reference to an object whose name I have in a string?

More specifically, I have a list of the parameter names (the member variables - built dynamically so I can't refer to them directly).

Each parameter is an object that also has an from_s method.

I want to do something like the following (which of course doesn't work...):

define_method(:from_s) do | arg |
    @ordered_parameter_names.each do | param |
        instance_eval "field_ref = @#{param}"
        field_ref.from_s(param)
    end
end

Ruby Solutions


Solution 1 - Ruby

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)

Solution 2 - Ruby

To get an instance variable from the name of an instance variable do:

name = "paramName"
instance_variable_get(("@" + name).intern)

This will return the value of the instance variable @paramName

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLK__View Question on Stackoverflow
Solution 1 - RubyYehuda KatzView Answer on Stackoverflow
Solution 2 - RubyDaniel LucraftView Answer on Stackoverflow