aspect4r 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|