interactor 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eef8d6afd5557c08a2400afb30b40209bb17fec5
4
- data.tar.gz: 8513cec42b1bbb273b96803ec06cce6144a4078f
3
+ metadata.gz: 25b48da784666d96730a23662bfe915115ce6be9
4
+ data.tar.gz: 5c7b218d7ff5857fef8d1faf6ea9e596ac3d9d49
5
5
  SHA512:
6
- metadata.gz: 856f697f4443750d4fe95473ca44674669a8148582c5bff2dbff5ecd46d4ff5626b42c216eb4247c909c4d9bba0511d5a8bbfb50f9a6432f23f88c2a40d6be9f
7
- data.tar.gz: 3ebed0429d15e0d9faa85d345523e0f0d9c3adf90ece48c0105761f8fbc1aea833fa718f07c2a362e194499bae18f79fe1309c14d55d720b6c9183c8a576326a
6
+ metadata.gz: 8df8db25f4fd3c5dee6fee8d4440480539886d244fdb8dc19365ced9b506875966e3347cf5a4cd579042037c66242bc019961797f938d46518e701952b1edb73
7
+ data.tar.gz: b5f3f10d429f80c5f13f7bd5bc0a0c886440de435583fad49c57e28e145d2e6bb3c0085b2909077d58531d42d4cf07f7ab95bc82ca8a04fe3dbd675006e26ab1
data/README.md CHANGED
@@ -108,8 +108,100 @@ after do
108
108
  end
109
109
  ```
110
110
 
111
- **NOTE:** An interactor can define multiple before/after hooks, allowing common
112
- hooks to be extracted into interactor concerns.
111
+ #### Around Hooks
112
+
113
+ You can also define around hooks in the same way as before or after hooks, using
114
+ either a block or a symbol method name. The difference is that an around block
115
+ or method accepts a single argument. Invoking the `call` method on that argument
116
+ will continue invocation of the interactor. For example, with a block:
117
+
118
+ ```ruby
119
+ around do |interactor|
120
+ context.start_time = Time.now
121
+ interactor.call
122
+ context.finish_time = Time.now
123
+ end
124
+ ```
125
+
126
+ With a method:
127
+
128
+ ```ruby
129
+ around :time_execution
130
+
131
+ def time_execution(interactor)
132
+ context.start_time = Time.now
133
+ interactor.call
134
+ context.finish_time = Time.now
135
+ end
136
+ ```
137
+
138
+ #### Hook Sequence
139
+
140
+ Before hooks are invoked in the order in which they were defined while after
141
+ hooks are invoked in the opposite order. Around hooks are invoked outside of any
142
+ defined before and after hooks. For example:
143
+
144
+ ```ruby
145
+ around do |interactor|
146
+ puts "around before 1"
147
+ interactor.call
148
+ puts "around after 1"
149
+ end
150
+
151
+ around do |interactor|
152
+ puts "around before 2"
153
+ interactor.call
154
+ puts "around after 2"
155
+ end
156
+
157
+ before do
158
+ puts "before 1"
159
+ end
160
+
161
+ before do
162
+ puts "before 2"
163
+ end
164
+
165
+ after do
166
+ puts "after 1"
167
+ end
168
+
169
+ after do
170
+ puts "after 2"
171
+ end
172
+ ```
173
+
174
+ will output:
175
+
176
+ ```
177
+ around before 1
178
+ around before 2
179
+ before 1
180
+ before 2
181
+ after 2
182
+ after 1
183
+ around after 2
184
+ around after 1
185
+ ```
186
+
187
+ #### Interactor Concerns
188
+
189
+ An interactor can define multiple before/after hooks, allowing common hooks to
190
+ be extracted into interactor concerns.
191
+
192
+ ```ruby
193
+ module InteractorTimer
194
+ extend ActiveSupport::Concern
195
+
196
+ included do
197
+ around do |interactor|
198
+ context.start_time = Time.now
199
+ interactor.call
200
+ context.finish_time = Time.now
201
+ end
202
+ end
203
+ end
204
+ ```
113
205
 
114
206
  ### An Example Interactor
115
207
 
@@ -375,7 +467,7 @@ class AuthenticateUser
375
467
 
376
468
  def call
377
469
  if user = User.authenticate(context.email, context.password)
378
- context.user. = user
470
+ context.user = user
379
471
  context.token = user.secret_token
380
472
  else
381
473
  context.fail!(message: "authenticate_user.failure")
@@ -390,7 +482,7 @@ context.
390
482
  ```ruby
391
483
  describe AuthenticateUser do
392
484
  describe "#call" do
393
- end
485
+
394
486
  let(:interactor) { AuthenticateUser.new(email: "john@example.com", password: "secret") }
395
487
  let(:context) { interactor.context }
396
488
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "interactor"
5
- spec.version = "3.0.1"
5
+ spec.version = "3.1.0"
6
6
 
7
7
  spec.author = "Collective Idea"
8
8
  spec.email = "info@collectiveidea.com"
@@ -10,6 +10,49 @@ module Interactor
10
10
 
11
11
  # Internal: Interactor::Hooks class methods.
12
12
  module ClassMethods
13
+ # Public: Declare hooks to run around Interactor invocation. The around
14
+ # method may be called multiple times; subsequent calls append declared
15
+ # hooks to existing around hooks.
16
+ #
17
+ # hooks - Zero or more Symbol method names representing instance methods
18
+ # to be called around interactor invocation. Each instance method
19
+ # invocation receives an argument representing the next link in
20
+ # the around hook chain.
21
+ # block - An optional block to be executed as a hook. If given, the block
22
+ # is executed after methods corresponding to any given Symbols.
23
+ #
24
+ # Examples
25
+ #
26
+ # class MyInteractor
27
+ # include Interactor
28
+ #
29
+ # around :time_execution
30
+ #
31
+ # around do |interactor|
32
+ # puts "started"
33
+ # interactor.call
34
+ # puts "finished"
35
+ # end
36
+ #
37
+ # def call
38
+ # puts "called"
39
+ # end
40
+ #
41
+ # private
42
+ #
43
+ # def time_execution(interactor)
44
+ # context.start_time = Time.now
45
+ # interactor.call
46
+ # context.finish_time = Time.now
47
+ # end
48
+ # end
49
+ #
50
+ # Returns nothing.
51
+ def around(*hooks, &block)
52
+ hooks << block if block
53
+ hooks.each { |hook| around_hooks.push(hook) }
54
+ end
55
+
13
56
  # Public: Declare hooks to run before Interactor invocation. The before
14
57
  # method may be called multiple times; subsequent calls append declared
15
58
  # hooks to existing before hooks.
@@ -84,6 +127,25 @@ module Interactor
84
127
  hooks.each { |hook| after_hooks.unshift(hook) }
85
128
  end
86
129
 
