Module: Aspect4r::Helper

Defined in:
lib/aspect4r/helper.rb

Constant Summary collapse

METHOD_TEMPLATE =

method before_advices after_advices

ERB.new <<-CODE, nil, '<>'
<% if inner_most %>
  wrapped_method = a4r_data.wrapped_methods['<%= method %>']
<% else %>
  wrapped_method = instance_method(:<%= method %>)
<% end %>

  define_method :<%= method %> do |*args, &block|
    result = nil

    # Before advices
<% before_advices.each do |definition| %>
<% if definition.options[:method_name_arg] %>
    result = <%= definition.with_method %> '<%= method %>', *args
<% else %>
    result = <%= definition.with_method %> *args
<% end %>

    return result.value if result.is_a? ReturnThis
<% if definition.options[:skip_if_false] %>
    return unless result
<% end %>
<% end %>

<% if around_advice %>
    # around advice
<%   if around_advice.options[:method_name_arg] %>
  result = <%= around_advice.with_method %> '<%= method %>', *args do |*args|
      wrapped_method.bind(self).call *args, &block
    end
<%   else %>
    result = <%= around_advice.with_method %> *args do |*args|
      wrapped_method.bind(self).call *args, &block
    end
<%   end %>
<% else %>
    # Invoke wrapped method
    result = wrapped_method.bind(self).call *args, &block
<% end %>

    # After advices
<% after_advices.each do |definition| %>
<% if definition.options[:method_name_arg] and definition.options[:result_arg] %>
    result = <%= definition.with_method %> '<%= method %>', result, *args
<% elsif definition.options[:method_name_arg] %>
    <%= definition.with_method %> '<%= method %>', *args
<% elsif definition.options[:result_arg] %>
    result = <%= definition.with_method %> result, *args
<% else %>
    <%= definition.with_method %> *args
<% end %>
<% end %>
    
    result
  end
CODE

Class Method Summary collapse

Class Method Details

.create_method(klass, method) ⇒ Object

method - target method



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
# File 'lib/aspect4r/helper.rb', line 67

def self.create_method klass, method
  @creating_method = true
  
  advices = klass.a4r_data.advices_for_method method
  return if advices.empty?
  
  grouped_advices = []
  group           = nil
  inner_most      = true

  advices.each do |advice|
    if ((group and group != advice.group) or advice.around?) and not grouped_advices.empty?
      create_method_with_advices klass, method, grouped_advices, inner_most
      
      grouped_advices = []
      inner_most      = false
    end
    
    grouped_advices << advice
    group           = advice.group
  end
  
  # create wrap method for before/after advices which are not wrapped inside around advice.
  create_method_with_advices klass, method, grouped_advices, inner_most unless grouped_advices.empty?
ensure
  @creating_method = nil
end

.create_method_with_advices(klass, method, advices, inner_most) ⇒ Object



155
156
157
158
159
160
161
162
163
# File 'lib/aspect4r/helper.rb', line 155

def self.create_method_with_advices klass, method, advices, inner_most
  before_advices = advices.select {|advice| advice.before? or advice.before_filter? }
  after_advices  = advices.select {|advice| advice.after?  }
  around_advice  = advices.first if advices.first.around?
  
  code = METHOD_TEMPLATE.result(binding)
  # puts code
  klass.class_eval code, __FILE__
end

.creating_method?Boolean

Returns:

  • (Boolean)


12
13
14
# File 'lib/aspect4r/helper.rb', line 12

def self.creating_method?
  @creating_method
end

.define_method(klass_or_module, *args, &block) ⇒ Object



16
17
18
19
20
21
# File 'lib/aspect4r/helper.rb', line 16

def self.define_method klass_or_module, *args, &block
  @creating_method = true
  klass_or_module.send :define_method, *args, &block
ensure
  @creating_method = false
end

.find_available_method_name(klass, method_name_prefix) ⇒ Object



5
6
7
8
9
10
# File 'lib/aspect4r/helper.rb', line 5

def self.find_available_method_name klass, method_name_prefix
  0.upto(10000) do |i|
    m = "#{method_name_prefix}#{i}_#{klass.hash}"
    return m unless klass.private_instance_methods(false).include?(m)
  end
end

.process_advice(meta_data, klass_or_module, *methods, &block) ⇒ Object

Store original method in aspect data and refer to it whenever recreating method



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
# File 'lib/aspect4r/helper.rb', line 24

def self.process_advice , klass_or_module, *methods, &block
  methods.flatten!

  options = .default_options.clone
  options.merge!(methods.pop) if methods.last.is_a? Hash
  options.merge!(.mandatory_options)

  # Convert symbols to strings to avoid inconsistencies
  methods.size.times do |i|
    methods[i] = methods[i].to_s if methods[i].is_a? Symbol
  end

  if block_given?
    with_method = find_available_method_name klass_or_module, .with_method_prefix
    klass_or_module.send :define_method, with_method, &block
    klass_or_module.send :private, with_method
  else
    with_method = methods.pop
  end
  
  a4r_data = klass_or_module.a4r_data
  advice   = Aspect4r::Model::Advice.new(.advice_type, 
                                         Aspect4r::Model::MethodMatcher.new(*methods), 
                                         with_method, 
                                         a4r_data.group, 
                                         options)
  a4r_data << advice

  methods.each do |method|
    next unless method.is_a? String
    
    wrapped_method = a4r_data.wrapped_methods[method]
    
    if not wrapped_method and klass_or_module.instance_methods.include?(method)
      wrapped_method = klass_or_module.instance_method(method)
      a4r_data.wrapped_methods[method] = wrapped_method
    end
    
    create_method klass_or_module, method if wrapped_method
  end
end