aspect4r 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/NOTES.rdoc +42 -0
- data/README.rdoc +70 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/aspect4r.gemspec +108 -0
- data/examples/after_example.rb +30 -0
- data/examples/around_example.rb +29 -0
- data/examples/before_example.rb +62 -0
- data/examples/combined_example.rb +39 -0
- data/lib/aspect4r/after.rb +29 -0
- data/lib/aspect4r/around.rb +29 -0
- data/lib/aspect4r/base.rb +32 -0
- data/lib/aspect4r/before.rb +37 -0
- data/lib/aspect4r/classic.rb +12 -0
- data/lib/aspect4r/errors.rb +5 -0
- data/lib/aspect4r/extensions/class_extension.rb +20 -0
- data/lib/aspect4r/extensions/module_extension.rb +30 -0
- data/lib/aspect4r/helper.rb +171 -0
- data/lib/aspect4r/model/advice.rb +29 -0
- data/lib/aspect4r/model/advice_metadata.rb +27 -0
- data/lib/aspect4r/model/advices_for_method.rb +45 -0
- data/lib/aspect4r/model/aspect_data.rb +19 -0
- data/lib/aspect4r/return_this.rb +9 -0
- data/lib/aspect4r.rb +10 -0
- data/spec/aspect4r/after_spec.rb +121 -0
- data/spec/aspect4r/around_spec.rb +128 -0
- data/spec/aspect4r/before_spec.rb +148 -0
- data/spec/aspect4r/class_inheritance_spec.rb +254 -0
- data/spec/aspect4r/classic_spec.rb +44 -0
- data/spec/aspect4r/helper_spec.rb +117 -0
- data/spec/aspect4r/inheritance_inclusion_combined_spec.rb +98 -0
- data/spec/aspect4r/module_inclusion_spec.rb +208 -0
- data/spec/aspect4r/super_in_method_spec.rb +118 -0
- data/spec/aspect4r_spec.rb +295 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -0
- data/test/after_test.rb +30 -0
- data/test/around_test.rb +28 -0
- data/test/before_test.rb +28 -0
- data/test/combined_test.rb +40 -0
- data/test/method_invocation_test.rb +28 -0
- data/test/test_helper.rb +9 -0
- metadata +147 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Aspect4r
|
4
|
+
module Helper
|
5
|
+
def self.find_available_method_name klass, method_name_prefix
|
6
|
+
0.upto(10000) do |i|
|
7
|
+
m = "#{method_name_prefix}#{i}_#{klass.hash}"
|
8
|
+
return m unless klass.private_instance_methods(false).include?(m)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.creating_method?
|
13
|
+
@creating_method
|
14
|
+
end
|
15
|
+
|
16
|
+
# Store original method in aspect data and refer to it whenever recreating method
|
17
|
+
def self.process_advice meta_data, klass_or_module, *methods, &block
|
18
|
+
methods.flatten!
|
19
|
+
|
20
|
+
options = meta_data.default_options.clone
|
21
|
+
options.merge!(methods.pop) if methods.last.is_a? Hash
|
22
|
+
options.merge!(meta_data.mandatory_options)
|
23
|
+
|
24
|
+
if block_given?
|
25
|
+
with_method = find_available_method_name klass_or_module, meta_data.with_method_prefix
|
26
|
+
klass_or_module.send :define_method, with_method, &block
|
27
|
+
klass_or_module.send :private, with_method
|
28
|
+
else
|
29
|
+
with_method = methods.pop
|
30
|
+
end
|
31
|
+
|
32
|
+
methods.each do |method|
|
33
|
+
method = method.to_sym
|
34
|
+
klass_or_module.a4r_data.methods_with_advices << method
|
35
|
+
|
36
|
+
aspect = klass_or_module.a4r_data[method] ||= Aspect4r::Model::AdvicesForMethod.new(method)
|
37
|
+
aspect.add Aspect4r::Model::Advice.new(meta_data.advice_type, with_method, options)
|
38
|
+
|
39
|
+
if not aspect.wrapped_method and klass_or_module.instance_methods.include?(method.to_s)
|
40
|
+
aspect.wrapped_method = klass_or_module.instance_method(method)
|
41
|
+
end
|
42
|
+
|
43
|
+
create_method klass_or_module, method if aspect.wrapped_method
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# method - target method
|
48
|
+
def self.create_method klass, method
|
49
|
+
@creating_method = true
|
50
|
+
|
51
|
+
aspect = klass.a4r_data[method.to_sym]
|
52
|
+
|
53
|
+
if aspect.nil? or aspect.empty?
|
54
|
+
# There is no aspect defined.
|
55
|
+
@creating_method = nil
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
grouped_advices = []
|
60
|
+
inner_most = true
|
61
|
+
|
62
|
+
aspect.advices.each do |advice|
|
63
|
+
if advice.around? and not grouped_advices.empty?
|
64
|
+
# wrap up advices before current advice
|
65
|
+
create_method_for_before_after_advices klass, method, grouped_advices, inner_most
|
66
|
+
|
67
|
+
inner_most = false
|
68
|
+
|
69
|
+
grouped_advices = []
|
70
|
+
end
|
71
|
+
|
72
|
+
# handle current advice
|
73
|
+
if advice.around?
|
74
|
+
create_method_for_around_advice klass, method, advice, inner_most
|
75
|
+
inner_most = false
|
76
|
+
else
|
77
|
+
grouped_advices << advice
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# create wrap method for before/after advices which are not wrapped inside around advice.
|
82
|
+
unless grouped_advices.empty?
|
83
|
+
create_method_for_before_after_advices klass, method, grouped_advices, inner_most unless grouped_advices.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
@creating_method = nil
|
87
|
+
end
|
88
|
+
|
89
|
+
# method
|
90
|
+
# advice
|
91
|
+
WRAP_METHOD_TEMPLATE = ERB.new <<-CODE, nil, '<>'
|
92
|
+
<% if inner_most %>
|
93
|
+
wrapped_method = a4r_data[:<%= method %>].wrapped_method
|
94
|
+
<% else %>
|
95
|
+
wrapped_method = instance_method(:<%= method %>)
|
96
|
+
<% end %>
|
97
|
+
|
98
|
+
define_method :<%= method %> do |*args|
|
99
|
+
<% if advice.options[:method_name_arg] %>
|
100
|
+
result = <%= advice.with_method %> '<%= method %>', wrapped_method, *args
|
101
|
+
<% else %>
|
102
|
+
result = <%= advice.with_method %> wrapped_method, *args
|
103
|
+
<% end %>
|
104
|
+
|
105
|
+
result
|
106
|
+
end
|
107
|
+
CODE
|
108
|
+
|
109
|
+
def self.create_method_for_around_advice klass, method, advice, inner_most
|
110
|
+
code = WRAP_METHOD_TEMPLATE.result(binding)
|
111
|
+
# puts code
|
112
|
+
klass.class_eval code, __FILE__
|
113
|
+
end
|
114
|
+
|
115
|
+
# method
|
116
|
+
# before_advices
|
117
|
+
# after_advices
|
118
|
+
METHOD_TEMPLATE = ERB.new <<-CODE, nil, '<>'
|
119
|
+
<% if inner_most %>
|
120
|
+
wrapped_method = a4r_data[:<%= method %>].wrapped_method
|
121
|
+
<% else %>
|
122
|
+
wrapped_method = instance_method(:<%= method %>)
|
123
|
+
<% end %>
|
124
|
+
|
125
|
+
define_method :<%= method %> do |*args|
|
126
|
+
result = nil
|
127
|
+
|
128
|
+
# Before advices
|
129
|
+
<% before_advices.each do |definition| %>
|
130
|
+
<% if definition.options[:method_name_arg] %>
|
131
|
+
result = <%= definition.with_method %> '<%= method %>', *args
|
132
|
+
<% else %>
|
133
|
+
result = <%= definition.with_method %> *args
|
134
|
+
<% end %>
|
135
|
+
|
136
|
+
return result.value if result.is_a? ReturnThis
|
137
|
+
<% if definition.options[:skip_if_false] %>
|
138
|
+
return unless result
|
139
|
+
<% end %>
|
140
|
+
<% end %>
|
141
|
+
|
142
|
+
# Call wrapped method
|
143
|
+
result = wrapped_method.bind(self).call *args
|
144
|
+
|
145
|
+
# After advices
|
146
|
+
<% after_advices.each do |definition| %>
|
147
|
+
<% if definition.options[:method_name_arg] and definition.options[:result_arg] %>
|
148
|
+
result = <%= definition.with_method %> '<%= method %>', result, *args
|
149
|
+
<% elsif definition.options[:method_name_arg] %>
|
150
|
+
<%= definition.with_method %> '<%= method %>', *args
|
151
|
+
<% elsif definition.options[:result_arg] %>
|
152
|
+
result = <%= definition.with_method %> result, *args
|
153
|
+
<% else %>
|
154
|
+
<%= definition.with_method %> *args
|
155
|
+
<% end %>
|
156
|
+
<% end %>
|
157
|
+
|
158
|
+
result
|
159
|
+
end
|
160
|
+
CODE
|
161
|
+
|
162
|
+
def self.create_method_for_before_after_advices klass, method, advices, inner_most
|
163
|
+
before_advices = advices.select {|advice| advice.before? }
|
164
|
+
after_advices = advices.select {|advice| advice.after? }
|
165
|
+
|
166
|
+
code = METHOD_TEMPLATE.result(binding)
|
167
|
+
# puts code
|
168
|
+
klass.class_eval code, __FILE__
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Aspect4r
|
2
|
+
module Model
|
3
|
+
class Advice
|
4
|
+
BEFORE = 1
|
5
|
+
AFTER = 2
|
6
|
+
AROUND = 3
|
7
|
+
|
8
|
+
attr_accessor :type, :with_method, :options
|
9
|
+
|
10
|
+
def initialize type, with_method, options = {}
|
11
|
+
@type = type
|
12
|
+
@with_method = with_method
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def name
|
17
|
+
options[:name] || with_method
|
18
|
+
end
|
19
|
+
|
20
|
+
%w(before after around).each do |aspect|
|
21
|
+
class_eval <<-CODE
|
22
|
+
def #{aspect}?
|
23
|
+
type == #{aspect.upcase}
|
24
|
+
end
|
25
|
+
CODE
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Aspect4r
|
2
|
+
module Model
|
3
|
+
class AdviceMetadata
|
4
|
+
attr_reader :advice_type, :default_options, :mandatory_options
|
5
|
+
|
6
|
+
def initialize advice_type, default_options = {}, mandatory_options = {}
|
7
|
+
@advice_type = advice_type
|
8
|
+
@default_options = default_options || {}
|
9
|
+
@mandatory_options = mandatory_options || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_method_prefix
|
13
|
+
case advice_type
|
14
|
+
when Aspect4r::Model::Advice::BEFORE then "a4r_before_"
|
15
|
+
when Aspect4r::Model::Advice::AFTER then "a4r_after_"
|
16
|
+
when Aspect4r::Model::Advice::AROUND then "a4r_around_"
|
17
|
+
else raise "Aspect4r internal error."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
BEFORE = new Aspect4r::Model::Advice::BEFORE, nil, :skip_if_false => false
|
22
|
+
BEFORE_FILTER = new Aspect4r::Model::Advice::BEFORE, nil, :skip_if_false => true
|
23
|
+
AFTER = new Aspect4r::Model::Advice::AFTER, :result_arg => true
|
24
|
+
AROUND = new Aspect4r::Model::Advice::AROUND
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Aspect4r
|
2
|
+
module Model
|
3
|
+
class AdvicesForMethod
|
4
|
+
attr_reader :method
|
5
|
+
attr_accessor :wrapped_method
|
6
|
+
|
7
|
+
def initialize method
|
8
|
+
@method = method
|
9
|
+
end
|
10
|
+
|
11
|
+
def advices
|
12
|
+
@advices ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def add new_advice
|
16
|
+
advices << new_advice unless include?(new_advice)
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?
|
20
|
+
@advices.nil? or @advices.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def include? new_advice
|
24
|
+
advices.detect { |advice| advice.name == new_advice.name }
|
25
|
+
end
|
26
|
+
|
27
|
+
def merge! another
|
28
|
+
unless another.nil? or another.empty?
|
29
|
+
another.advices.each do |advice|
|
30
|
+
advices.push advice unless include?(advice)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def clone
|
38
|
+
o = self.class.new(method)
|
39
|
+
o.advices.push *advices unless empty?
|
40
|
+
|
41
|
+
o
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Aspect4r
|
4
|
+
module Model
|
5
|
+
class AspectData < Hash
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def advices
|
11
|
+
@advices ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def methods_with_advices
|
15
|
+
@methods_with_advices ||= Set.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/aspect4r.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'aspect4r/before'
|
2
|
+
require 'aspect4r/after'
|
3
|
+
require 'aspect4r/around'
|
4
|
+
|
5
|
+
module Aspect4r
|
6
|
+
def self.included(base)
|
7
|
+
base.send(:include, Base::InstanceMethods)
|
8
|
+
base.extend Base::ClassMethods, Before::ClassMethods, After::ClassMethods, Around::ClassMethods
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Aspect4r::After do
|
4
|
+
before do
|
5
|
+
@klass = Class.new do
|
6
|
+
include Aspect4r::After
|
7
|
+
|
8
|
+
attr_accessor :value
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@value = 'init'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test value
|
15
|
+
@value = value
|
16
|
+
'test_return'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should run advice method after original method" do
|
22
|
+
@klass.class_eval do
|
23
|
+
def do_something result, value
|
24
|
+
'do_something'
|
25
|
+
end
|
26
|
+
|
27
|
+
after :test, :do_something
|
28
|
+
end
|
29
|
+
|
30
|
+
o = @klass.new
|
31
|
+
o.test('something').should == 'do_something'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should run advice block after original method" do
|
35
|
+
i = 100
|
36
|
+
|
37
|
+
@klass.class_eval do
|
38
|
+
after :test do |result, value|
|
39
|
+
i = 200
|
40
|
+
'after_test'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
o = @klass.new
|
45
|
+
o.test('something').should == 'after_test'
|
46
|
+
|
47
|
+
o.value.should == 'something'
|
48
|
+
|
49
|
+
i.should == 200
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should flatten arguments" do
|
53
|
+
i = 100
|
54
|
+
|
55
|
+
@klass.class_eval do
|
56
|
+
after [:test] do |result, value|
|
57
|
+
i = 200
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
o = @klass.new
|
62
|
+
o.test('something')
|
63
|
+
|
64
|
+
i.should == 200
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have access to instance variables inside advice block" do
|
68
|
+
@klass.class_eval do
|
69
|
+
after :test do |result, value|
|
70
|
+
@var = 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
o = @klass.new
|
75
|
+
o.test('something')
|
76
|
+
|
77
|
+
o.instance_variable_get(:@var).should == 1
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should pass method name to advice block(or method) as first arg if method_name_arg is true" do
|
81
|
+
s = nil
|
82
|
+
|
83
|
+
@klass.class_eval do
|
84
|
+
after :test, :method_name_arg => true do |method, result, value|
|
85
|
+
s = method
|
86
|
+
result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
o = @klass.new
|
91
|
+
o.test('something')
|
92
|
+
|
93
|
+
s.should == 'test'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should pass result to advice method(or block) and return modified result" do
|
97
|
+
@klass.class_eval do
|
98
|
+
def do_something result, value
|
99
|
+
result + ' enhanced'
|
100
|
+
end
|
101
|
+
|
102
|
+
after :test, :do_something
|
103
|
+
end
|
104
|
+
|
105
|
+
o = @klass.new
|
106
|
+
o.test('something').should == 'test_return enhanced'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not pass result and not change result if result_arg is set to false" do
|
110
|
+
@klass.class_eval do
|
111
|
+
def do_something value
|
112
|
+
'do_something'
|
113
|
+
end
|
114
|
+
|
115
|
+
after :test, :do_something, :result_arg => false
|
116
|
+
end
|
117
|
+
|
118
|
+
o = @klass.new
|
119
|
+
o.test('something').should == 'test_return'
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Aspect4r::Around do
|
4
|
+
before do
|
5
|
+
@klass = Class.new do
|
6
|
+
include Aspect4r::Around
|
7
|
+
|
8
|
+
attr_accessor :value
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@value = 'init'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test value
|
15
|
+
@value = value
|
16
|
+
'test_return'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should run advice method instead of original method" do
|
22
|
+
@klass.class_eval do
|
23
|
+
def do_something orig, value
|
24
|
+
raise 'error'
|
25
|
+
end
|
26
|
+
|
27
|
+
around :test, :do_something
|
28
|
+
end
|
29
|
+
|
30
|
+
o = @klass.new
|
31
|
+
lambda { o.test('something') }.should raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should run advice block instead of original method" do
|
35
|
+
i = 100
|
36
|
+
|
37
|
+
@klass.class_eval do
|
38
|
+
around :test do |orig, value|
|
39
|
+
i = 200
|
40
|
+
'around_block_return'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
o = @klass.new
|
45
|
+
o.test('something').should == 'around_block_return'
|
46
|
+
|
47
|
+
o.value.should == 'init'
|
48
|
+
|
49
|
+
i.should == 200
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should flatten arguments" do
|
53
|
+
i = 100
|
54
|
+
|
55
|
+
@klass.class_eval do
|
56
|
+
around [:test] do |orig, value|
|
57
|
+
i = 200
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
o = @klass.new
|
62
|
+
o.test('something')
|
63
|
+
|
64
|
+
i.should == 200
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have access to instance variables inside advice block" do
|
68
|
+
@klass.class_eval do
|
69
|
+
around :test do |orig, value|
|
70
|
+
@var = 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
o = @klass.new
|
75
|
+
o.test('something')
|
76
|
+
|
77
|
+
o.instance_variable_get(:@var).should == 1
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be able to invoke original method from advice block" do
|
81
|
+
i = 100
|
82
|
+
|
83
|
+
@klass.class_eval do
|
84
|
+
around :test do |proxy, value|
|
85
|
+
i = 200
|
86
|
+
a4r_invoke proxy, value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
o = @klass.new
|
91
|
+
o.test('something').should == 'test_return'
|
92
|
+
|
93
|
+
o.value.should == 'something'
|
94
|
+
|
95
|
+
i.should == 200
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should be able to invoke original method from advice method" do
|
99
|
+
@klass.class_eval do
|
100
|
+
def do_something proxy, value
|
101
|
+
a4r_invoke proxy, value
|
102
|
+
end
|
103
|
+
|
104
|
+
around :test, :do_something
|
105
|
+
end
|
106
|
+
|
107
|
+
o = @klass.new
|
108
|
+
o.test('something').should == 'test_return'
|
109
|
+
|
110
|
+
o.value.should == 'something'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should pass method name to advice block(or method) as first arg if method_name_arg is true" do
|
114
|
+
s = nil
|
115
|
+
|
116
|
+
@klass.class_eval do
|
117
|
+
around :test, :method_name_arg => true do |method, proxy, value|
|
118
|
+
s = method
|
119
|
+
a4r_invoke proxy, value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
o = @klass.new
|
124
|
+
o.test('something')
|
125
|
+
|
126
|
+
s.should == 'test'
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Aspect4r::Before do
|
4
|
+
before do
|
5
|
+
@klass = Class.new do
|
6
|
+
include Aspect4r::Before
|
7
|
+
|
8
|
+
attr :value
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@value = 'init'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test value
|
15
|
+
@value = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should run advice method before original method" do
|
21
|
+
@klass.class_eval do
|
22
|
+
def do_something value
|
23
|
+
raise 'error'
|
24
|
+
end
|
25
|
+
|
26
|
+
before :test, :do_something
|
27
|
+
end
|
28
|
+
|
29
|
+
o = @klass.new
|
30
|
+
lambda { o.test('something') }.should raise_error('error')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should run advice block before original method" do
|
34
|
+
i = 100
|
35
|
+
|
36
|
+
@klass.class_eval do
|
37
|
+
before :test do |value|
|
38
|
+
i = 200
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
o = @klass.new
|
43
|
+
o.test('something').should == 'something'
|
44
|
+
|
45
|
+
o.value.should == 'something'
|
46
|
+
|
47
|
+
i.should == 200
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should flatten arguments" do
|
51
|
+
i = 100
|
52
|
+
|
53
|
+
@klass.class_eval do
|
54
|
+
before [:test] do |value|
|
55
|
+
i = 200
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
o = @klass.new
|
60
|
+
o.test('something').should == 'something'
|
61
|
+
|
62
|
+
o.value.should == 'something'
|
63
|
+
|
64
|
+
i.should == 200
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have access to instance variables inside advice block" do
|
68
|
+
@klass.class_eval do
|
69
|
+
before :test do |value|
|
70
|
+
@var = 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
o = @klass.new
|
75
|
+
o.test('something')
|
76
|
+
|
77
|
+
o.instance_variable_get(:@var).should == 1
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not skip method if before advice returned false" do
|
81
|
+
@klass.class_eval do
|
82
|
+
before :test do |value|
|
83
|
+
false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
o = @klass.new
|
88
|
+
o.test('something')
|
89
|
+
|
90
|
+
o.value.should == 'something'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should pass method name as first arg to before advice block(or method) if method_name_arg is true" do
|
94
|
+
s = nil
|
95
|
+
|
96
|
+
@klass.class_eval do
|
97
|
+
before :test, :method_name_arg => true do |method, value|
|
98
|
+
s = method
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
o = @klass.new
|
103
|
+
o.test('something')
|
104
|
+
|
105
|
+
s.should == 'test'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should skip original method if before advice returned instance of ReturnThis" do
|
109
|
+
@klass.class_eval do
|
110
|
+
def do_something value
|
111
|
+
Aspect4r::ReturnThis.new('do_something')
|
112
|
+
end
|
113
|
+
|
114
|
+
before :test, :do_something
|
115
|
+
end
|
116
|
+
|
117
|
+
o = @klass.new
|
118
|
+
o.test('something').should == 'do_something'
|
119
|
+
|
120
|
+
o.value.should == 'init'
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should skip original method if before_filter advice returned false" do
|
124
|
+
@klass.class_eval do
|
125
|
+
before_filter :test do
|
126
|
+
false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
o = @klass.new
|
131
|
+
o.test('something').should be_false
|
132
|
+
|
133
|
+
o.value.should == 'init'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should not skip original method if before_filter did not return false or nil" do
|
137
|
+
@klass.class_eval do
|
138
|
+
before_filter :test do
|
139
|
+
true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
o = @klass.new
|
144
|
+
o.test('something')
|
145
|
+
|
146
|
+
o.value.should == 'something'
|
147
|
+
end
|
148
|
+
end
|