realtà severin
dispone di un migliore idea, solo perché l'uso di method_missing è una cattiva pratica, non sempre, ma soprattutto.
Un problema con quel codice fornito da severin
: restituisce il valore che è stato passato all'inizializzatore, quindi non è possibile cambiarlo. Vi suggerisco un po 'diverso approccio:
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
permette di controllare:
u = User.new(:name => 'John')
p u.name
u[:name] = 'Maria'
p u.name
e inoltre è possibile farlo con Struct:
attrs = {:name => 'John', :age => 22, :position => 'developer'}
keys = attrs.keys
user = Struct.new(*keys).new(*keys.map { |k| attrs[k] })
Lets testarlo:
p user
p user.name
user[:name] = 'Maria'
p user.name
user.name = 'Vlad'
p user[:name]
O anche OpenStruct, ma essere ca REFUL non creerà metodo se già hanno in metodi di istanza, si può cercare che utilizzando OpenStruct.instance_methods
(a causa del tipo viene utilizzato, ora sto usando secondo approccio):
attrs = {:name => 'John', :age => 22, :position => 'developer'}
user = OpenStruct.new(attrs)
Sì, così facile :
user.name
user[:name] # will give you an error, because OpenStruct isn't a Enumerable or Hash
fonte
2010-10-31 17:36:53
Assicuratevi di guardare OpenStruct (struct.rb nella libreria standard). È un po 'diverso da quello che stai chiedendo: consente a qualsiasi chiamata di metodo su OpenStruct di essere un accessor, indipendentemente dal fatto che sia già stato definito. Ma è un codice che non devi scrivere, che a volte può essere un vantaggio. –