Innate::Helper::Aspect

Provides before/after wrappers for actions

This helper is essential for proper working of {Action#render}.

Constants

AOP

Public Class Methods

ancestral_aop(from) click to toggle source

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
included(into) click to toggle source
    # File lib/innate/helper/aspect.rb, line 10
10:       def self.included(into)
11:         into.extend(SingletonMethods)
12:         into.add_action_wrapper(5.0, :aspect_wrap)
13:       end

Public Instance Methods

aspect_call(position, name) click to toggle source
    # 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
aspect_wrap(action) click to toggle source
    # 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
wrap_action_call(action, &block) click to toggle source

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.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.