/usr/lib/ruby/vendor_ruby/innate/helper/aspect.rb is in ruby-innate 2013.02.21-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | module Innate
module Helper
##
# The Aspect helper allows you to execute hooks before or after a number of
# actions.
#
# See {Innate::Helper::Aspect::SingletonMethods} for more details on the
# various hooks available.
#
# @example Querying a database before a number of actions.
# class Posts
# include Innate::Node
#
# map '/'
# helper :aspect
#
# before(:index, :other) do
# @posts = Post.all
# end
#
# def index
# return @posts
# end
#
# def other
# return @posts[0]
# end
# end
#
# This helper is essential for proper working of {Action#render}.
#
module Aspect
##
# Hash containing the various hooks to call for certain actions.
#
AOP = Hash.new { |h,k| h[k] = Hash.new { |hh,kk| hh[kk] = {} } }
##
# Called whenever this helper is included into a class.
#
# @param [Class] into The class the module was included into.
#
def self.included(into)
into.extend(SingletonMethods)
into.add_action_wrapper(5.0, :aspect_wrap)
end
# Consider objects that have Aspect included
def self.ancestral_aop(from)
aop = {}
from.ancestors.reverse.each do |anc|
aop.merge!(AOP[anc]) if anc < Aspect
end
aop
end
##
# Calls the aspect for a given position and name.
#
# @param [#to_sym] position The position of the hook, e.g. :before_all.
# @param [#to_sym] name The name of the method for which to call the hook.
#
def aspect_call(position, name)
return unless aop = Aspect.ancestral_aop(self.class)
return unless block = at_position = aop[position]
block = at_position[name.to_sym] unless at_position.is_a?(Proc)
instance_eval(&block) if block
end
##
# Wraps the specified action between various hooks.
#
# @param [Innate::Action] action The action to wrap.
#
def aspect_wrap(action)
return yield unless method = action.name
aspect_call(:before_all, method)
aspect_call(:before, method)
result = yield
aspect_call(:after, method)
aspect_call(:after_all, method)
result
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
#
def wrap_action_call(action, &block)
return yield if action.options[:is_layout]
wrap = SortedSet.new
action.node.ancestral_trait_values(:wrap).each{|sset| wrap.merge(sset) }
head, *tail = wrap.map{|k,v| v }
tail.reverse!
combined = tail.inject(block){|s,v| lambda{ __send__(v, action, &s) } }
__send__(head, action, &combined)
end
##
# Module containing various methods that will be made available as class
# methods to the class that included {Innate::Helper::Aspect}.
#
module SingletonMethods
include Traited
##
# Hook that is called before all the actions in a node.
#
# @example
# class MainController
# include Innate::Node
#
# map '/'
#
# helper :aspect
#
# before_all do
# puts 'Executed before all actions'
# end
#
# def index
# return 'Hello, Innate!'
# end
# end
#
def before_all(&block)
AOP[self][:before_all] = block
end
##
# Hook that is called before a specific list of actions.
#
# @example
# class MainController
# include Innate::Node
#
# map '/'
#
# helper :aspect
#
# before(:index, :other) do
# puts 'Executed before specific actions only.'
# end
#
# def index
# return 'Hello, Innate!'
# end
#
# def other
# return 'Other method'
# end
# end
#
def before(*names, &block)
names.each{|name| AOP[self][:before][name] = block }
end
##
# Hook that is called after all the actions in a node.
#
# @example
# class MainController
# include Innate::Node
#
# map '/'
#
# helper :aspect
#
# after_all do
# puts 'Executed after all actions'
# end
#
# def index
# return 'Hello, Innate!'
# end
# end
#
def after_all(&block)
AOP[self][:after_all] = block
end
##
# Hook that is called after a specific list of actions.
#
# @example
# class MainController
# include Innate::Node
#
# map '/'
#
# helper :aspect
#
# after(:index, :other) do
# puts 'Executed after specific actions only.'
# end
#
# def index
# return 'Hello, Innate!'
# end
#
# def other
# return 'Other method'
# end
# end
#
def after(*names, &block)
names.each{|name| AOP[self][:after][name] = block }
end
##
# Wraps the block around the list of actions resulting in the block
# being called both before and after each action.
#
# @example
# class MainController
# include Innate::Node
#
# map '/'
#
# helper :aspect
#
# wrap(:index) do
# puts 'Wrapped around the index method'
# end
#
# def index
# return 'Hello, Innate!'
# end
#
# def other
# return 'Other method'
# end
# end
#
def wrap(*names, &block)
before(*names, &block)
after(*names, &block)
end
def add_action_wrapper(order, method_name)
if wrap = trait[:wrap]
wrap.merge(SortedSet[[order, method_name.to_s]])
else
trait :wrap => SortedSet[[order, method_name.to_s]]
end
end
end # SingletonMethods
end # Aspect
end # Helper
end # Innate
|