Add support for Aspect Oriented Programming (AOP).

Examples

class Controller

  pre :force_login, :where => :prepend
  wrap Benchmark, :on => :index
  post :taraa, :on => login

end

module Timestamped

  pre :on => :og_insert { |this| this.create_time = Time.now }
  pre :on => :og_update { |this| this.update_time = Time.now }
  pre :on => [:og_insert, :og_update] { |this| this.create_time = Time.now }

end

Methods
Classes and Modules
Module Aspects::ClassMethods
Constants
Advice = Struct.new(:code, :options)
  Store the code and the metadata (options) for an Advice.
Public Class methods
append_features(base)
# File lib/facets/more/aspects.rb, line 178
  def self.append_features(base)
    super
    base.extend(ClassMethods)
    base.inheritor :advices, [], :+
  end
include_advice_modules(target)

Include Modules that define advices.

# File lib/facets/more/aspects.rb, line 101
  def self.include_advice_modules(target)
    add_advices = []
    del_advices = []

    for a in target.advices
      if a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
        target.module_eval %{ include #{a.code} }

        options = a.options.reject { |k,v| k == :pre || k == :post }

        method = (a.options[:pre] || 'pre').to_s
        if a.code.instance_methods.include?(method)
          options.update(:where => :prepend, :join => :pre)
          add_advices <<  Advice.new(method.to_sym, options)
        end

        method = (a.options[:post] || 'post').to_s
        if a.code.instance_methods.include?(method)
          options.update(:where => :append, :join => :post)
          add_advices <<  Advice.new(method.to_sym, options)
        end

        del_advices << a
      end
    end

    # Delete the original advices.

    for a in del_advices
      target.advices!.delete(a)
    end

    # Add the new advices.

    target.advices!.concat(add_advices)
  end
wrap(target, methods = target.instance_methods)

Apply the advices to the target class.

# File lib/facets/more/aspects.rb, line 75
  def self.wrap(target, methods = target.instance_methods)
    include_advice_modules(target)

    for m in [methods].flatten
      args = []
      target.instance_method(m).arity.times { |i| args << "a#{i}" }
      args = args.join(',')

      target.module_eval "alias_method :__unwrapped_\#{m}, :\#{m}\ndef \#{m}(\#{args})\n\#{gen_advice_code(m, target.advices, :pre)}\n__unwrapped_\#{m}(\#{args})\n\#{gen_advice_code(m, target.advices, :post)}\nend\n", __FILE__, __LINE__ 
    end
  end