Module: Orientdb4r::Aop2::ClassMethods2

Defined in:
lib/orientdb4r/utils.rb

Instance Method Summary collapse

Instance Method Details

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

!!



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

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



104
105
106
# File 'lib/orientdb4r/utils.rb', line 104

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

#around(original_method, *hooks) ⇒ Object



107
108
109
# File 'lib/orientdb4r/utils.rb', line 107

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

#before(original_method, *hooks) ⇒ Object



101
102
103
# File 'lib/orientdb4r/utils.rb', line 101

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

#init_aop_extensionObject



76
77
78
79
80
81
82
83
84
85
# File 'lib/orientdb4r/utils.rb', line 76

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



162
163
164
165
166
167
168
# File 'lib/orientdb4r/utils.rb', line 162

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



159
160
161
# File 'lib/orientdb4r/utils.rb', line 159

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)


94
95
96
97
# File 'lib/orientdb4r/utils.rb', line 94

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



86
87
88
89
90
# File 'lib/orientdb4r/utils.rb', line 86

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

#redefine_method(orig_method) ⇒ Object



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

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

!!



117
118
119
# File 'lib/orientdb4r/utils.rb', line 117

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