From: Daniel Schierbeck Date: 2006-06-14T17:57:59+09:00 Subject: Re: Cut-based AOP Austin Ziegler wrote: > I have yet to need AOP in Ruby. Of any sort. I think AOP is just what we need. Currently, it's difficult to combine different extensions of the current behavior (e.g. transforming and validating attributes -- they often both overwrite `#{attr}='). I'm not sure we need the full-fledged Cut version, I think a different `def' would suffice. Perhaps `aspect'? Well, I'm not really fluid in the AOP lingo. 1 class Module 2 def attr_transformer(*attrs, &block) 3 attrs.each do |attr| 4 define_method("#{attr}=") do |value| 5 instance_variable_set("@#{attr}", block.call(value)) 6 end 7 end 8 end 9 10 def attr_validator(*attrs, &block) 11 attrs.each do |attr| 12 define_method("#{attr}=") do |value| 13 if block.call(value) 14 instance_variable_set("@#{attr}", value) 15 else 16 raise ArgumentError, "invalid value" 17 end 18 end 19 end 20 end 21 end How would one use #attr_transformer and #attr_validator together? Ideally, you could do this: class Module def attr_transformer(*attrs, &block) attrs.each do |attr| define_aspect("#{attr}=") do |value| # call the previously defined method, or # super, if none exist. previous(value) end end end def attr_validator(*attrs, &block) attrs.each do |attr| define_aspect("#{attr}=") do |value| if block.call(value) previous(value) else raise ArgumentError, "invalid value" end end end end end class Foo attr_accessor(:bar, :baz) attr_transformer(:bar){|value| value ** 2} attr_validator(:bar){|value| value > 0 and value < 10} end foo = Foo.new foo.bar = 3 The following would then happen: 1. The aspect defined by #attr_validator will be called. 2. The aspect defined by #attr_transformer will be called 3. The method defined by #attr_accessor will be called Of course, one could just make do with a `previous' keyword in the normal method definitions. Cheers, Daniel