Clifford Heath wrote: > I'm trying to define s.t. like attr_accessor, but one that takes > an optional block defining a function that filters the value on > the setter. Perhaps that will be clear if I show you the snippet: > > class Object > def add_property(sym, &block) > n = sym.id2name > code = %Q{ > def #{n}() > @#{n} ||= nil > end > def #{n}=(value) > @#{n} = block ? block.call(value) : value > end > } > eval(code) > end > end > > # A test object: > d = 3 > > # Add a getter and custom setter to 3: > d.add_property(:do_it) {|v| > # Custom setter method > puts "d.do_it here, v = #{v.inspect}" > v # No filtering this time, just return the value. > } > > # Assign the property: > d.do_it = "a value" > > Ok, I can see why "block" isn't defined. How can I pass add_property's > block in as a block to be used *inside* the evaluated code? You can use define_method: class Module def add_property(sym,&test) define_method("#{sym}=") do |val| test && test[val] instance_variable_set("@#{sym}", val) end define_method(sym) do |val| instance_variable_get("@#{sym}") end end end class Foo add_property :age do |x| raise "Illegal negative" unless x >= 0 end end >> Foo.new.age = -2 RuntimeError: Illegal negative from (irb):55 from (irb):54:in `[]' from (irb):43:in `age=' from (irb):42:in `age=' from (irb):59 >> Foo.new.age = 1 => 1 >> Foo.new.age = 0 => 0 Kind regards robert