Provides before/after wrappers for actions
This helper is essential for proper working of {Action#render}.
Consider objects that have Aspect included
# File lib/innate/helper/aspect.rb, line 16 16: def self.ancestral_aop(from) 17: aop = {} 18: from.ancestors.reverse.map{|anc| aop.merge!(AOP[anc]) if anc < Aspect } 19: aop 20: end
# File lib/innate/helper/aspect.rb, line 22 22: def aspect_call(position, name) 23: return unless aop = Aspect.ancestral_aop(self.class) 24: return unless block = at_position = aop[position] 25: 26: block = at_position[name.to_sym] unless at_position.is_a?(Proc) 27: 28: instance_eval(&block) if block 29: end
# File lib/innate/helper/aspect.rb, line 31 31: def aspect_wrap(action) 32: return yield unless method = action.name 33: 34: aspect_call(:before_all, method) 35: aspect_call(:before, method) 36: result = yield 37: aspect_call(:after, method) 38: aspect_call(:after_all, method) 39: 40: result 41: end
This awesome piece of hackery implements action AOP.
The so-called aspects are simply methods that may yield the next aspect in the chain, this is similar to racks concept of middleware, but instead of initializing with an app we simply pass a block that may be yielded with the action being processed.
This gives us things like logging, caching, aspects, authentication, etc.
Add the name of your method to the trait[:wrap] to add your own method to the wrap_action_call chain.
@example adding your method
class MyNode Innate.node '/' private def wrap_logging(action) Innate::Log.info("Executing #{action.name}") yield end trait[:wrap] end
methods may register themself in the trait[:wrap] and will be called in left-to-right order, each being passed the action instance and a block that they have to yield to continue the chain.
@param [Action] action instance that is being passed to every registered method @param [Proc] block contains the instructions to call the action method if any
@see Action#render @author manveru
# File lib/innate/helper/aspect.rb, line 81 81: def wrap_action_call(action, &block) 82: return yield if action.options[:is_layout] 83: wrap = SortedSet.new 84: action.node.ancestral_trait_values(:wrap).each{|sset| wrap.merge(sset) } 85: head, *tail = wrap.map{|k,v| v } 86: tail.reverse! 87: combined = tail.inject(block){|s,v| lambda{ __send__(v, action, &s) } } 88: __send__(head, action, &combined) 89: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.