En fait severin
avez une meilleure idée, juste parce que l'utilisation de method_missing est une mauvaise pratique, pas tout le temps, mais la plupart du temps.
Un problème avec ce code fourni par severin
: il renvoie la valeur qui a été transmise à l'initialiseur, donc vous ne pouvez pas le changer. Je vous propose une petite approche différente:
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
permet de vérifier:
u = User.new(:name => 'John')
p u.name
u[:name] = 'Maria'
p u.name
Et vous pouvez aussi le faire avec Struct:
attrs = {:name => 'John', :age => 22, :position => 'developer'}
keys = attrs.keys
user = Struct.new(*keys).new(*keys.map { |k| attrs[k] })
Lets tester:
p user
p user.name
user[:name] = 'Maria'
p user.name
user.name = 'Vlad'
p user[:name]
Ou même OpenStruct, mais soyez ca REFUL il ne crée pas la méthode si elle a déjà dans les méthodes d'exemple, vous pouvez chercher qu'en utilisant OpenStruct.instance_methods
(à cause du type est utilisé, j'utilise maintenant la deuxième approche):
attrs = {:name => 'John', :age => 22, :position => 'developer'}
user = OpenStruct.new(attrs)
Eh oui, si facile :
user.name
user[:name] # will give you an error, because OpenStruct isn't a Enumerable or Hash
Assurez-vous de regarder OpenStruct (struct.rb dans la bibliothèque standard). C'est un peu différent de ce que vous demandez: cela permet à tout appel de méthode sur OpenStruct d'être un accesseur, qu'il soit déjà défini ou non. Mais c'est un code que vous n'avez pas à écrire, ce qui peut parfois être un plus. –