Better way to make struct with defaults?

G

Gavin Kistner

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
#=> #<struct Person sex="male", name="Gavin", age=32>
 
J

Joel VanderWerf

Gavin said:
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
#=> #<struct Person sex="male", name="Gavin", age=32>

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:

#<struct Person sex="male", age=32, name="Gavin">
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top