From: Joel VanderWerf Date: 2005-10-02T04:24:07+09:00 Subject: Re: Better way to make struct with defaults? Gavin Kistner wrote: > I'm using the same ideas as Struct to quickly create a class that: > a) Has default values for the properties > b) Uses symbols inside #new to set the values (instead of argument order) > > I have it working (code below) but whenever I construct a string for > use with *_eval, I feel that I'm probably being boneheaded, and there's > a better way to do it. What suggestions do people have for cleaning up > and/or simplifying the following code? > > def Struct.with_defaults( property_hash ) > klass = self.new( *property_hash.keys ) > klass.class_eval <<-ENDCODE > def initialize( values={} ) > #{property_hash.map{ |prop,default| > "self.#{prop} = values[#{prop.inspect}] || # > {default.inspect}" > }.join("\n")} > end > ENDCODE > klass > end > > Person = Struct.with_defaults :sex=>'male', :age=>0, :name=>nil > gk = Person.new :name=>'Gavin', :age=>32 > p gk > #=> # > def Struct.with_defaults( property_hash ) klass = self.new( *property_hash.keys ) default_setters = property_hash.map do |prop,default| ["#{prop}=".intern, prop, default] end klass.class_eval do define_method :initialize do |values| values ||= {} default_setters.each do |setter,prop,default| value = values.key?(prop) ? values[prop] : default send setter, value end end end klass end Person = Struct.with_defaults :sex=>'male', :age=>0, :name=>nil gk = Person.new :name=>'Gavin', :age=>32 p gk __END__ output: # -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407