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