130
+ # Internal: An Array of declared hooks to run around Interactor
131
+ # invocation. The hooks appear in the order in which they will be run.
132
+ #
133
+ # Examples
134
+ #
135
+ # class MyInteractor
136
+ # include Interactor
137
+ #
138
+ # around :time_execution, :use_transaction
139
+ # end
140
+ #
141
+ # MyInteractor.around_hooks
142
+ # # => [:time_execution, :use_transaction]
143
+ #
144
+ # Returns an Array of Symbols and Procs.
145
+ def around_hooks
146
+ @around_hooks ||= []
147
+ end
148
+
87
149
  # Internal: An Array of declared hooks to run before Interactor
88
150
  # invocation. The hooks appear in the order in which they will be run.
89
151
  #
@@ -125,7 +187,7 @@ module Interactor
125
187
 
126
188
  private
127
189
 
128
- # Internal: Run before and after hooks around yielded execution. The
190
+ # Internal: Run around, before and after hooks around yielded execution. The
129
191
  # required block is surrounded with hooks and executed.
130
192
  #
131
193
  # Examples
@@ -146,9 +208,20 @@ module Interactor
146
208
  #
147
209
  # Returns nothing.
148
210
  def with_hooks
149
- run_before_hooks
150
- yield
151
- run_after_hooks
211
+ run_around_hooks do
212
+ run_before_hooks
213
+ yield
214
+ run_after_hooks
215
+ end
216
+ end
217
+
218
+ # Internal: Run around hooks.
219
+ #
220
+ # Returns nothing.
221
+ def run_around_hooks(&block)
222
+ self.class.around_hooks.reverse.inject(block) { |chain, hook|
223
+ proc { run_hook(hook, chain) }
224
+ }.call
152
225
  end
153
226
 
154
227
  # Internal: Run before hooks.
@@ -181,10 +254,13 @@ module Interactor
181
254
  # proc, the proc is evaluated in the context of the current instance.
182
255
  #
183
256
  # hook - A Symbol or Proc hook.
257
+ # args - Zero or more arguments to be passed as block arguments into the
258
+ # given block or as arguments into the method described by the given
259
+ # Symbol method name.
184
260
  #
185
261
  # Returns nothing.
186
- def run_hook(hook)
187
- hook.is_a?(Symbol) ? send(hook) : instance_eval(&hook)
262
+ def run_hook(hook, *args)
263
+ hook.is_a?(Symbol) ? send(hook, *args) : instance_exec(*args, &hook)
188
264
  end
189
265
  end
190
266
  end
@@ -26,6 +26,12 @@ describe "Integration" do
26
26
 
