Actually severin
have a better idea, just because usage of method_missing is a bad practice, not all the time, but most of it.
One problem with that code provided by severin
: it returns value that have been passed to initializer, so you cannot change it. I suggest you a little different approach:
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
Lets check it:
u = User.new(:name => 'John')
p u.name
u[:name] = 'Maria'
p u.name
And also you can do it with Struct:
attrs = {:name => 'John', :age => 22, :position => 'developer'}
keys = attrs.keys
user = Struct.new(*keys).new(*keys.map { |k| attrs[k] })
Lets test it:
p user
p user.name
user[:name] = 'Maria'
p user.name
user.name = 'Vlad'
p user[:name]
Or even OpenStruct, but be careful it will not create method if it already have it in instance methods, you can look for that by using OpenStruct.instance_methods
(because of type is used, I'm now using second approach):
attrs = {:name => 'John', :age => 22, :position => 'developer'}
user = OpenStruct.new(attrs)
Yep, so easy:
user.name
user[:name] # will give you an error, because OpenStruct isn't a Enumerable or Hash