Ruby: genera dinĂ¡micamente attribute_accessor
attr-accessor (3)
Podrías hacer un poco de meta-magia para resolver esto, usando method_missing:
class Event
def method_missing(method_name, *args, &block)
if instance_variable_names.include? "@#{method_name}"
instance_variable_get "@#{method_name}"
else
super
end
end
end
Lo que esto hará es permitir el acceso a las variables de instancia de objeto a través de la sintaxis de object.variable, si el objeto tiene esas variables definidas, sin recurrir a modificar la clase completa a través de attr_accessor.
Estoy intentando generar el attr_reader a partir de un hash (con hash anidado) para que refleje la creación de instancia_variable automáticamente.
Esto es lo que tengo hasta ahora:
data = {:@datetime => ''2011-11-23'', :@duration => ''90'', :@class => {:@price => ''£7'', :@level => ''all''}}
class Event
#attr_reader :datetime, :duration, :class, :price, :level
def init(data, recursion)
data.each do |name, value|
if value.is_a? Hash
init(value, recursion+1)
else
instance_variable_set(name, value)
#bit missing: attr_accessor name.to_sym
end
end
end
Pero no puedo encontrar una manera de hacerlo: (
attr_accessor
es un método de clase y como tal debe invocarse en la clase. También es un método privado, por lo que necesita invocarlo en un contexto en el que el objeto de clase sea self
.
Como ejemplo:
class C
def foo
self.class.instance_eval do
attr_accessor :baz
end
end
end
Después de crear una instancia de C
y llamar a foo
en esa instancia, esa instancia, y todas las instancias futuras, contendrán los métodos baz
y baz=
.
attr_accessor
llamar al método de clase (privado) attr_accessor
en la clase de Event
:
self.class.send(:attr_accessor, name)
Te recomiendo agregar la @
en esta línea:
instance_variable_set("@#{name}", value)
Y no los uses en el hachís.
data = {:datetime => ''2011-11-23'', :duration => ''90'', :class => {:price => ''£7'', :level => ''all''}}