From: Robert Klemme Date: 2004-11-15T23:43:22+09:00 Subject: Re: OpenStruct#update ? "Florian Gross" schrieb im Newsbeitrag news:2vrofmF2ouoprU1@uni-berlin.de... > Robert Klemme wrote: > > > "Florian Gross" schrieb im Newsbeitrag > >>h.each do |k,v| > >> class << o; self; end.send(:attr_accessor, k) > >> o.k = v > >>end > > > > Are you sure, this works? IMHO this is more efficient: > > > > class << o; self; end.send(:attr_accessor, *h.keys) > > h.each do |k,v| > > o.send("#{k}=", v) > > end > > You are right of course. I also like how you moved the attr_accessor out > of the loop -- nice idea. Thanks! > > But it would be even better to check for existing methods in order to not > > overwrite existing methods: > > > > cl = class << o; self; end > > im = cl.instance_methods > > h.each do |k,v| > > cl.send(:attr_reader, k) unless im.include?(k.to_s) > > cl.send(:attr_writer, k) unless im.include?("#{k}=") > > o.send("#{k}=", v) > > end > > Hm, I think that would still overwrite methods of o's class and > inherited ones. I don't think so: >> class Foo; attr_accessor :bar end => nil >> f=Foo.new => # >> class < true The singleton class of f knows about instance methods defined in super classes. Which is logical, considering this: >> class < [Foo, Object, Kernel] > What about this? > > accessors = h.keys - o.methods > class << o; self; end.send(:attr_accessor, *accessors) > h.each do |key, value| > o.send("#{key}=", value) if accessors.include?(key) > end Nice and short. But it has some drawbacks: (with f and Foo as above) >> h={:foo=>"foo", :bar=>"bar"} => {:foo=>"foo", :bar=>"bar"} >> h.keys-f.methods => [:foo, :bar] >> h.keys => [:foo, :bar] You would want ":bar" removed from the keys but it isn't because f.methods returns an array of String. (I assume that symbols are the most likely keys for the hash - which might be wrong.) Plus, it's not selective enough IMHO because if you just have a setter, then that is overwritten. And if you just have a getter, then no setter is defined and you get an error during o.send("#{key}="...). Kind regards robert