aspector 0.13.1 → 0.14.0
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +26 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -11
- data/Changelog.md +59 -0
- data/Gemfile +9 -14
- data/Gemfile.lock +84 -50
- data/README.md +118 -0
- data/Rakefile +6 -22
- data/aspector.gemspec +15 -127
- data/benchmarks/after_benchmark.rb +28 -0
- data/benchmarks/around_advice_benchmark.rb +35 -0
- data/benchmarks/around_benchmark.rb +32 -0
- data/benchmarks/before_benchmark.rb +28 -0
- data/benchmarks/benchmark_helper.rb +17 -0
- data/benchmarks/combined_benchmark.rb +36 -0
- data/benchmarks/method_invocation_benchmark.rb +30 -0
- data/benchmarks/raw_benchmark.rb +39 -0
- data/examples/activerecord_hooks.rb +10 -15
- data/examples/around_example.rb +20 -31
- data/examples/aspector_apply_example.rb +10 -17
- data/examples/aspector_example.rb +7 -16
- data/examples/cache_aspect.rb +20 -30
- data/examples/design_by_contract.rb +20 -44
- data/examples/exception_handler.rb +12 -20
- data/examples/exception_handler2.rb +16 -24
- data/examples/implicit_method_option_test.rb +8 -16
- data/examples/interception_options_example.rb +71 -0
- data/examples/logging_aspect.rb +16 -24
- data/examples/process_aspector.rb +13 -0
- data/examples/retry_aspect.rb +20 -20
- data/lib/aspector.rb +17 -15
- data/lib/aspector/advice.rb +44 -57
- data/lib/aspector/advice_metadata.rb +10 -11
- data/lib/aspector/aspect_instances.rb +2 -3
- data/lib/aspector/base.rb +6 -368
- data/lib/aspector/base_class_methods.rb +24 -55
- data/lib/aspector/deferred_logic.rb +3 -4
- data/lib/aspector/deferred_option.rb +5 -10
- data/lib/aspector/interception.rb +356 -0
- data/lib/aspector/logger.rb +18 -45
- data/lib/aspector/logging.rb +10 -29
- data/lib/aspector/method_matcher.rb +5 -6
- data/lib/aspector/object_extension.rb +4 -12
- data/lib/aspector/version.rb +3 -0
- data/spec/examples_spec.rb +59 -0
- data/spec/functionals/aspect_for_multiple_targets_spec.rb +54 -0
- data/spec/functionals/aspect_interception_options_accessing_spec.rb +112 -0
- data/spec/functionals/aspect_on_a_class_spec.rb +159 -0
- data/spec/functionals/aspect_on_an_instance_spec.rb +66 -0
- data/spec/functionals/aspector_spec.rb +138 -0
- data/spec/functionals/aspects_combined_spec.rb +37 -0
- data/spec/functionals/aspects_execution_order_spec.rb +61 -0
- data/spec/functionals/aspects_on_private_methods_spec.rb +82 -0
- data/spec/spec_helper.rb +20 -21
- data/spec/support/class_builder.rb +44 -0
- data/spec/units/advice_spec.rb +49 -0
- data/spec/units/advices/after_spec.rb +328 -0
- data/spec/units/advices/around_spec.rb +336 -0
- data/spec/units/advices/before_filter_spec.rb +287 -0
- data/spec/units/advices/before_spec.rb +237 -0
- data/spec/units/advices/raw_spec.rb +67 -0
- data/spec/units/base_class_methods_spec.rb +262 -0
- data/spec/units/base_spec.rb +133 -0
- data/spec/units/deferred_logic_spec.rb +35 -0
- data/spec/units/logger_spec.rb +20 -0
- data/spec/units/logging_spec.rb +85 -0
- data/spec/units/method_matcher_spec.rb +95 -0
- data/spec/units/object_extension_spec.rb +11 -0
- data/spec/units/special_chars_spec.rb +128 -0
- metadata +98 -246
- data/.document +0 -5
- data/.rvmrc +0 -8
- data/README.rdoc +0 -80
- data/VERSION +0 -1
- data/performance-tests/after_test.rb +0 -25
- data/performance-tests/around_advice_benchmark.rb +0 -66
- data/performance-tests/around_test.rb +0 -27
- data/performance-tests/before_test.rb +0 -25
- data/performance-tests/combined_test.rb +0 -33
- data/performance-tests/method_invocation_test.rb +0 -25
- data/performance-tests/raw_test.rb +0 -37
- data/performance-tests/test_helper.rb +0 -9
- data/run_all_examples.sh +0 -12
- data/spec/functional/advices_on_private_methods_spec.rb +0 -21
- data/spec/functional/aspect_on_eigen_class_spec.rb +0 -72
- data/spec/functional/aspect_on_object_spec.rb +0 -20
- data/spec/functional/aspector_spec.rb +0 -140
- data/spec/functional/aspects_combined_spec.rb +0 -48
- data/spec/functional/execution_order_spec.rb +0 -42
- data/spec/unit/advice_spec.rb +0 -4
- data/spec/unit/after_spec.rb +0 -88
- data/spec/unit/around_spec.rb +0 -76
- data/spec/unit/base_class_methods_spec.rb +0 -28
- data/spec/unit/base_spec.rb +0 -112
- data/spec/unit/before_spec.rb +0 -125
- data/spec/unit/deferred_logic_spec.rb +0 -23
- data/spec/unit/method_matcher_spec.rb +0 -43
- data/spec/unit/raw_spec.rb +0 -53
- data/spec/unit/special_chars_spec.rb +0 -122
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Raw advices' do
|
4
|
+
subject { klass.new }
|
5
|
+
|
6
|
+
context 'standard case' do
|
7
|
+
let(:klass) do
|
8
|
+
ClassBuilder.build do
|
9
|
+
def before_exec
|
10
|
+
values << 'before_exec'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
aspector(klass) do
|
17
|
+
raw :exec do
|
18
|
+
alias_method :exec_without_aspect, :exec
|
19
|
+
|
20
|
+
def exec
|
21
|
+
values << 'exec-result'
|
22
|
+
exec_without_aspect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should execute exec_without_aspect' do
|
29
|
+
expect(subject)
|
30
|
+
.to receive(:exec_without_aspect)
|
31
|
+
.once
|
32
|
+
|
33
|
+
subject.exec
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should work' do
|
37
|
+
subject.exec
|
38
|
+
expect(subject.values).to eq %w( exec-result exec-result )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when we want to use method that is defined after aspector binding' do
|
43
|
+
let(:klass) do
|
44
|
+
ClassBuilder.build do
|
45
|
+
aspector do
|
46
|
+
raw :exec do
|
47
|
+
alias_method :exec_without_aspect, :exec
|
48
|
+
|
49
|
+
def exec
|
50
|
+
after_defined_method
|
51
|
+
exec_without_aspect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def after_defined_method
|
57
|
+
values << 'after-defined'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should be able to use it' do
|
63
|
+
subject.exec
|
64
|
+
expect(subject.values).to eq %w( after-defined exec-result )
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Aspector::Base class methods' do
|
4
|
+
subject { ClassBuilder.inherit(Aspector::Base) }
|
5
|
+
|
6
|
+
describe '.enable' do
|
7
|
+
pending
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.disable' do
|
11
|
+
pending
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.logger' do
|
15
|
+
pending
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.advices' do
|
19
|
+
pending
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.default_options' do
|
23
|
+
pending
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.apply' do
|
27
|
+
pending
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.default' do
|
31
|
+
context 'when there are no default options' do
|
32
|
+
let(:options) { { rand => rand } }
|
33
|
+
|
34
|
+
before do
|
35
|
+
subject.instance_variable_set(:'@default_options', nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should assign provided options' do
|
39
|
+
subject.send(:default, options)
|
40
|
+
|
41
|
+
expect(subject.instance_variable_get(:'@default_options')).to eq options
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when there are default options' do
|
46
|
+
let(:options) { { rand => rand } }
|
47
|
+
let(:default_options) { { rand => rand } }
|
48
|
+
|
49
|
+
before do
|
50
|
+
subject.instance_variable_set(:'@default_options', default_options)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should merge with existing options' do
|
54
|
+
subject.send(:default, options)
|
55
|
+
|
56
|
+
defaults = options.merge(default_options)
|
57
|
+
expect(subject.instance_variable_get(:'@default_options')).to eq defaults
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.before' do
|
63
|
+
subject do
|
64
|
+
ClassBuilder.inherit(Aspector::Base) do
|
65
|
+
before :test, :do_before
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
let(:advices) { subject.send(:advices) }
|
70
|
+
let(:advice) { advices.first }
|
71
|
+
|
72
|
+
it 'should create an advice' do
|
73
|
+
expect(subject.send(:advices).size).to eq 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'created advice should be a before one' do
|
77
|
+
expect(advice.before?).to eq true
|
78
|
+
expect(advice.before_filter?).to eq false
|
79
|
+
expect(advice.after?).to eq false
|
80
|
+
expect(advice.around?).to eq false
|
81
|
+
expect(advice.raw?).to eq false
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'skip_if_false for this advice should not be true' do
|
85
|
+
expect(advice.options[:skip_if_false]).not_to eq true
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should create a advice with a do_before method' do
|
89
|
+
expect(advice.with_method).to eq :do_before
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '.before_filter' do
|
94
|
+
subject do
|
95
|
+
ClassBuilder.inherit(Aspector::Base) do
|
96
|
+
before_filter :test, :do_before
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
let(:advices) { subject.send(:advices) }
|
101
|
+
let(:advice) { advices.first }
|
102
|
+
|
103
|
+
it 'should create an advice' do
|
104
|
+
expect(subject.send(:advices).size).to eq 1
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'created advice should be only a before one' do
|
108
|
+
expect(advice.before_filter?).to eq true
|
109
|
+
expect(advice.before?).to eq false
|
110
|
+
expect(advice.after?).to eq false
|
111
|
+
expect(advice.around?).to eq false
|
112
|
+
expect(advice.raw?).to eq false
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should create a advice with a do_before method' do
|
116
|
+
expect(advice.with_method).to eq :do_before
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '.after' do
|
121
|
+
subject do
|
122
|
+
ClassBuilder.inherit(Aspector::Base) do
|
123
|
+
after :test, :do_after
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
let(:advices) { subject.send(:advices) }
|
128
|
+
let(:advice) { advices.first }
|
129
|
+
|
130
|
+
it 'should create an advice' do
|
131
|
+
expect(subject.send(:advices).size).to eq 1
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'created advice should be a before one' do
|
135
|
+
expect(advice.after?).to eq true
|
136
|
+
expect(advice.before_filter?).to eq false
|
137
|
+
expect(advice.before?).to eq false
|
138
|
+
expect(advice.around?).to eq false
|
139
|
+
expect(advice.raw?).to eq false
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'skip_if_false for this advice should not be true' do
|
143
|
+
expect(advice.options[:skip_if_false]).not_to eq true
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should create a advice with a do_after method' do
|
147
|
+
expect(advice.with_method).to eq :do_after
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '.around' do
|
152
|
+
subject do
|
153
|
+
ClassBuilder.inherit(Aspector::Base) do
|
154
|
+
around :test, :do_around
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
let(:advices) { subject.send(:advices) }
|
159
|
+
let(:advice) { advices.first }
|
160
|
+
|
161
|
+
it 'should create an advice' do
|
162
|
+
expect(subject.send(:advices).size).to eq 1
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'created advice should be a around one' do
|
166
|
+
expect(advice.after?).to eq false
|
167
|
+
expect(advice.before?).to eq false
|
168
|
+
expect(advice.around?).to eq true
|
169
|
+
expect(advice.raw?).to eq false
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'skip_if_false for this advice should not be true' do
|
173
|
+
expect(advice.options[:skip_if_false]).not_to eq true
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should create a advice with a do_around method' do
|
177
|
+
expect(advice.with_method).to eq :do_around
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '.raw' do
|
182
|
+
subject do
|
183
|
+
ClassBuilder.inherit(Aspector::Base) do
|
184
|
+
raw :test do
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
let(:advices) { subject.send(:advices) }
|
190
|
+
let(:advice) { advices.first }
|
191
|
+
|
192
|
+
it 'should create an advice' do
|
193
|
+
expect(subject.send(:advices).size).to eq 1
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'created advice should be a around one' do
|
197
|
+
expect(advice.after?).to eq false
|
198
|
+
expect(advice.before_filter?).to eq false
|
199
|
+
expect(advice.before?).to eq false
|
200
|
+
expect(advice.around?).to eq false
|
201
|
+
expect(advice.raw?).to eq true
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'skip_if_false for this advice should not be true' do
|
205
|
+
expect(advice.options[:skip_if_false]).not_to eq true
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe '.target' do
|
210
|
+
context 'when there is no code and no block' do
|
211
|
+
let(:code) { nil }
|
212
|
+
|
213
|
+
it 'should raise ArgumentError' do
|
214
|
+
expect { subject.send(:target, code) }.to raise_error(ArgumentError)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'when there is code and no block given' do
|
219
|
+
let(:code) { true }
|
220
|
+
|
221
|
+
it 'should not raise ArgumentError' do
|
222
|
+
expect { subject.send(:target, code) {} }.not_to raise_error
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'when there is block given and no code' do
|
227
|
+
let(:code) { nil }
|
228
|
+
|
229
|
+
it 'should not raise ArgumentError' do
|
230
|
+
expect { subject.send(:target, code) {} }.not_to raise_error
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'when there is code and block given' do
|
235
|
+
let(:code) { true }
|
236
|
+
|
237
|
+
it 'should not raise ArgumentError' do
|
238
|
+
expect { subject.send(:target, code) {} }.not_to raise_error
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe '.options' do
|
244
|
+
it 'should return DeferredOptions instance' do
|
245
|
+
expect(subject.send(:options)).to be_kind_of Aspector::DeferredOption
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '._deferred_logics_' do
|
250
|
+
context 'when there is nothing in @deferred_logics' do
|
251
|
+
pending
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'when there is value in @deferred_logics' do
|
255
|
+
pending
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe '._create_advice_' do
|
260
|
+
pending
|
261
|
+
end
|
262
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Aspector::Base do
|
4
|
+
let(:klass) { ClassBuilder.build }
|
5
|
+
let(:aspect) do
|
6
|
+
Aspector do
|
7
|
+
before :exec do
|
8
|
+
values << 'do_before'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { klass.new }
|
14
|
+
|
15
|
+
describe 'default options' do
|
16
|
+
context 'when we create aspector with default options' do
|
17
|
+
subject do
|
18
|
+
Aspector do
|
19
|
+
default exec: 'value'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should store them' do
|
24
|
+
expect(subject.send(:default_options)[:exec]).to eq 'value'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#options' do
|
30
|
+
# They are used to access options set when aspect is applied
|
31
|
+
let(:method) { rand }
|
32
|
+
let(:aspect) do
|
33
|
+
Aspector do
|
34
|
+
before options[:methods] do
|
35
|
+
values << 'do_this'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
before do
|
41
|
+
aspect.apply(klass, methods: :exec)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should use methods block' do
|
45
|
+
subject.exec
|
46
|
+
expect(subject.values).to eq %w( do_this exec-result )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#apply' do
|
51
|
+
context 'applying to a single target' do
|
52
|
+
it 'should apply a given code to the method' do
|
53
|
+
aspect.apply(klass)
|
54
|
+
subject.exec
|
55
|
+
expect(subject.values).to eq %w( do_before exec-result )
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'applying to multiple targets at once' do
|
60
|
+
let(:klass1) { ClassBuilder.build }
|
61
|
+
let(:klass2) { ClassBuilder.build }
|
62
|
+
|
63
|
+
let(:instance1) { klass1.new }
|
64
|
+
let(:instance2) { klass2.new }
|
65
|
+
|
66
|
+
before { aspect.apply(klass1, klass2) }
|
67
|
+
|
68
|
+
it 'should apply to all the targets' do
|
69
|
+
instance1.exec
|
70
|
+
expect(instance1.values).to eq %w( do_before exec-result )
|
71
|
+
|
72
|
+
instance2.exec
|
73
|
+
expect(instance2.values).to eq %w( do_before exec-result )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when we try to apply to nonexisting method' do
|
78
|
+
let(:aspect) do
|
79
|
+
Aspector do
|
80
|
+
before options[:methods] do
|
81
|
+
# dummy advice
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should not do anything (should not fail)' do
|
87
|
+
expect { aspect.apply(klass, methods: 'not_exist') }.not_to raise_error
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#target' do
|
93
|
+
context 'adding method to targeted class/module' do
|
94
|
+
before do
|
95
|
+
aspector(klass) do
|
96
|
+
target do
|
97
|
+
def before_exec
|
98
|
+
values << 'before-exec'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
before :exec, :before_exec
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should add to target' do
|
107
|
+
subject.exec
|
108
|
+
expect(subject.values).to eq %w( before-exec exec-result )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when we provide an aspect as an argument to a #target method' do
|
113
|
+
let(:aspect_class) do
|
114
|
+
Class.new(Aspector::Base) do
|
115
|
+
target do |aspect|
|
116
|
+
define_method :before_exec do
|
117
|
+
values << "before_exec(#{aspect.class})"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
before :exec, :before_exec
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should add it to target' do
|
126
|
+
aspect_class.apply(klass)
|
127
|
+
|
128
|
+
subject.exec
|
129
|
+
expect(subject.values).to eq ["before_exec(#{aspect_class})", 'exec-result']
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|