En realidad tiene un severin
Mejor idea, solo porque el uso de method_missing es una mala práctica, no todo el tiempo, pero la mayor parte.
Un problema con el código proporcionado por severin
: devuelve el valor que se ha pasado al inicializador, por lo que no puede cambiarlo. Te sugiero un enfoque un poco diferente:
class User < Hash
def initialize(attrs)
attrs.each do |k, v|
self[k] = v
end
end
def []=(k, v)
unless respond_to?(k)
self.class.send :define_method, k do
self[k]
end
end
super
end
end
Permite comprobar que:
u = User.new(:name => 'John')
p u.name
u[:name] = 'Maria'
p u.name
y también puede hacerlo con Struct:
attrs = {:name => 'John', :age => 22, :position => 'developer'}
keys = attrs.keys
user = Struct.new(*keys).new(*keys.map { |k| attrs[k] })
Lets probarlo:
p user
p user.name
user[:name] = 'Maria'
p user.name
user.name = 'Vlad'
p user[:name]
O incluso OpenStruct, pero se ca REFUL no creará método si ya lo tenemos en los métodos de instancia, se puede buscar que mediante el uso OpenStruct.instance_methods
(a causa de tipo se utiliza, ahora estoy usando segundo enfoque):
attrs = {:name => 'John', :age => 22, :position => 'developer'}
user = OpenStruct.new(attrs)
Sí, tan fácil :
user.name
user[:name] # will give you an error, because OpenStruct isn't a Enumerable or Hash
Asegúrese de ver OpenStruct (struct.rb en la biblioteca estándar). Es un poco diferente de lo que está pidiendo: permite que cualquier llamada de método en el OpenStruct sea un acceso, ya sea que esté o no definido. Pero es un código que no tiene que escribir, que a veces puede ser un plus. –