Module: Orientdb4r::Aop2::ClassMethods2

Defined in:
lib/orientdb4r/utils.rb

Instance Method Summary collapse

Instance Method Details

#add_hook(type, original_method, *hooks) ⇒ Object

!!



137
138
139
140
141
# File 'lib/orientdb4r/utils.rb', line 137

def add_hook(type, original_method, *hooks) #!!
  Array(original_method).each do |method|
    store_hook(type, method, *hooks)
  end
end

#after(original_method, *hooks) ⇒ Object



129
130
131
# File 'lib/orientdb4r/utils.rb', line 129

def after(original_method, *hooks)
  add_hook(:after, original_method, *hooks)
end

#around(original_method, *hooks) ⇒ Object



132
133
134
# File 'lib/orientdb4r/utils.rb', line 132

def around(original_method, *hooks)
  add_hook(:around, original_method, *hooks)
end

#before(original_method, *hooks) ⇒ Object



126
127
128
# File 'lib/orientdb4r/utils.rb', line 126

def before(original_method, *hooks)
  add_hook(:before, original_method, *hooks)
end

#init_aop_extensionObject



101
102
103
104
105
106
107
108
109
110
# File 'lib/orientdb4r/utils.rb', line 101

def init_aop_extension
  @hooks = {}
  [:before, :after, :around].each { |where| @hooks[where] = Hash.new { |hash, key| hash[key] = [] }}
  # will be like this:
  # {:before=>{:disconnect=>[:assert_connected], :query=>[:assert_connected], :command=>[:assert_connected]}, :after=>{}, :around=>{}}
  class << self
    attr_reader :hooks
  end
  @@redefining = false # flag whether the process of method redefining is running
end

#invoke_arround_hooks(obj, method_name, hooks, &block) ⇒ Object



187
188
189
190
191
192
193
# File 'lib/orientdb4r/utils.rb', line 187

def invoke_arround_hooks(obj, method_name, hooks, &block)
  hook = hooks.slice! 0
  return block.call if hook.nil? # call original method if no more hook

  # invoke the hook with lambda containing recursion
  obj.send(hook.to_sym) { invoke_arround_hooks(obj, method_name, hooks, &block); }
end

#invoke_hooks(obj, hook_type, method_name) ⇒ Object



184
185
186
# File 'lib/orientdb4r/utils.rb', line 184

def invoke_hooks(obj, hook_type, method_name)
  hooks[hook_type][method_name.to_sym].each { |hook| obj.send hook }
end

#is_hooked?(method) ⇒ Boolean

—————————————————————– Helpers

Returns:

  • (Boolean)


119
120
121
122
# File 'lib/orientdb4r/utils.rb', line 119

def is_hooked?(method)
  # look into array of keys (method names) in 2nd level hashs (see above)
  hooks.values.map(&:keys).flatten.uniq.include? method
end

#method_added(method) ⇒ Object



111
112
113
114
115
# File 'lib/orientdb4r/utils.rb', line 111

def method_added(method)
  unless @@redefining # avoid recursion
    redefine_method(method) if is_hooked?(method)
  end
end

#redefine_method(orig_method) ⇒ Object



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
# File 'lib/orientdb4r/utils.rb', line 146

def redefine_method(orig_method)
  @@redefining = true

  arity = instance_method(orig_method.to_sym).arity
  params = ''
  fixed_cnt = arity.abs
  fixed_cnt -= 1 if arity < 0
  # build up a list of params
  1.upto(fixed_cnt).each {|x| params << "p#{x},"}
  params << "*argv" if arity < 0
  params.gsub!(/,$/, '') # remove last ','

  alias_method "#{orig_method}_aop2_orig".to_sym, orig_method.to_sym

  class_eval <<-FILTER,__FILE__,__LINE__ + 1
    def #{orig_method}(#{params})
      self.aop_context = { :method => '#{orig_method}', :class => self.class }
      begin
        self.class.invoke_hooks(self, :before, :#{orig_method})
        rslt = self.class.invoke_arround_hooks(self, :#{orig_method}, self.class.hooks[:around][:#{orig_method}].clone) {
          #{orig_method}_aop2_orig(#{params})
        }
        self.class.invoke_hooks(self, :after, :#{orig_method})
#            rescue Exception => e
#              # TODO use logging
#              $stderr.puts '' << e.class.name << ': ' << e.message
#              $stderr.puts e.backtrace.inspect
#              raise e
      ensure
        self.aop_context = nil
      end
      rslt
    end
  FILTER

  @@redefining = false
end

#store_hook(type, method_name, *hook_methods) ⇒ Object

!!



142
143
144
# File 'lib/orientdb4r/utils.rb', line 142

def store_hook(type, method_name, *hook_methods) #!!
  hooks[type.to_sym][method_name.to_sym] += hook_methods.flatten.map(&:to_sym)
end