From: David Masover Date: 2009-10-29T23:19:21+09:00 Subject: Re: Setting instance variables from hash parameters (with defaults) On Monday 26 October 2009 10:42:01 am Leslie Viljoen wrote: > I see this is a shorter way: > > module Defaulting > def set_params(defs, params) > defs.merge(params).each {|name, val| eval "@#{name} = val"} > end > end > > ..still, any way to get rid of that eval? You want instance_variable_set: module Defaulting def set_params def, params defs.merge(params).each {|name, val| instance_variable_set name, val} end end I can think of a few ways to make it easier to use, and I'd suggest actually calling the name= method, rather than setting the instance variable directly. Here's a rough sketch: module Defaulting def init_with_vars *vars, &init_block defaults = vars.last.kind_of?(Hash) ? vars.pop : {} vars = (vars + defaults.keys).uniq attr_accessor *vars define_method :initialize do |*args, &block| if args.last.kind_of? Hash defaults.merge(args).each_pair {|name, val| self.send("#{name}=", val) } end if init_block init_block.call *args, &block end end end end I'm fairly sure there's something like this already, some combination of something like Struct could work. I do like this usage, though: class Foo include Defaulting init_with_vars :foo, :bar, :baz => 'default baz' def bar 'overriding default bar reader' end end Mostly because for so many classes, I don't need an initialize method at all, except as a convenience to set up variables I know I'll need.