27
27
  let(:organizer) {
28
28
  build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
29
+ around do |interactor|
30
+ context.steps << :around_before
31
+ interactor.call
32
+ context.steps << :around_after
33
+ end
34
+
29
35
  before do
30
36
  context.steps << :before
31
37
  end
@@ -38,6 +44,12 @@ describe "Integration" do
38
44
 
39
45
  let(:organizer2) {
40
46
  build_organizer(organize: [interactor2a, interactor2b, interactor2c]) do
47
+ around do |interactor|
48
+ context.steps << :around_before2
49
+ interactor.call
50
+ context.steps << :around_after2
51
+ end
52
+
41
53
  before do
42
54
  context.steps << :before2
43
55
  end
@@ -50,6 +62,12 @@ describe "Integration" do
50
62
 
51
63
  let(:interactor2a) {
52
64
  build_interactor do
65
+ around do |interactor|
66
+ context.steps << :around_before2a
67
+ interactor.call
68
+ context.steps << :around_after2a
69
+ end
70
+
53
71
  before do
54
72
  context.steps << :before2a
55
73
  end
@@ -70,6 +88,12 @@ describe "Integration" do
70
88
 
71
89
  let(:interactor2b) {
72
90
  build_interactor do
91
+ around do |interactor|
92
+ context.steps << :around_before2b
93
+ interactor.call
94
+ context.steps << :around_after2b
95
+ end
96
+
73
97
  before do
74
98
  context.steps << :before2b
75
99
  end
@@ -90,6 +114,12 @@ describe "Integration" do
90
114
 
91
115
  let(:interactor2c) {
92
116
  build_interactor do
117
+ around do |interactor|
118
+ context.steps << :around_before2c
119
+ interactor.call
120
+ context.steps << :around_after2c
121
+ end
122
+
93
123
  before do
94
124
  context.steps << :before2c
95
125
  end
@@ -110,6 +140,12 @@ describe "Integration" do
110
140
 
111
141
  let(:interactor3) {
112
142
  build_interactor do
143
+ around do |interactor|
144
+ context.steps << :around_before3
145
+ interactor.call
146
+ context.steps << :around_after3
147
+ end
148
+
113
149
  before do
114
150
  context.steps << :before3
115
151
  end
@@ -130,6 +166,12 @@ describe "Integration" do
130
166
 
131
167
  let(:organizer4) {
132
168
  build_organizer(organize: [interactor4a, interactor4b, interactor4c]) do
169
+ around do |interactor|
170
+ context.steps << :around_before4
171
+ interactor.call
172
+ context.steps << :around_after4
173
+ end
174
+
133
175
  before do
134
176
  context.steps << :before4
135
177
  end
@@ -142,6 +184,12 @@ describe "Integration" do
142
184
 
143
185
  let(:interactor4a) {
144
186
  build_interactor do
187
+ around do |interactor|
188
+ context.steps << :around_before4a
189
+ interactor.call
190
+ context.steps << :around_after4a
191
+ end
192
+
145
193
  before do
146
194
  context.steps << :before4a
147
195
  end
@@ -162,6 +210,12 @@ describe "Integration" do
162
210
 
163
211
  let(:interactor4b) {
164
212
  build_interactor do
213
+ around do |interactor|
214
+ context.steps << :around_before4b
215
+ interactor.call
216
+ context.steps << :around_after4b
217
+ end
218
+
165
219
  before do
166
220
  context.steps << :before4b
167
221
  end
@@ -182,6 +236,12 @@ describe "Integration" do
182
236
 
183
237
  let(:interactor4c) {
184
238
  build_interactor do
239
+ around do |interactor|
240
+ context.steps << :around_before4c
241
+ interactor.call
242
+ context.steps << :around_after4c
243
+ end
244
+
185
245
  before do
186
246
  context.steps << :before4c
187
247
  end
@@ -202,6 +262,12 @@ describe "Integration" do
202
262
 
203
263
  let(:interactor5) {
204
264
  build_interactor do
265
+ around do |interactor|
266
+ context.steps << :around_before5
267
+ interactor.call
268
+ context.steps << :around_after5
269
+ end
270
+
205
271
  before do
206
272
  context.steps << :before5
207
273
  end
@@ -220,7 +286,7 @@ describe "Integration" do
220
286
  end
221
287
  }
222
288
 
223
- let(:context) { Interactor::Context.build(steps: []) }
289
+ let(:context) { Interactor::Context.new(steps: []) }
224
290
 
225
291
  context "when successful" do
226
292
  it "calls and runs hooks in the proper sequence" do
@@ -229,27 +295,34 @@ describe "Integration" do
229
295
  }.to change {
230
296
  context.steps
231
297
  }.from([]).to([
232
- :before,
233
- :before2,
234
- :before2a, :call2a, :after2a,
235
- :before2b, :call2b, :after2b,
236
- :before2c, :call2c, :after2c,
237
- :after2,
238
- :before3, :call3, :after3,
239
- :before4,
240
- :before4a, :call4a, :after4a,
241
- :before4b, :call4b, :after4b,
242
- :before4c, :call4c, :after4c,
243
- :after4,
244
- :before5, :call5, :after5,
245
- :after
298
+ :around_before, :before,
299
+ :around_before2, :before2,
300
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
301
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
302
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
303
+ :after2, :around_after2,
304
+ :around_before3, :before3, :call3, :after3, :around_after3,
305
+ :around_before4, :before4,
306
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
307
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
308
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
309
+ :after4, :around_after4,
310
+ :around_before5, :before5, :call5, :after5, :around_after5,
311
+ :after, :around_after
246
312
  ])
247
313
  end
248
314
  end
249
315
 
250
- context "when a before hook fails" do
316
+ context "when an around hook fails early" do
251
317
  let(:organizer) {
252
318
  build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
319
+ around do |interactor|
320
+ context.fail!
321
+ context.steps << :around_before
322
+ interactor.call
323
+ context.steps << :around_after
324
+ end
325
+
253
326
  before do
254
327
  context.fail!
255
328
  context.steps << :before
@@ -270,11 +343,18 @@ describe "Integration" do
270
343
  end
271
344
  end
272
345
 
273
- context "when a before hook errors" do
346
+ context "when an around hook errors early" do
274
347
  let(:organizer) {
275
348
  build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
276
- before do
349
+ around do |interactor|
277
350
  raise "foo"
351
+ context.steps << :around_before
352
+ interactor.call
353
+ context.steps << :around_after
354
+ end
355
+
356
+ before do
357
+ context.fail!
278
358
  context.steps << :before
279
359
  end
280
360
 
@@ -299,9 +379,83 @@ describe "Integration" do
299
379
  end
300
380
  end
301
381
 
382
+ context "when a before hook fails" do
383
+ let(:organizer) {
384
+ build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
385
+ around do |interactor|
386
+ context.steps << :around_before
387
+ interactor.call
388
+ context.steps << :around_after
389
+ end
390
+
391
+ before do
392
+ context.fail!
393
+ context.steps << :before
394
+ end
395
+
396
+ after do
397
+ context.steps << :after
398
+ end
399
+ end
400
+ }
401
+
402
+ it "aborts" do
403
+ expect {
404
+ organizer.call(context)
405
+ }.to change {
406
+ context.steps
407
+ }.from([]).to([
408
+ :around_before
409
+ ])
410
+ end
411
+ end
412
+
413
+ context "when a before hook errors" do
414
+ let(:organizer) {
415
+ build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
416
+ around do |interactor|
417
+ context.steps << :around_before
418
+ interactor.call
419
+ context.steps << :around_after
420
+ end
421
+
422
+ before do
423
+ raise "foo"
424
+ context.steps << :before
425
+ end
426
+
427
+ after do
428
+ context.steps << :after
429
+ end
430
+ end
431
+ }
432
+
433
+ it "aborts" do
434
+ expect {
435
+ organizer.call(context) rescue nil
436
+ }.to change {
437
+ context.steps
438
+ }.from([]).to([
439
+ :around_before
440
+ ])
441
+ end
442
+
443
+ it "raises the error" do
444
+ expect {
445
+ organizer.call(context)
446
+ }.to raise_error("foo")
447
+ end
448
+ end
449
+
302
450
  context "when an after hook fails" do
303
451
  let(:organizer) {
304
452
  build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
453
+ around do |interactor|
454
+ context.steps << :around_before
455
+ interactor.call
456
+ context.steps << :around_after
457
+ end
458
+
305
459
  before do
306
460
  context.steps << :before
307
461
  end
@@ -313,25 +467,25 @@ describe "Integration" do
313
467
  end
314
468
  }
315
469
 
316
- it "rolls back successfully called interactors" do
470
+ it "rolls back successfully called interactors and the failed interactor" do
317
471
  expect {
318
472
  organizer.call(context)
319
473
  }.to change {
320
474
  context.steps
321
475
  }.from([]).to([
322
- :before,
323
- :before2,
324
- :before2a, :call2a, :after2a,
325
- :before2b, :call2b, :after2b,
326
- :before2c, :call2c, :after2c,
327
- :after2,
328
- :before3, :call3, :after3,
329
- :before4,
330
- :before4a, :call4a, :after4a,
331
- :before4b, :call4b, :after4b,
332
- :before4c, :call4c, :after4c,
333
- :after4,
334
- :before5, :call5, :after5,
476
+ :around_before, :before,
477
+ :around_before2, :before2,
478
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
479
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
480
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
481
+ :after2, :around_after2,
482
+ :around_before3, :before3, :call3, :after3, :around_after3,
483
+ :around_before4, :before4,
484
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
485
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
486
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
487
+ :after4, :around_after4,
488
+ :around_before5, :before5, :call5, :after5, :around_after5,
335
489
  :rollback5,
336
490
  :rollback4c,
337
491
  :rollback4b,
@@ -347,6 +501,12 @@ describe "Integration" do
347
501
  context "when an after hook errors" do
348
502
  let(:organizer) {
349
503
  build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
504
+ around do |interactor|
505
+ context.steps << :around_before
506
+ interactor.call
507
+ context.steps << :around_after
508
+ end
509
+
350
510
  before do
351
511
  context.steps << :before
352
512
  end
@@ -358,25 +518,25 @@ describe "Integration" do
358
518
  end
359
519
  }
360
520
 
361
- it "aborts" do
521
+ it "rolls back successfully called interactors and the failed interactor" do
362
522
  expect {
363
523
  organizer.call(context) rescue nil
364
524
  }.to change {
365
525
  context.steps
366
526
  }.from([]).to([
367
- :before,
368
- :before2,
369
- :before2a, :call2a, :after2a,
370
- :before2b, :call2b, :after2b,
371
- :before2c, :call2c, :after2c,
372
- :after2,
373
- :before3, :call3, :after3,
374
- :before4,
375
- :before4a, :call4a, :after4a,
376
- :before4b, :call4b, :after4b,
377
- :before4c, :call4c, :after4c,
378
- :after4,
379
- :before5, :call5, :after5,
527
+ :around_before, :before,
528
+ :around_before2, :before2,
529
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
530
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
531
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
532
+ :after2, :around_after2,
533
+ :around_before3, :before3, :call3, :after3, :around_after3,
534
+ :around_before4, :before4,
535
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
536
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
537
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
538
+ :after4, :around_after4,
539
+ :around_before5, :before5, :call5, :after5, :around_after5,
380
540
  :rollback5,
381
541
  :rollback4c,
382
542
  :rollback4b,
@@ -395,40 +555,51 @@ describe "Integration" do
395
555
  end
396
556
  end
397
557
 
398
- context "when a nested before hook fails" do
399
- let(:interactor3) {
400
- build_interactor do
401
- before do
558
+ context "when an around hook fails late" do
559
+ let(:organizer) {
560
+ build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
561
+ around do |interactor|
562
+ context.steps << :around_before
563
+ interactor.call
402
564
  context.fail!
403
- context.steps << :before3
404
- end
405
-
406
- after do
407
- context.steps << :after3
565
+ context.steps << :around_after
408
566
  end
409
567
 
410
- def call
411
- context.steps << :call3
568
+ before do
569
+ context.steps << :before
412
570
  end
413
571
 
414
- def rollback
415
- context.steps << :rollback3
572
+ after do
573
+ context.steps << :after
416
574
  end
417
575
  end
418
576
  }
419
577
 
420
- it "rolls back successfully called interactors" do
578
+ it "rolls back successfully called interactors and the failed interactor" do
421
579
  expect {
422
580
  organizer.call(context)
423
581
  }.to change {
424
582
  context.steps
425
583
  }.from([]).to([
426
- :before,
427
- :before2,
428
- :before2a, :call2a, :after2a,
429
- :before2b, :call2b, :after2b,
430
- :before2c, :call2c, :after2c,
431
- :after2,
584
+ :around_before, :before,
585
+ :around_before2, :before2,
586
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
587
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
588
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
589
+ :after2, :around_after2,
590
+ :around_before3, :before3, :call3, :after3, :around_after3,
591
+ :around_before4, :before4,
592
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
593
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
594
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
595
+ :after4, :around_after4,
596
+ :around_before5, :before5, :call5, :after5, :around_after5,
597
+ :after,
598
+ :rollback5,
599
+ :rollback4c,
600
+ :rollback4b,
601
+ :rollback4a,
602
+ :rollback3,
432
603
  :rollback2c,
433
604
  :rollback2b,
434
605
  :rollback2a
@@ -436,40 +607,51 @@ describe "Integration" do
436
607
  end
437
608
  end
438
609
 
439
- context "when a nested before hook errors" do
440
- let(:interactor3) {
441
- build_interactor do
442
- before do
610
+ context "when an around hook errors late" do
611
+ let(:organizer) {
612
+ build_organizer(organize: [organizer2, interactor3, organizer4, interactor5]) do
613
+ around do |interactor|
614
+ context.steps << :around_before
615
+ interactor.call
443
616
  raise "foo"
444
- context.steps << :before3
445
- end
446
-
447
- after do
448
- context.steps << :after3
617
+ context.steps << :around_after
449
618
  end
450
619
 
451
- def call
452
- context.steps << :call3
620
+ before do
621
+ context.steps << :before
453
622
  end
454
623
 
455
- def rollback
456
- context.steps << :rollback3
624
+ after do
625
+ context.steps << :after
457
626
  end
458
627
  end
459
628
  }
460
629
 
461
- it "rolls back successfully called interactors" do
630
+ it "rolls back successfully called interactors and the failed interactor" do
462
631
  expect {
463
632
  organizer.call(context) rescue nil
464
633
  }.to change {
465
634
  context.steps
466
635
  }.from([]).to([
467
- :before,
468
- :before2,
469
- :before2a, :call2a, :after2a,
470
- :before2b, :call2b, :after2b,
471
- :before2c, :call2c, :after2c,
472
- :after2,
636
+ :around_before, :before,
637
+ :around_before2, :before2,
638
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
639
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
640
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
641
+ :after2, :around_after2,
642
+ :around_before3, :before3, :call3, :after3, :around_after3,
643
+ :around_before4, :before4,
644
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
645
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
646
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
647
+ :after4, :around_after4,
648
+ :around_before5, :before5, :call5, :after5, :around_after5,
649
+ :after,
650
+ :rollback5,
651
+ :rollback4c,
652
+ :rollback4b,
653
+ :rollback4a,
654
+ :rollback3,
473
655
  :rollback2c,
474
656
  :rollback2b,
475
657
  :rollback2a
@@ -483,9 +665,16 @@ describe "Integration" do
483
665
  end
484
666
  end
485
667
 
486
- context "when a nested call fails" do
668
+ context "when a nested around hook fails early" do
487
669
  let(:interactor3) {
488
670
  build_interactor do
671
+ around do |interactor|
672
+ context.fail!
673
+ context.steps << :around_before3
674
+ interactor.call
675
+ context.steps << :around_after3
676
+ end
677
+
489
678
  before do
490
679
  context.steps << :before3
491
680
  end
@@ -495,7 +684,6 @@ describe "Integration" do
495
684
  end
496
685
 
497
686
  def call
498
- context.fail!
499
687
  context.steps << :call3
500
688
  end
501
689
 
@@ -511,13 +699,12 @@ describe "Integration" do
511
699
  }.to change {
512
700
  context.steps
513
701
  }.from([]).to([
514
- :before,
515
- :before2,
516
- :before2a, :call2a, :after2a,
517
- :before2b, :call2b, :after2b,
518
- :before2c, :call2c, :after2c,
519
- :after2,
520
- :before3,
702
+ :around_before, :before,
703
+ :around_before2, :before2,
704
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
705
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
706
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
707
+ :after2, :around_after2,
521
708
  :rollback2c,
522
709
  :rollback2b,
523
710
  :rollback2a
@@ -525,9 +712,16 @@ describe "Integration" do
525
712
  end
526
713
  end
527
714
 
528
- context "when a nested call errors" do
715
+ context "when a nested around hook errors early" do
529
716
  let(:interactor3) {
530
717
  build_interactor do
718
+ around do |interactor|
719
+ raise "foo"
720
+ context.steps << :around_before3
721
+ interactor.call
722
+ context.steps << :around_after3
723
+ end
724
+
531
725
  before do
532
726
  context.steps << :before3
533
727
  end
@@ -537,7 +731,6 @@ describe "Integration" do
537
731
  end
538
732
 
539
733
  def call
540
- raise "foo"
541
734
  context.steps << :call3
542
735
  end
543
736
 
@@ -553,13 +746,12 @@ describe "Integration" do
553
746
  }.to change {
554
747
  context.steps
555
748
  }.from([]).to([
556
- :before,
557
- :before2,
558
- :before2a, :call2a, :after2a,
559
- :before2b, :call2b, :after2b,
560
- :before2c, :call2c, :after2c,
561
- :after2,
562
- :before3,
749
+ :around_before, :before,
750
+ :around_before2, :before2,
751
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
752
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
753
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
754
+ :after2, :around_after2,
563
755
  :rollback2c,
564
756
  :rollback2b,
565
757
  :rollback2a
@@ -573,15 +765,21 @@ describe "Integration" do
573
765
  end
574
766
  end
575
767
 
576
- context "when a nested after hook fails" do
768
+ context "when a nested before hook fails" do
577
769
  let(:interactor3) {
578
770
  build_interactor do
771
+ around do |interactor|
772
+ context.steps << :around_before3
773
+ interactor.call
774
+ context.steps << :around_after3
775
+ end
776
+
579
777
  before do
778
+ context.fail!
580
779
  context.steps << :before3
581
780
  end
582
781
 
583
782
  after do
584
- context.fail!
585
783
  context.steps << :after3
586
784
  end
587
785
 
@@ -595,20 +793,19 @@ describe "Integration" do
595
793
  end
596
794
  }
597
795
 
598
- it "rolls back successfully called interactors and the failed interactor" do
796
+ it "rolls back successfully called interactors" do
599
797
  expect {
600
798
  organizer.call(context)
601
799
  }.to change {
602
800
  context.steps
603
801
  }.from([]).to([
604
- :before,
605
- :before2,
606
- :before2a, :call2a, :after2a,
607
- :before2b, :call2b, :after2b,
608
- :before2c, :call2c, :after2c,
609
- :after2,
610
- :before3, :call3,
611
- :rollback3,
802
+ :around_before, :before,
803
+ :around_before2, :before2,
804
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
805
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
806
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
807
+ :after2, :around_after2,
808
+ :around_before3,
612
809
  :rollback2c,
613
810
  :rollback2b,
614
811
  :rollback2a
@@ -616,15 +813,21 @@ describe "Integration" do
616
813
  end
617
814
  end
618
815
 
619
- context "when a nested after hook errors" do
816
+ context "when a nested before hook errors" do
620
817
  let(:interactor3) {
621
818
  build_interactor do
819
+ around do |interactor|
820
+ context.steps << :around_before3
821
+ interactor.call
822
+ context.steps << :around_after3
823
+ end
824
+
622
825
  before do
826
+ raise "foo"
623
827
  context.steps << :before3
624
828
  end
625
829
 
626
830
  after do
627
- raise "foo"
628
831
  context.steps << :after3
629
832
  end
630
833
 
@@ -638,20 +841,19 @@ describe "Integration" do
638
841
  end
639
842
  }
640
843
 
641
- it "rolls back successfully called interactors and the failed interactor" do
844
+ it "rolls back successfully called interactors" do
642
845
  expect {
643
846
  organizer.call(context) rescue nil
644
847
  }.to change {
645
848
  context.steps
646
849
  }.from([]).to([
647
- :before,
648
- :before2,
649
- :before2a, :call2a, :after2a,
650
- :before2b, :call2b, :after2b,
651
- :before2c, :call2c, :after2c,
652
- :after2,
653
- :before3, :call3,
654
- :rollback3,
850
+ :around_before, :before,
851
+ :around_before2, :before2,
852
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
853
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
854
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
855
+ :after2, :around_after2,
856
+ :around_before3,
655
857
  :rollback2c,
656
858
  :rollback2b,
657
859
  :rollback2a
@@ -665,24 +867,30 @@ describe "Integration" do
665
867
  end
666
868
  end
667
869
 
668
- context "when a deeply nested before hook fails" do
669
- let(:interactor4b) {
870
+ context "when a nested call fails" do
871
+ let(:interactor3) {
670
872
  build_interactor do
873
+ around do |interactor|
874
+ context.steps << :around_before3
875
+ interactor.call
876
+ context.steps << :around_after3
877
+ end
878
+
671
879
  before do
672
- context.fail!
673
- context.steps << :before4b
880
+ context.steps << :before3
674
881
  end
675
882
 
676
883
  after do
677
- context.steps << :after4b
884
+ context.steps << :after3
678
885
  end
679
886
 
680
887
  def call
681
- context.steps << :call4b
888
+ context.fail!
889
+ context.steps << :call3
682
890
  end
683
891
 
684
892
  def rollback
685
- context.steps << :rollback4b
893
+ context.steps << :rollback3
686
894
  end
687
895
  end
688
896
  }
@@ -693,17 +901,13 @@ describe "Integration" do
693
901
  }.to change {
694
902
  context.steps
695
903
  }.from([]).to([
696
- :before,
697
- :before2,
698
- :before2a, :call2a, :after2a,
699
- :before2b, :call2b, :after2b,
700
- :before2c, :call2c, :after2c,
701
- :after2,
702
- :before3, :call3, :after3,
703
- :before4,
704
- :before4a, :call4a, :after4a,
705
- :rollback4a,
706
- :rollback3,
904
+ :around_before, :before,
905
+ :around_before2, :before2,
906
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
907
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
908
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
909
+ :after2, :around_after2,
910
+ :around_before3, :before3,
707
911
  :rollback2c,
708
912
  :rollback2b,
709
913
  :rollback2a
@@ -711,24 +915,30 @@ describe "Integration" do
711
915
  end
712
916
  end
713
917
 
714
- context "when a deeply nested before hook errors" do
715
- let(:interactor4b) {
918
+ context "when a nested call errors" do
919
+ let(:interactor3) {
716
920
  build_interactor do
921
+ around do |interactor|
922
+ context.steps << :around_before3
923
+ interactor.call
924
+ context.steps << :around_after3
925
+ end
926
+
717
927
  before do
718
- raise "foo"
719
- context.steps << :before4b
928
+ context.steps << :before3
720
929
  end
721
930
 
722
931
  after do
723
- context.steps << :after4b
932
+ context.steps << :after3
724
933
  end
725
934
 
726
935
  def call
727
- context.steps << :call4b
936
+ raise "foo"
937
+ context.steps << :call3
728
938
  end
729
939
 
730
940
  def rollback
731
- context.steps << :rollback4b
941
+ context.steps << :rollback3
732
942
  end
733
943
  end
734
944
  }
@@ -739,17 +949,13 @@ describe "Integration" do
739
949
  }.to change {
740
950
  context.steps
741
951
  }.from([]).to([
742
- :before,
743
- :before2,
744
- :before2a, :call2a, :after2a,
745
- :before2b, :call2b, :after2b,
746
- :before2c, :call2c, :after2c,
747
- :after2,
748
- :before3, :call3, :after3,
749
- :before4,
750
- :before4a, :call4a, :after4a,
751
- :rollback4a,
752
- :rollback3,
952
+ :around_before, :before,
953
+ :around_before2, :before2,
954
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
955
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
956
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
957
+ :after2, :around_after2,
958
+ :around_before3, :before3,
753
959
  :rollback2c,
754
960
  :rollback2b,
755
961
  :rollback2a
@@ -763,45 +969,47 @@ describe "Integration" do
763
969
  end
764
970
  end
765
971
 
766
- context "when a deeply nested call fails" do
767
- let(:interactor4b) {
972
+ context "when a nested after hook fails" do
973
+ let(:interactor3) {
768
974
  build_interactor do
975
+ around do |interactor|
976
+ context.steps << :around_before3
977
+ interactor.call
978
+ context.steps << :around_after3
979
+ end
980
+
769
981
  before do
770
- context.steps << :before4b
982
+ context.steps << :before3
771
983
  end
772
984
 
773
985
  after do
774
- context.steps << :after4b
986
+ context.fail!
987
+ context.steps << :after3
775
988
  end
776
989
 
777
990
  def call
778
- context.fail!
779
- context.steps << :call4b
991
+ context.steps << :call3
780
992
  end
781
993
 
782
994
  def rollback
783
- context.steps << :rollback4b
995
+ context.steps << :rollback3
784
996
  end
785
997
  end
786
998
  }
787
999
 
788
- it "rolls back successfully called interactors" do
1000
+ it "rolls back successfully called interactors and the failed interactor" do
789
1001
  expect {
790
1002
  organizer.call(context)
791
1003
  }.to change {
792
1004
  context.steps
793
1005
  }.from([]).to([
794
- :before,
795
- :before2,
796
- :before2a, :call2a, :after2a,
797
- :before2b, :call2b, :after2b,
798
- :before2c, :call2c, :after2c,
799
- :after2,
800
- :before3, :call3, :after3,
801
- :before4,
802
- :before4a, :call4a, :after4a,
803
- :before4b,
804
- :rollback4a,
1006
+ :around_before, :before,
1007
+ :around_before2, :before2,
1008
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1009
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1010
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1011
+ :after2, :around_after2,
1012
+ :around_before3, :before3, :call3,
805
1013
  :rollback3,
806
1014
  :rollback2c,
807
1015
  :rollback2b,
@@ -810,45 +1018,47 @@ describe "Integration" do
810
1018
  end
811
1019
  end
812
1020
 
813
- context "when a deeply nested call errors" do
814
- let(:interactor4b) {
1021
+ context "when a nested after hook errors" do
1022
+ let(:interactor3) {
815
1023
  build_interactor do
1024
+ around do |interactor|
1025
+ context.steps << :around_before3
1026
+ interactor.call
1027
+ context.steps << :around_after3
1028
+ end
1029
+
816
1030
  before do
817
- context.steps << :before4b
1031
+ context.steps << :before3
818
1032
  end
819
1033
 
820
1034
  after do
821
- context.steps << :after4b
1035
+ raise "foo"
1036
+ context.steps << :after3
822
1037
  end
823
1038
 
824
1039
  def call
825
- raise "foo"
826
- context.steps << :call4b
1040
+ context.steps << :call3
827
1041
  end
828
1042
 
829
1043
  def rollback
830
- context.steps << :rollback4b
1044
+ context.steps << :rollback3
831
1045
  end
832
1046
  end
833
1047
  }
834
1048
 
835
- it "rolls back successfully called interactors" do
1049
+ it "rolls back successfully called interactors and the failed interactor" do
836
1050
  expect {
837
1051
  organizer.call(context) rescue nil
838
1052
  }.to change {
839
1053
  context.steps
840
1054
  }.from([]).to([
841
- :before,
842
- :before2,
843
- :before2a, :call2a, :after2a,
844
- :before2b, :call2b, :after2b,
845
- :before2c, :call2c, :after2c,
846
- :after2,
847
- :before3, :call3, :after3,
848
- :before4,
849
- :before4a, :call4a, :after4a,
850
- :before4b,
851
- :rollback4a,
1055
+ :around_before, :before,
1056
+ :around_before2, :before2,
1057
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1058
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1059
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1060
+ :after2, :around_after2,
1061
+ :around_before3, :before3, :call3,
852
1062
  :rollback3,
853
1063
  :rollback2c,
854
1064
  :rollback2b,
@@ -863,10 +1073,454 @@ describe "Integration" do
863
1073
  end
864
1074
  end
865
1075
 
866
- context "when a deeply nested after hook fails" do
867
- let(:interactor4b) {
1076
+ context "when a nested around hook fails late" do
1077
+ let(:interactor3) {
868
1078
  build_interactor do
869
- before do
1079
+ around do |interactor|
1080
+ context.steps << :around_before3
1081
+ interactor.call
1082
+ context.fail!
1083
+ context.steps << :around_after3
1084
+ end
1085
+
1086
+ before do
1087
+ context.steps << :before3
1088
+ end
1089
+
1090
+ after do
1091
+ context.steps << :after3
1092
+ end
1093
+
1094
+ def call
1095
+ context.steps << :call3
1096
+ end
1097
+
1098
+ def rollback
1099
+ context.steps << :rollback3
1100
+ end
1101
+ end
1102
+ }
1103
+
1104
+ it "rolls back successfully called interactors and the failed interactor" do
1105
+ expect {
1106
+ organizer.call(context)
1107
+ }.to change {
1108
+ context.steps
1109
+ }.from([]).to([
1110
+ :around_before, :before,
1111
+ :around_before2, :before2,
1112
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1113
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1114
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1115
+ :after2, :around_after2,
1116
+ :around_before3, :before3, :call3, :after3,
1117
+ :rollback3,
1118
+ :rollback2c,
1119
+ :rollback2b,
1120
+ :rollback2a
1121
+ ])
1122
+ end
1123
+ end
1124
+
1125
+ context "when a nested around hook errors late" do
1126
+ let(:interactor3) {
1127
+ build_interactor do
1128
+ around do |interactor|
1129
+ context.steps << :around_before3
1130
+ interactor.call
1131
+ raise "foo"
1132
+ context.steps << :around_after3
1133
+ end
1134
+
1135
+ before do
1136
+ context.steps << :before3
1137
+ end
1138
+
1139
+ after do
1140
+ context.steps << :after3
1141
+ end
1142
+
1143
+ def call
1144
+ context.steps << :call3
1145
+ end
1146
+
1147
+ def rollback
1148
+ context.steps << :rollback3
1149
+ end
1150
+ end
1151
+ }
1152
+
1153
+ it "rolls back successfully called interactors and the failed interactor" do
1154
+ expect {
1155
+ organizer.call(context) rescue nil
1156
+ }.to change {
1157
+ context.steps
1158
+ }.from([]).to([
1159
+ :around_before, :before,
1160
+ :around_before2, :before2,
1161
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1162
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1163
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1164
+ :after2, :around_after2,
1165
+ :around_before3, :before3, :call3, :after3,
1166
+ :rollback3,
1167
+ :rollback2c,
1168
+ :rollback2b,
1169
+ :rollback2a
1170
+ ])
1171
+ end
1172
+
1173
+ it "raises the error" do
1174
+ expect {
1175
+ organizer.call(context)
1176
+ }.to raise_error("foo")
1177
+ end
1178
+ end
1179
+
1180
+ context "when a deeply nested around hook fails early" do
1181
+ let(:interactor4b) {
1182
+ build_interactor do
1183
+ around do |interactor|
1184
+ context.fail!
1185
+ context.steps << :around_before4b
1186
+ interactor.call
1187
+ context.steps << :around_after4b
1188
+ end
1189
+
1190
+ before do
1191
+ context.steps << :before4b
1192
+ end
1193
+
1194
+ after do
1195
+ context.steps << :after4b
1196
+ end
1197
+
1198
+ def call
1199
+ context.steps << :call4b
1200
+ end
1201
+
1202
+ def rollback
1203
+ context.steps << :rollback4b
1204
+ end
1205
+ end
1206
+ }
1207
+
1208
+ it "rolls back successfully called interactors" do
1209
+ expect {
1210
+ organizer.call(context)
1211
+ }.to change {
1212
+ context.steps
1213
+ }.from([]).to([
1214
+ :around_before, :before,
1215
+ :around_before2, :before2,
1216
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1217
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1218
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1219
+ :after2, :around_after2,
1220
+ :around_before3, :before3, :call3, :after3, :around_after3,
1221
+ :around_before4, :before4,
1222
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1223
+ :rollback4a,
1224
+ :rollback3,
1225
+ :rollback2c,
1226
+ :rollback2b,
1227
+ :rollback2a
1228
+ ])
1229
+ end
1230
+ end
1231
+
1232
+ context "when a deeply nested around hook errors early" do
1233
+ let(:interactor4b) {
1234
+ build_interactor do
1235
+ around do |interactor|
1236
+ raise "foo"
1237
+ context.steps << :around_before4b
1238
+ interactor.call
1239
+ context.steps << :around_after4b
1240
+ end
1241
+
1242
+ before do
1243
+ context.steps << :before4b
1244
+ end
1245
+
1246
+ after do
1247
+ context.steps << :after4b
1248
+ end
1249
+
1250
+ def call
1251
+ context.steps << :call4b
1252
+ end
1253
+
1254
+ def rollback
1255
+ context.steps << :rollback4b
1256
+ end
1257
+ end
1258
+ }
1259
+
1260
+ it "rolls back successfully called interactors" do
1261
+ expect {
1262
+ organizer.call(context) rescue nil
1263
+ }.to change {
1264
+ context.steps
1265
+ }.from([]).to([
1266
+ :around_before, :before,
1267
+ :around_before2, :before2,
1268
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1269
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1270
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1271
+ :after2, :around_after2,
1272
+ :around_before3, :before3, :call3, :after3, :around_after3,
1273
+ :around_before4, :before4,
1274
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1275
+ :rollback4a,
1276
+ :rollback3,
1277
+ :rollback2c,
1278
+ :rollback2b,
1279
+ :rollback2a
1280
+ ])
1281
+ end
1282
+
1283
+ it "raises the error" do
1284
+ expect {
1285
+ organizer.call(context)
1286
+ }.to raise_error("foo")
1287
+ end
1288
+ end
1289
+
1290
+ context "when a deeply nested before hook fails" do
1291
+ let(:interactor4b) {
1292
+ build_interactor do
1293
+ around do |interactor|
1294
+ context.steps << :around_before4b
1295
+ interactor.call
1296
+ context.steps << :around_after4b
1297
+ end
1298
+
1299
+ before do
1300
+ context.fail!
1301
+ context.steps << :before4b
1302
+ end
1303
+
1304
+ after do
1305
+ context.steps << :after4b
1306
+ end
1307
+
1308
+ def call
1309
+ context.steps << :call4b
1310
+ end
1311
+
1312
+ def rollback
1313
+ context.steps << :rollback4b
1314
+ end
1315
+ end
1316
+ }
1317
+
1318
+ it "rolls back successfully called interactors" do
1319
+ expect {
1320
+ organizer.call(context)
1321
+ }.to change {
1322
+ context.steps
1323
+ }.from([]).to([
1324
+ :around_before, :before,
1325
+ :around_before2, :before2,
1326
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1327
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1328
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1329
+ :after2, :around_after2,
1330
+ :around_before3, :before3, :call3, :after3, :around_after3,
1331
+ :around_before4, :before4,
1332
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1333
+ :around_before4b,
1334
+ :rollback4a,
1335
+ :rollback3,
1336
+ :rollback2c,
1337
+ :rollback2b,
1338
+ :rollback2a
1339
+ ])
1340
+ end
1341
+ end
1342
+
1343
+ context "when a deeply nested before hook errors" do
1344
+ let(:interactor4b) {
1345
+ build_interactor do
1346
+ around do |interactor|
1347
+ context.steps << :around_before4b
1348
+ interactor.call
1349
+ context.steps << :around_after4b
1350
+ end
1351
+
1352
+ before do
1353
+ raise "foo"
1354
+ context.steps << :before4b
1355
+ end
1356
+
1357
+ after do
1358
+ context.steps << :after4b
1359
+ end
1360
+
1361
+ def call
1362
+ context.steps << :call4b
1363
+ end
1364
+
1365
+ def rollback
1366
+ context.steps << :rollback4b
1367
+ end
1368
+ end
1369
+ }
1370
+
1371
+ it "rolls back successfully called interactors" do
1372
+ expect {
1373
+ organizer.call(context) rescue nil
1374
+ }.to change {
1375
+ context.steps
1376
+ }.from([]).to([
1377
+ :around_before, :before,
1378
+ :around_before2, :before2,
1379
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1380
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1381
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1382
+ :after2, :around_after2,
1383
+ :around_before3, :before3, :call3, :after3, :around_after3,
1384
+ :around_before4, :before4,
1385
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1386
+ :around_before4b,
1387
+ :rollback4a,
1388
+ :rollback3,
1389
+ :rollback2c,
1390
+ :rollback2b,
1391
+ :rollback2a
1392
+ ])
1393
+ end
1394
+
1395
+ it "raises the error" do
1396
+ expect {
1397
+ organizer.call(context)
1398
+ }.to raise_error("foo")
1399
+ end
1400
+ end
1401
+
1402
+ context "when a deeply nested call fails" do
1403
+ let(:interactor4b) {
1404
+ build_interactor do
1405
+ around do |interactor|
1406
+ context.steps << :around_before4b
1407
+ interactor.call
1408
+ context.steps << :around_after4b
1409
+ end
1410
+
1411
+ before do
1412
+ context.steps << :before4b
1413
+ end
1414
+
1415
+ after do
1416
+ context.steps << :after4b
1417
+ end
1418
+
1419
+ def call
1420
+ context.fail!
1421
+ context.steps << :call4b
1422
+ end
1423
+
1424
+ def rollback
1425
+ context.steps << :rollback4b
1426
+ end
1427
+ end
1428
+ }
1429
+
1430
+ it "rolls back successfully called interactors" do
1431
+ expect {
1432
+ organizer.call(context)
1433
+ }.to change {
1434
+ context.steps
1435
+ }.from([]).to([
1436
+ :around_before, :before,
1437
+ :around_before2, :before2,
1438
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1439
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1440
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1441
+ :after2, :around_after2,
1442
+ :around_before3, :before3, :call3, :after3, :around_after3,
1443
+ :around_before4, :before4,
1444
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1445
+ :around_before4b, :before4b,
1446
+ :rollback4a,
1447
+ :rollback3,
1448
+ :rollback2c,
1449
+ :rollback2b,
1450
+ :rollback2a
1451
+ ])
1452
+ end
1453
+ end
1454
+
1455
+ context "when a deeply nested call errors" do
1456
+ let(:interactor4b) {
1457
+ build_interactor do
1458
+ around do |interactor|
1459
+ context.steps << :around_before4b
1460
+ interactor.call
1461
+ context.steps << :around_after4b
1462
+ end
1463
+
1464
+ before do
1465
+ context.steps << :before4b
1466
+ end
1467
+
1468
+ after do
1469
+ context.steps << :after4b
1470
+ end
1471
+
1472
+ def call
1473
+ raise "foo"
1474
+ context.steps << :call4b
1475
+ end
1476
+
1477
+ def rollback
1478
+ context.steps << :rollback4b
1479
+ end
1480
+ end
1481
+ }
1482
+
1483
+ it "rolls back successfully called interactors" do
1484
+ expect {
1485
+ organizer.call(context) rescue nil
1486
+ }.to change {
1487
+ context.steps
1488
+ }.from([]).to([
1489
+ :around_before, :before,
1490
+ :around_before2, :before2,
1491
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1492
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1493
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1494
+ :after2, :around_after2,
1495
+ :around_before3, :before3, :call3, :after3, :around_after3,
1496
+ :around_before4, :before4,
1497
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1498
+ :around_before4b, :before4b,
1499
+ :rollback4a,
1500
+ :rollback3,
1501
+ :rollback2c,
1502
+ :rollback2b,
1503
+ :rollback2a
1504
+ ])
1505
+ end
1506
+
1507
+ it "raises the error" do
1508
+ expect {
1509
+ organizer.call(context)
1510
+ }.to raise_error("foo")
1511
+ end
1512
+ end
1513
+
1514
+ context "when a deeply nested after hook fails" do
1515
+ let(:interactor4b) {
1516
+ build_interactor do
1517
+ around do |interactor|
1518
+ context.steps << :around_before4b
1519
+ interactor.call
1520
+ context.steps << :around_after4b
1521
+ end
1522
+
1523
+ before do
870
1524
  context.steps << :before4b
871
1525
  end
872
1526
 
@@ -891,16 +1545,16 @@ describe "Integration" do
891
1545
  }.to change {
892
1546
  context.steps
893
1547
  }.from([]).to([
894
- :before,
895
- :before2,
896
- :before2a, :call2a, :after2a,
897
- :before2b, :call2b, :after2b,
898
- :before2c, :call2c, :after2c,
899
- :after2,
900
- :before3, :call3, :after3,
901
- :before4,
902
- :before4a, :call4a, :after4a,
903
- :before4b, :call4b,
1548
+ :around_before, :before,
1549
+ :around_before2, :before2,
1550
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1551
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1552
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1553
+ :after2, :around_after2,
1554
+ :around_before3, :before3, :call3, :after3, :around_after3,
1555
+ :around_before4, :before4,
1556
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1557
+ :around_before4b, :before4b, :call4b,
904
1558
  :rollback4b,
905
1559
  :rollback4a,
906
1560
  :rollback3,
@@ -914,6 +1568,12 @@ describe "Integration" do
914
1568
  context "when a deeply nested after hook errors" do
915
1569
  let(:interactor4b) {
916
1570
  build_interactor do
1571
+ around do |interactor|
1572
+ context.steps << :around_before4b
1573
+ interactor.call
1574
+ context.steps << :around_after4b
1575
+ end
1576
+
917
1577
  before do
918
1578
  context.steps << :before4b
919
1579
  end
@@ -939,16 +1599,130 @@ describe "Integration" do
939
1599
  }.to change {
940
1600
  context.steps
941
1601
  }.from([]).to([
942
- :before,
943
- :before2,
944
- :before2a, :call2a, :after2a,
945
- :before2b, :call2b, :after2b,
946
- :before2c, :call2c, :after2c,
947
- :after2,
948
- :before3, :call3, :after3,
949
- :before4,
950
- :before4a, :call4a, :after4a,
951
- :before4b, :call4b,
1602
+ :around_before, :before,
1603
+ :around_before2, :before2,
1604
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1605
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1606
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1607
+ :after2, :around_after2,
1608
+ :around_before3, :before3, :call3, :after3, :around_after3,
1609
+ :around_before4, :before4,
1610
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1611
+ :around_before4b, :before4b, :call4b,
1612
+ :rollback4b,
1613
+ :rollback4a,
1614
+ :rollback3,
1615
+ :rollback2c,
1616
+ :rollback2b,
1617
+ :rollback2a
1618
+ ])
1619
+ end
1620
+
1621
+ it "raises the error" do
1622
+ expect {
1623
+ organizer.call(context)
1624
+ }.to raise_error("foo")
1625
+ end
1626
+ end
1627
+
1628
+ context "when a deeply nested around hook fails late" do
1629
+ let(:interactor4b) {
1630
+ build_interactor do
1631
+ around do |interactor|
1632
+ context.steps << :around_before4b
1633
+ interactor.call
1634
+ context.fail!
1635
+ context.steps << :around_after4b
1636
+ end
1637
+
1638
+ before do
1639
+ context.steps << :before4b
1640
+ end
1641
+
1642
+ after do
1643
+ context.steps << :after4b
1644
+ end
1645
+
1646
+ def call
1647
+ context.steps << :call4b
1648
+ end
1649
+
1650
+ def rollback
1651
+ context.steps << :rollback4b
1652
+ end
1653
+ end
1654
+ }
1655
+
1656
+ it "rolls back successfully called interactors and the failed interactor" do
1657
+ expect {
1658
+ organizer.call(context)
1659
+ }.to change {
1660
+ context.steps
1661
+ }.from([]).to([
1662
+ :around_before, :before,
1663
+ :around_before2, :before2,
1664
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1665
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1666
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1667
+ :after2, :around_after2,
1668
+ :around_before3, :before3, :call3, :after3, :around_after3,
1669
+ :around_before4, :before4,
1670
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1671
+ :around_before4b, :before4b, :call4b, :after4b,
1672
+ :rollback4b,
1673
+ :rollback4a,
1674
+ :rollback3,
1675
+ :rollback2c,
1676
+ :rollback2b,
1677
+ :rollback2a
1678
+ ])
1679
+ end
1680
+ end
1681
+
1682
+ context "when a deeply nested around hook errors late" do
1683
+ let(:interactor4b) {
1684
+ build_interactor do
1685
+ around do |interactor|
1686
+ context.steps << :around_before4b
1687
+ interactor.call
1688
+ raise "foo"
1689
+ context.steps << :around_after4b
1690
+ end
1691
+
1692
+ before do
1693
+ context.steps << :before4b
1694
+ end
1695
+
1696
+ after do
1697
+ context.steps << :after4b
1698
+ end
1699
+
1700
+ def call
1701
+ context.steps << :call4b
1702
+ end
1703
+
1704
+ def rollback
1705
+ context.steps << :rollback4b
1706
+ end
1707
+ end
1708
+ }
1709
+
1710
+ it "rolls back successfully called interactors and the failed interactor" do
1711
+ expect {
1712
+ organizer.call(context) rescue nil
1713
+ }.to change {
1714
+ context.steps
1715
+ }.from([]).to([
1716
+ :around_before, :before,
1717
+ :around_before2, :before2,
1718
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1719
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1720
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1721
+ :after2, :around_after2,
1722
+ :around_before3, :before3, :call3, :after3, :around_after3,
1723
+ :around_before4, :before4,
1724
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1725
+ :around_before4b, :before4b, :call4b, :after4b,
952
1726
  :rollback4b,
953
1727
  :rollback4a,
954
1728
  :rollback3,