lib/glue/aspects.rb in glue-0.20.0 vs lib/glue/aspects.rb in glue-0.21.0
- old
+ new
@@ -3,232 +3,222 @@
module Glue
# An Aspect is a class that defines advices.
class Aspect
- class << self
- def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
- target.send(:include, Aspects) unless target.ancestors.include?(Aspects)
- target.wrap(self, :pre => pre, :post => post)
- end
+ class << self
+ def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
+ target.send(:include, Aspects) unless target.ancestors.include?(Aspects)
+ target.wrap(self, :pre => pre, :post => post)
+ end
- alias_method :observe, :wrap
- end
+ alias_method :observe, :wrap
+ end
- def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
- target.send(:include, Aspects) unless target.ancestors.include?(Aspects)
- target.wrap(self, :pre => pre, :post => post)
- end
- alias_method :observe, :wrap
+ def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
+ target.send(:include, Aspects) unless target.ancestors.include?(Aspects)
+ target.wrap(self, :pre => pre, :post => post)
+ end
+ alias_method :observe, :wrap
end
# Add support for Aspect Oriented Programming (AOP).
#
# === Examples
#
# class Controller
-# pre :force_login, :where => :prepend
-# wrap Benchmark, :on => :index
-# post :taraa, :on => login
+# 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 }
+# 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
module Aspects
- # Store the code and the metadata (options) for
- # an Advice.
+ # Store the code and the metadata (options) for
+ # an Advice.
- Advice = Struct.new(:code, :options)
+ Advice = Struct.new(:code, :options)
- # Apply the advices to the target class.
+ # Apply the advices to the target class.
- 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 <<-end_eval, __FILE__, __LINE__
- alias_method :__unwrapped_#{m}, :#{m}
- def #{m}(#{args})
- #{gen_advice_code(m, target.advices, :pre)}
- __unwrapped_#{m}(#{args})
- #{gen_advice_code(m, target.advices, :post)}
- end
- end_eval
- end
- end
+ 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 <<-end_eval, __FILE__, __LINE__
+ alias_method :__unwrapped_#{m}, :#{m}
+ def #{m}(#{args})
+ #{gen_advice_code(m, target.advices, :pre)}
+ __unwrapped_#{m}(#{args})
+ #{gen_advice_code(m, target.advices, :post)}
+ end
+ end_eval
+ end
+ end
- # Include Modules that define advices.
+ # Include Modules that define advices.
- def self.include_advice_modules(target)
- 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 }
+ def self.include_advice_modules(target)
+ 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)
- target.advices << Advice.new(method, options)
- end
-
- method = (a.options[:post] || 'post').to_s
- if a.code.instance_methods.include?(method)
- options.update(:where => :append, :join => :post)
- target.advices << Advice.new(method, options)
- end
- end
- end
+ method = (a.options[:pre] || 'pre').to_s
+ if a.code.instance_methods.include?(method)
+ options.update(:where => :prepend, :join => :pre)
+ target.advices << Advice.new(method, options)
+ end
+
+ method = (a.options[:post] || 'post').to_s
+ if a.code.instance_methods.include?(method)
+ options.update(:where => :append, :join => :post)
+ target.advices << Advice.new(method, options)
+ end
+ end
+ end
- # Remove the original advice.
+ # Remove the original advice.
- target.advices.delete_if do |a|
- a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
- end
- end
+ target.advices.delete_if do |a|
+ a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
+ end
+ end
- # Generates the code to call the aspects.
-
- def self.gen_advice_code(method, advices, join = :pre) # :nodoc:
- code = ''
+ # Generates the code to call the aspects.
+
+ def self.gen_advice_code(method, advices, join = :pre) # :nodoc:
+ code = ''
- advices.each_with_index do |advice, idx|
- o = options = advice.options
+ advices.each_with_index do |advice, idx|
+ o = options = advice.options
- if only = options[:only] || options[:on]
- next unless [only].flatten.include?(method.to_sym)
- elsif except = options[:except]
- next if [except].flatten.include?(method.to_sym)
- end
-
- advice = advice.code
+ if only = options[:only] || options[:on]
+ next unless [only].flatten.include?(method.to_sym)
+ elsif except = options[:except]
+ next if [except].flatten.include?(method.to_sym)
+ end
+
+ advice = advice.code
- if advice.is_a?(Symbol) or advice.is_a?(String)
- next if o[:join] != join
- code << "#{advice}; "
- elsif advice.respond_to?('call')
- next if o[:join] != join
- code << "self.class.advices[#{idx}].code.call(self); "
- elsif advice.is_a?(Class)
- if advice.class.ancestors.include?(Class)
- if m = o[join] and advice.methods.include?(m.to_s)
- code << "#{advice}.#{m}(self); "
- end
- else
- # Module, allready handled.
- end
- else
- if m = o[join] and advice.methods.include?(m.to_s)
- code << "self.class.advices[#{idx}].code.#{m}(self); "
- end
- end
- end
-
- return code
- end
+ if advice.is_a?(Symbol) or advice.is_a?(String)
+ next if o[:join] != join
+ code << "#{advice}; "
+ elsif advice.respond_to?('call')
+ next if o[:join] != join
+ code << "self.class.advices[#{idx}].code.call(self); "
+ elsif advice.is_a?(Class)
+ if advice.class.ancestors.include?(Class)
+ if m = o[join] and advice.methods.include?(m.to_s)
+ code << "#{advice}.#{m}(self); "
+ end
+ else
+ # Module, allready handled.
+ end
+ else
+ if m = o[join] and advice.methods.include?(m.to_s)
+ code << "self.class.advices[#{idx}].code.#{m}(self); "
+ end
+ end
+ end
+
+ return code
+ end
- def self.append_features(base)
- super
- base.extend(ClassMethods)
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
- base.module_eval %{
- Glue::PropertyUtils.enchant(self)
+ base.module_eval %{
+ Glue::PropertyUtils.enchant(self)
- def self.advices
- __meta[:advices] || []
- end
+ def self.advices
+ __meta[:advices] || []
+ end
- def self.advices=(advices)
- __meta[:advices] = advices
- end
-
- #def self.inherited(child)
- # super
- # child.send(:include, Aspects)
- #end
- #
- #def self.append_features(base)
- # super
- # base.send(:include, Aspects)
- #end
- }
- end
+ def self.advices=(advices)
+ __meta[:advices] = advices
+ end
+ }
+ end
- module ClassMethods
-
- # Add a pre (before) advice.
+ module ClassMethods
+
+ # Add a pre (before) advice.
- def pre(*args, &block)
- o = options = {
- :join => :pre,
- :where => :prepend,
- }
- options.update(args.pop) if args.last.is_a?(Hash)
+ def pre(*args, &block)
+ o = options = {
+ :join => :pre,
+ :where => :prepend,
+ }
+ options.update(args.pop) if args.last.is_a?(Hash)
- if block_given?
- advices = [ Advice.new(block, options) ]
- else
- advices = args.collect { |a| Advice.new(a, options) }
- end
-
- if options[:where] == :prepend
- self.advices = advices + self.advices
- else
- self.advices = self.advices + advices
- end
- end
- alias_method :before, :pre
-
- # Add a post (after) advice.
+ if block_given?
+ advices = [ Advice.new(block, options) ]
+ else
+ advices = args.collect { |a| Advice.new(a, options) }
+ end
+
+ if options[:where] == :prepend
+ self.advices = advices + self.advices
+ else
+ self.advices = self.advices + advices
+ end
+ end
+ alias_method :before, :pre
+
+ # Add a post (after) advice.
- def post(*args, &block)
- o = options = {
- :join => :post,
- :where => :append,
- }
- options.update(args.pop) if args.last.is_a?(Hash)
+ def post(*args, &block)
+ o = options = {
+ :join => :post,
+ :where => :append,
+ }
+ options.update(args.pop) if args.last.is_a?(Hash)
- if block_given?
- advices = [ Advice.new(block, options) ]
- else
- advices = args.collect { |a| Advice.new(a, options) }
- end
-
- if options[:where] == :prepend
- self.advices = advices + self.advices
- else
- self.advices = self.advices + advices
- end
- end
- alias_method :after, :post
+ if block_given?
+ advices = [ Advice.new(block, options) ]
+ else
+ advices = args.collect { |a| Advice.new(a, options) }
+ end
+
+ if options[:where] == :prepend
+ self.advices = advices + self.advices
+ else
+ self.advices = self.advices + advices
+ end
+ end
+ alias_method :after, :post
- # Add a wrap (arround) aspect. An aspect is a class that
- # responds to the before and after advices.
-
- def wrap(*args)
- o = options = {
- :pre => :pre,
- :post => :post
- }
- options.update(args.pop) if args.last.is_a?(Hash)
+ # Add a wrap (arround) aspect. An aspect is a class that
+ # responds to the before and after advices.
+
+ def wrap(*args)
+ o = options = {
+ :pre => :pre,
+ :post => :post
+ }
+ options.update(args.pop) if args.last.is_a?(Hash)
- for aspect in args
- self.advices << Advice.new(aspect, options)
- end
- end
- alias_method :around, :wrap
- alias_method :observer, :wrap
+ for aspect in args
+ self.advices << Advice.new(aspect, options)
+ end
+ end
+ alias_method :around, :wrap
+ alias_method :observer, :wrap
- end
+ end
end
end