faktycznie severin
mieć lepszy pomysł, tylko dlatego, że użycie metody method_missing to zła praktyka, nie cały czas, ale większość.
Jeden problem z tym kodem dostarczony przez severin
: zwraca wartość, która została przekazana do inicjatora, więc nie można go zmienić. Proponuję wam trochę innego podejścia:
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
Pozwala to sprawdzić:
u = User.new(:name => 'John')
p u.name
u[:name] = 'Maria'
p u.name
A także można zrobić z Struct:
attrs = {:name => 'John', :age => 22, :position => 'developer'}
keys = attrs.keys
user = Struct.new(*keys).new(*keys.map { |k| attrs[k] })
Lets go przetestować:
p user
p user.name
user[:name] = 'Maria'
p user.name
user.name = 'Vlad'
p user[:name]
Lub nawet OpenStruct, ale bądź ca reful nie stworzy metodę, jeśli już to w metodach instancji, można spojrzeć na to przez zastosowanie OpenStruct.instance_methods
(ze względu na typ jest używany, jestem teraz za pomocą drugiego podejścia):
attrs = {:name => 'John', :age => 22, :position => 'developer'}
user = OpenStruct.new(attrs)
Tak, tak łatwo :
user.name
user[:name] # will give you an error, because OpenStruct isn't a Enumerable or Hash
Zobacz, co należy napisać w OpenStruct (struct.rb w standardowej bibliotece). Jest trochę inny niż to, o co prosisz: pozwala na wywołanie metody na OpenStruct jako akcesor, bez względu na to, czy zostało już zdefiniowane, czy nie. Ale to kod, którego nie musisz pisać, co czasem może być plusem. –