From: Florian Gross Date: 2004-11-15T22:18:20+09:00 Subject: Re: OpenStruct#update ? 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. > 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. 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