Obtener el valor de una variable de instancia con su nombre


En general, ¿cómo puedo obtener una referencia a un objeto cuyo nombre tengo en una cadena?

Más específicamente, tengo una lista de los nombres de los parámetros (las variables miembro - construidas dinámicamente por lo que no puedo hacer referencia a ellos directamente).

Cada parámetro es un objeto que también tiene un método from_s.

Quiero hacer algo como lo siguiente (que por supuesto no funciona...):

define_method(:from_s) do | arg |
    @ordered_parameter_names.each do | param |
        instance_eval "field_ref = @#{param}"
        field_ref.from_s(param)
    end
end
Author: the Tin Man, 2009-07-02

2 answers

La forma más idiomática de lograr esto es:

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

No hay necesidad de usar + o intern; Ruby manejará esto muy bien. Sin embargo, si te encuentras alcanzando otro objeto y sacando su ivar, hay una probabilidad razonablemente buena de que hayas roto la encapsulación.

Si desea acceder explícitamente a un ivar, lo correcto es convertirlo en un accessor. Considere lo siguiente:

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

En este caso, si lo hicieras Computer.new, te verías forzado usar instance_variable_get para llegar a @cpus. Pero si estás haciendo esto, probablemente quieres decir que @cpus sea público. Lo que debes hacer es:

class Computer
  attr_reader :cpus
end

Ahora puedes hacer Computer.new(4).cpus.

Tenga en cuenta que puede reabrir cualquier clase existente y convertir un ivar privado en un lector. Dado que un accessor es solo un método, puede hacer Computer.new(4).send(var_that_evaluates_to_cpus)

 164
Author: Yehuda Katz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-06 20:42:16

Para obtener una variable de instancia del nombre de una variable de instancia, haga lo siguiente:

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

Esto devolverá el valor de la variable de instancia @paramName

 7
Author: Daniel Lucraft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 14:52:36