interactor 3.0.1 → 3.1.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 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,