activeinteractor 1.0.0.beta.3 → 1.0.0.beta.4
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 +4 -4
- data/CHANGELOG.md +26 -1
- data/README.md +28 -4
- data/lib/active_interactor/interactor.rb +25 -7
- data/lib/active_interactor/interactor/perform_options.rb +5 -21
- data/lib/active_interactor/interactor/worker.rb +33 -42
- data/lib/active_interactor/organizer.rb +58 -28
- data/lib/active_interactor/organizer/interactor_interface.rb +66 -0
- data/lib/active_interactor/organizer/interactor_interface_collection.rb +58 -0
- data/lib/active_interactor/version.rb +1 -1
- data/spec/active_interactor/interactor/perform_options_spec.rb +25 -0
- data/spec/active_interactor/interactor/worker_spec.rb +81 -82
- data/spec/active_interactor/organizer/interactor_interface_collection_spec.rb +76 -0
- data/spec/active_interactor/organizer/interactor_interface_spec.rb +162 -0
- data/spec/active_interactor/organizer_spec.rb +36 -32
- data/spec/integration/basic_integration_spec.rb +311 -12
- data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +4 -4
- metadata +22 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b887e29c2334d776e28d0df4e79ba53b42123d47e4e6f4da6c94a2fa5b38ea78
|
4
|
+
data.tar.gz: e6ca29f29e435b5b73e405c41eccfa6dea8837a7316c3d3143abd97cda241347
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f766aa0e2c50d7cec5c74def38f7e2ea9d3918354f511d2ec127cf4054c9484638f1cd6f984686e1b12ca09116f53708fd4e5f714620178c4dd73ab745d6ee3
|
7
|
+
data.tar.gz: 2ece11503295a16bfba3860cb8d4ad3653eca4a1399c5b8928b2780884ca81b48b3a6128c9fce11b464cd0bf2928d4f22924a7d2d6a4c4a00e71d9c7603375a2
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning].
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [v1.0.0-beta.4] - 2020-01-14
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- [#114] `ActiveInteractor::Organizer::InteractorInterface`
|
15
|
+
- [#114] `ActiveInteractor::Organizer::InteractorInterfaceCollection`
|
16
|
+
- [#115] `ActiveInteractor::Interactor#options`
|
17
|
+
- [#115] `ActiveInteractor::Interactor#with_options`
|
18
|
+
- [#115] `ActiveInteractor::Interactor::PerformOptions#skip_each_perform_callbacks`
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
- [#115] `ActiveInteractor::Interactor::Worker#execute_perform` and `#execute_perform!` no longer accept arguments,
|
23
|
+
use `ActiveInteractor::Interactor#with_options` instead.
|
24
|
+
- [#115] `ActiveInteractor::Organizer` can now skip `each_perform` callbacks with
|
25
|
+
the option `skip_each_perform_callbacks`
|
26
|
+
|
27
|
+
### Removed
|
28
|
+
|
29
|
+
- [#115] `ActiveInteractor::Interactor#execute_rollback`
|
30
|
+
- [#115] `ActiveInteractor::Interactor::Worker#run_callbacks`
|
31
|
+
|
10
32
|
## [v1.0.0-beta.3] - 2020-01-12
|
11
33
|
|
12
34
|
### Added
|
@@ -147,7 +169,8 @@ and this project adheres to [Semantic Versioning].
|
|
147
169
|
|
148
170
|
<!-- versions -->
|
149
171
|
|
150
|
-
[Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0-beta.
|
172
|
+
[Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0-beta.4...HEAD
|
173
|
+
[v1.0.0-beta.4]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0-beta.3...v1.0.0-beta.4
|
151
174
|
[v1.0.0-beta.3]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0-beta.2...v1.0.0-beta.3
|
152
175
|
[v1.0.0-beta.2]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0-beta.1...v1.0.0-beta.2
|
153
176
|
[v1.0.0-beta.1]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.7...v1.0.0-beta.1
|
@@ -181,3 +204,5 @@ and this project adheres to [Semantic Versioning].
|
|
181
204
|
[#105]: https://github.com/aaronmallen/activeinteractor/pull/105
|
182
205
|
[#109]: https://github.com/aaronmallen/activeinteractor/pull/109
|
183
206
|
[#110]: https://github.com/aaronmallen/activeinteractor/pull/110
|
207
|
+
[#114]:https://github.com/aaronmallen/activeinteractor/pull/114
|
208
|
+
[#115]: https://github.com/aaronmallen/activeinteractor/pull/115
|
data/README.md
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
|
12
12
|
Ruby interactors with [ActiveModel::Validations] based on the [interactor][collective_idea_interactors] gem.
|
13
13
|
|
14
|
+
**ActiveInteractor v1.0.0 is currently in beta. For documentation on the current stable version please
|
15
|
+
see [v0.1.7](https://github.com/aaronmallen/activeinteractor/tree/0-1-stable)**
|
16
|
+
|
14
17
|
<!-- TOC -->
|
15
18
|
|
16
19
|
* [Getting Started](#getting-started)
|
@@ -26,7 +29,8 @@ Ruby interactors with [ActiveModel::Validations] based on the [interactor][colle
|
|
26
29
|
* [Kinds of Interactors](#kinds-of-interactors)
|
27
30
|
* [Interactors](#interactors)
|
28
31
|
* [Organizers](#organizers)
|
29
|
-
|
32
|
+
* [Organizing Interactors Conditionally](#organizing-interactors-conditionally)
|
33
|
+
* [Running Interactors In Parallel](#running-interactors-in-parallel)
|
30
34
|
* [Rollback](#rollback)
|
31
35
|
* [Callbacks](#callbacks)
|
32
36
|
* [Validation Callbacks](#validation-callbacks)
|
@@ -46,7 +50,7 @@ Ruby interactors with [ActiveModel::Validations] based on the [interactor][colle
|
|
46
50
|
Add this line to your application's Gemfile:
|
47
51
|
|
48
52
|
```ruby
|
49
|
-
gem 'activeinteractor'
|
53
|
+
gem 'activeinteractor', '~> 1.0.0.beta.3'
|
50
54
|
```
|
51
55
|
|
52
56
|
And then execute:
|
@@ -58,7 +62,7 @@ bundle
|
|
58
62
|
Or install it yourself as:
|
59
63
|
|
60
64
|
```bash
|
61
|
-
gem install activeinteractor
|
65
|
+
gem install activeinteractor --pre
|
62
66
|
```
|
63
67
|
|
64
68
|
## What is an Interactor
|
@@ -422,7 +426,27 @@ end
|
|
422
426
|
The organizer passes its context to the interactors that it organizes, one at a time and in order. Each interactor may
|
423
427
|
change that context before it's passed along to the next interactor.
|
424
428
|
|
425
|
-
|
429
|
+
###### Organizing Interactors Conditionally
|
430
|
+
|
431
|
+
We can also add conditional statements to our organizer by passing a block to the `#organize` method:
|
432
|
+
|
433
|
+
```ruby
|
434
|
+
class PlaceOrder < ActiveInteractor::Organizer
|
435
|
+
organize do
|
436
|
+
add :create_order, if :user_registered?
|
437
|
+
add :charge_card, if: -> { context.order_number }
|
438
|
+
add :send_thank_you, if: -> { context.order_number }
|
439
|
+
end
|
440
|
+
|
441
|
+
private
|
442
|
+
|
443
|
+
def user_registered?
|
444
|
+
context.user&.registered?
|
445
|
+
end
|
446
|
+
end
|
447
|
+
```
|
448
|
+
|
449
|
+
###### Running Interactors In Parallel
|
426
450
|
|
427
451
|
Organizers can be told to run their interactors in parallel with the `#perform_in_parallel` class method. This
|
428
452
|
will run each interactor in parallel with one and other only passing the original context to each organizer.
|
@@ -11,7 +11,7 @@ module ActiveInteractor
|
|
11
11
|
extend ClassMethods
|
12
12
|
include Callbacks
|
13
13
|
include Context
|
14
|
-
delegate :execute_perform, :execute_perform!,
|
14
|
+
delegate :execute_perform, :execute_perform!, to: :worker
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -23,10 +23,11 @@ module ActiveInteractor
|
|
23
23
|
# MyInteractor.perform(name: 'Aaron')
|
24
24
|
# #=> <#MyInteractor::Context name='Aaron'>
|
25
25
|
# @param context [Hash|Context::Base] attributes to assign to the interactor context
|
26
|
-
# @param options [
|
26
|
+
# @param options [Hash] execution options for the interactor perform step
|
27
|
+
# see {PerformOptions}
|
27
28
|
# @return [Context::Base] an instance of context.
|
28
|
-
def perform(context = {}, options =
|
29
|
-
new(context).
|
29
|
+
def perform(context = {}, options = {})
|
30
|
+
new(context).with_options(options).execute_perform
|
30
31
|
end
|
31
32
|
|
32
33
|
# Run an interactor context. The {.perform!} method behaves identically to
|
@@ -37,14 +38,22 @@ module ActiveInteractor
|
|
37
38
|
# MyInteractor.perform!(name: 'Aaron')
|
38
39
|
# #=> <#MyInteractor::Context name='Aaron'>
|
39
40
|
# @param context [Hash|Context::Base] attributes to assign to the interactor context
|
40
|
-
# @param options [
|
41
|
+
# @param options [Hash] execution options for the interactor perform step
|
42
|
+
# see {PerformOptions}
|
41
43
|
# @raise [Error::ContextFailure] if the context fails.
|
42
44
|
# @return [Context::Base] an instance of context.
|
43
|
-
def perform!(context = {}, options =
|
44
|
-
new(context).
|
45
|
+
def perform!(context = {}, options = {})
|
46
|
+
new(context).with_options(options).execute_perform!
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
50
|
+
# Options for invokation of {#perform}
|
51
|
+
# @since 1.0.0
|
52
|
+
# @return [PerformOptions] the options
|
53
|
+
def options
|
54
|
+
@options ||= PerformOptions.new
|
55
|
+
end
|
56
|
+
|
48
57
|
# Invoke an Interactor instance without any hooks, tracking, or rollback
|
49
58
|
# @abstract It is expected that the {#perform} method is overwritten
|
50
59
|
# for each interactor class.
|
@@ -55,6 +64,15 @@ module ActiveInteractor
|
|
55
64
|
# failure is expected to overwrite the {#rollback} method.
|
56
65
|
def rollback; end
|
57
66
|
|
67
|
+
# Set options for invokation of {#perform}
|
68
|
+
# @since 1.0.0
|
69
|
+
# @param options [PerformOptions|Hash] the perform options
|
70
|
+
# @return [Base] the instance of {Base}
|
71
|
+
def with_options(options)
|
72
|
+
@options = options.is_a?(PerformOptions) ? options : PerformOptions.new(options)
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
58
76
|
private
|
59
77
|
|
60
78
|
def worker
|
@@ -5,6 +5,8 @@ module ActiveInteractor
|
|
5
5
|
# Options object for interactor perform
|
6
6
|
# @author Aaron Allen <hello@aaronmallen.me>
|
7
7
|
# @since 1.0.0
|
8
|
+
# @!attribute [rw] skip_each_perform_callbacks
|
9
|
+
# @return [Boolean] whether or not to skip :each_perform callbacks for an {Organizer}
|
8
10
|
# @!attribute [rw] skip_perform_callbacks
|
9
11
|
# @return [Boolean] whether or not to skip :perform callbacks
|
10
12
|
# @!attribute [rw] skip_rollback
|
@@ -19,27 +21,9 @@ module ActiveInteractor
|
|
19
21
|
# @!attribute [rw] validate_on_called
|
20
22
|
# @return [Boolean] whether or not to run validation on :called
|
21
23
|
class PerformOptions
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
skip_perform_callbacks: false,
|
26
|
-
skip_rollback: false,
|
27
|
-
skip_rollback_callbacks: false,
|
28
|
-
validate: true,
|
29
|
-
validate_on_calling: true,
|
30
|
-
validate_on_called: true
|
31
|
-
}.freeze
|
32
|
-
|
33
|
-
attr_accessor :skip_perform_callbacks, :skip_rollback, :skip_rollback_callbacks,
|
34
|
-
:validate, :validate_on_calling, :validate_on_called
|
35
|
-
|
36
|
-
# @param options [Hash] the attributes for the {PerformOptions}
|
37
|
-
# @return [PerformOptions] a new instance of {PerformOptions}
|
38
|
-
def initialize(options = {})
|
39
|
-
DEFAULTS.dup.merge(options).each do |key, value|
|
40
|
-
instance_variable_set("@#{key}", value)
|
41
|
-
end
|
42
|
-
end
|
24
|
+
include ActiveInteractor::Configurable
|
25
|
+
defaults skip_each_perform_callbacks: false, skip_perform_callbacks: false, skip_rollback: false,
|
26
|
+
skip_rollback_callbacks: false, validate: true, validate_on_calling: true, validate_on_called: true
|
43
27
|
end
|
44
28
|
end
|
45
29
|
end
|
@@ -8,108 +8,99 @@ module ActiveInteractor
|
|
8
8
|
# @author Aaron Allen <hello@aaronmallen.me>
|
9
9
|
# @since 0.0.2
|
10
10
|
class Worker
|
11
|
-
delegate :run_callbacks, to: :interactor
|
12
|
-
|
13
11
|
# @param interactor [Base] an instance of interactor
|
14
12
|
# @return [Worker] a new instance of {Worker}
|
15
13
|
def initialize(interactor)
|
16
|
-
|
14
|
+
options = interactor.options.dup
|
15
|
+
@interactor = interactor.dup.with_options(options)
|
17
16
|
end
|
18
17
|
|
19
18
|
# Calls {#execute_perform!} and rescues {Error::ContextFailure}
|
20
|
-
# @param options [PerformOptions|Hash] execution options for the interactor perform step
|
21
19
|
# @return [Context::Base] an instance of {Context::Base}
|
22
|
-
def execute_perform
|
23
|
-
execute_perform!
|
20
|
+
def execute_perform
|
21
|
+
execute_perform!
|
24
22
|
rescue Error::ContextFailure => e
|
25
23
|
ActiveInteractor.logger.error("ActiveInteractor: #{e}")
|
26
24
|
context
|
27
25
|
end
|
28
26
|
|
29
27
|
# Calls {Interactor#perform} with callbacks and context validation
|
30
|
-
# @param options [PerformOptions|Hash] execution options for the interactor perform step
|
31
28
|
# @raise [Error::ContextFailure] if the context fails
|
32
29
|
# @return [Context::Base] an instance of {Context::Base}
|
33
|
-
def execute_perform!
|
34
|
-
|
35
|
-
execute_context!(options)
|
30
|
+
def execute_perform!
|
31
|
+
execute_context!
|
36
32
|
rescue StandardError => e
|
37
|
-
handle_error(e
|
33
|
+
handle_error(e)
|
38
34
|
end
|
39
35
|
|
40
36
|
# Calls {Interactor#rollback} with callbacks
|
41
37
|
# @return [Boolean] `true` if rolled back successfully or `false` if already
|
42
38
|
# rolled back
|
43
|
-
def execute_rollback
|
44
|
-
|
45
|
-
return if options.skip_rollback
|
39
|
+
def execute_rollback
|
40
|
+
return if interactor.options.skip_rollback
|
46
41
|
|
47
|
-
execute_interactor_rollback!
|
42
|
+
execute_interactor_rollback!
|
48
43
|
end
|
49
44
|
|
50
45
|
private
|
51
46
|
|
52
47
|
attr_reader :context, :interactor
|
53
48
|
|
54
|
-
def execute_context!
|
55
|
-
if options.skip_perform_callbacks
|
56
|
-
execute_context_with_validation_check!
|
49
|
+
def execute_context!
|
50
|
+
if interactor.options.skip_perform_callbacks
|
51
|
+
execute_context_with_validation_check!
|
57
52
|
else
|
58
|
-
execute_context_with_callbacks!
|
53
|
+
execute_context_with_callbacks!
|
59
54
|
end
|
60
55
|
end
|
61
56
|
|
62
|
-
def execute_context_with_callbacks!
|
63
|
-
run_callbacks :perform do
|
64
|
-
execute_context_with_validation_check!
|
57
|
+
def execute_context_with_callbacks!
|
58
|
+
interactor.run_callbacks :perform do
|
59
|
+
execute_context_with_validation_check!
|
65
60
|
@context = interactor.finalize_context!
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
69
|
-
def execute_context_with_validation!
|
70
|
-
validate_on_calling
|
64
|
+
def execute_context_with_validation!
|
65
|
+
validate_on_calling
|
71
66
|
interactor.perform
|
72
|
-
validate_on_called
|
67
|
+
validate_on_called
|
73
68
|
end
|
74
69
|
|
75
|
-
def execute_context_with_validation_check!
|
76
|
-
return interactor.perform unless options.validate
|
70
|
+
def execute_context_with_validation_check!
|
71
|
+
return interactor.perform unless interactor.options.validate
|
77
72
|
|
78
|
-
execute_context_with_validation!
|
73
|
+
execute_context_with_validation!
|
79
74
|
end
|
80
75
|
|
81
|
-
def execute_interactor_rollback!
|
82
|
-
return interactor.context_rollback! if options.skip_rollback_callbacks
|
76
|
+
def execute_interactor_rollback!
|
77
|
+
return interactor.context_rollback! if interactor.options.skip_rollback_callbacks
|
83
78
|
|
84
|
-
run_callbacks :rollback do
|
79
|
+
interactor.run_callbacks :rollback do
|
85
80
|
interactor.context_rollback!
|
86
81
|
end
|
87
82
|
end
|
88
83
|
|
89
|
-
def handle_error(exception
|
84
|
+
def handle_error(exception)
|
90
85
|
@context = interactor.finalize_context!
|
91
|
-
execute_rollback
|
86
|
+
execute_rollback
|
92
87
|
raise exception
|
93
88
|
end
|
94
89
|
|
95
|
-
def parse_options(options)
|
96
|
-
@options = options.is_a?(PerformOptions) ? options : PerformOptions.new(options)
|
97
|
-
end
|
98
|
-
|
99
90
|
def validate_context(validation_context = nil)
|
100
|
-
run_callbacks :validation do
|
91
|
+
interactor.run_callbacks :validation do
|
101
92
|
interactor.context_valid?(validation_context)
|
102
93
|
end
|
103
94
|
end
|
104
95
|
|
105
|
-
def validate_on_calling
|
106
|
-
return unless options.validate_on_calling
|
96
|
+
def validate_on_calling
|
97
|
+
return unless interactor.options.validate_on_calling
|
107
98
|
|
108
99
|
interactor.context_fail! unless validate_context(:calling)
|
109
100
|
end
|
110
101
|
|
111
|
-
def validate_on_called
|
112
|
-
return unless options.validate_on_called
|
102
|
+
def validate_on_called
|
103
|
+
return unless interactor.options.validate_on_called
|
113
104
|
|
114
105
|
interactor.context_fail! unless validate_context(:called)
|
115
106
|
end
|
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_support/core_ext/class/attribute'
|
4
|
-
|
4
|
+
|
5
|
+
require 'active_interactor/organizer/interactor_interface_collection'
|
5
6
|
|
6
7
|
module ActiveInteractor
|
7
8
|
# A base Organizer class. All organizers should inherit from
|
8
9
|
# {Organizer}.
|
9
10
|
# @author Aaron Allen <hello@aaronmallen.me>
|
10
11
|
# @since 0.0.1
|
11
|
-
# @!attribute [r] organized
|
12
|
-
# @!scope class
|
13
|
-
# @return [Array<Base>] the organized interactors
|
14
12
|
# @!attribute [r] parallel
|
15
13
|
# @since 1.0.0
|
16
14
|
# @!scope class
|
@@ -36,7 +34,6 @@ module ActiveInteractor
|
|
36
34
|
# MyOrganizer.perform
|
37
35
|
# #=> <MyOrganizer::Context interactor1=true interactor2=true>
|
38
36
|
class Organizer < Base
|
39
|
-
class_attribute :organized, instance_writer: false, default: []
|
40
37
|
class_attribute :parallel, instance_writer: false, default: false
|
41
38
|
define_callbacks :each_perform
|
42
39
|
|
@@ -83,7 +80,6 @@ module ActiveInteractor
|
|
83
80
|
|
84
81
|
# Define a callback to call around each organized interactor's
|
85
82
|
# {Base.perform} has been invokation
|
86
|
-
#
|
87
83
|
# @example
|
88
84
|
# class MyInteractor1 < ActiveInteractor::Base
|
89
85
|
# before_perform :print_name
|
@@ -129,7 +125,6 @@ module ActiveInteractor
|
|
129
125
|
|
130
126
|
# Define a callback to call before each organized interactor's
|
131
127
|
# {Base.perform} has been invoked
|
132
|
-
#
|
133
128
|
# @example
|
134
129
|
# class MyInteractor1 < ActiveInteractor::Base
|
135
130
|
# before_perform :print_name
|
@@ -172,21 +167,50 @@ module ActiveInteractor
|
|
172
167
|
# Declare Interactors to be invoked as part of the
|
173
168
|
# organizer's invocation. These interactors are invoked in
|
174
169
|
# the order in which they are declared
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
# organize InteractorOne, InteractorTwo
|
170
|
+
# @example Basic interactor organization
|
171
|
+
# class MyOrganizer < ActiveInteractor::Organizer
|
172
|
+
# organize :interactor_one, :interactor_two
|
179
173
|
# end
|
180
|
-
#
|
181
|
-
# class
|
182
|
-
# organize
|
174
|
+
# @example Conditional interactor organization with block
|
175
|
+
# class MyOrganizer < ActiveInteractor::Organizer
|
176
|
+
# organize do
|
177
|
+
# add :interactor_one
|
178
|
+
# add :interactor_two, if: -> { context.valid? }
|
179
|
+
# end
|
183
180
|
# end
|
181
|
+
# @example Conditional interactor organization with method
|
182
|
+
# class MyOrganizer < ActiveInteractor::Organizer
|
183
|
+
# organize do
|
184
|
+
# add :interactor_one
|
185
|
+
# add :interactor_two, unless: :invalid_context?
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# private
|
184
189
|
#
|
185
|
-
#
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
+
# def invalid_context?
|
191
|
+
# !context.valid?
|
192
|
+
# end
|
193
|
+
# end
|
194
|
+
# @example Interactor organization with perform options
|
195
|
+
# class MyOrganizer < ActiveInteractor::Organizer
|
196
|
+
# organize do
|
197
|
+
# add :interactor_one, validate: false
|
198
|
+
# add :interactor_two, skip_perform_callbacks: true
|
199
|
+
# end
|
200
|
+
# end
|
201
|
+
# @param interactors [Array<Base|Symbol|String>] the interactors to call
|
202
|
+
# @yield [.organized] if block given
|
203
|
+
# @return [InteractorInterfaceCollection] an instance of {InteractorInterfaceCollection}
|
204
|
+
def self.organize(*interactors, &block)
|
205
|
+
organized.concat(interactors) if interactors
|
206
|
+
organized.instance_eval(&block) if block
|
207
|
+
organized
|
208
|
+
end
|
209
|
+
|
210
|
+
# Organized interactors
|
211
|
+
# @return [InteractorInterfaceCollection] an instance of {InteractorInterfaceCollection}
|
212
|
+
def self.organized
|
213
|
+
@organized ||= InteractorInterfaceCollection.new
|
190
214
|
end
|
191
215
|
|
192
216
|
# Run organized interactors in parallel
|
@@ -196,7 +220,7 @@ module ActiveInteractor
|
|
196
220
|
end
|
197
221
|
|
198
222
|
# Invoke the organized interactors. An organizer is
|
199
|
-
# expected not to define its own {
|
223
|
+
# expected not to define its own {Interactor#perform #perform} method
|
200
224
|
# in favor of this default implementation.
|
201
225
|
def perform
|
202
226
|
if self.class.parallel
|
@@ -208,11 +232,16 @@ module ActiveInteractor
|
|
208
232
|
|
209
233
|
private
|
210
234
|
|
211
|
-
def
|
235
|
+
def execute_interactor(interface, fail_on_error = false, perform_options = {})
|
236
|
+
interface.perform(self, context, fail_on_error, perform_options)
|
237
|
+
end
|
238
|
+
|
239
|
+
def execute_interactor_with_callbacks(interface, fail_on_error = false, perform_options = {})
|
240
|
+
args = [interface, fail_on_error, perform_options]
|
241
|
+
return execute_interactor(*args) if options.skip_each_perform_callbacks
|
242
|
+
|
212
243
|
run_callbacks :each_perform do
|
213
|
-
|
214
|
-
method = fail_on_error ? :execute_perform! : :execute_perform
|
215
|
-
instance.send(method, execute_options)
|
244
|
+
execute_interactor(*args)
|
216
245
|
end
|
217
246
|
end
|
218
247
|
|
@@ -222,16 +251,17 @@ module ActiveInteractor
|
|
222
251
|
end
|
223
252
|
|
224
253
|
def perform_in_order
|
225
|
-
self.class.organized.each do |
|
226
|
-
|
254
|
+
self.class.organized.each do |interface|
|
255
|
+
result = execute_interactor_with_callbacks(interface, true)
|
256
|
+
context.merge!(result) if result
|
227
257
|
end
|
228
258
|
rescue Error::ContextFailure => e
|
229
259
|
context.merge!(e.context)
|
230
260
|
end
|
231
261
|
|
232
262
|
def perform_in_parallel
|
233
|
-
results = self.class.organized.map do |
|
234
|
-
Thread.new { execute_interactor_with_callbacks(
|
263
|
+
results = self.class.organized.map do |interface|
|
264
|
+
Thread.new { execute_interactor_with_callbacks(interface, false, skip_rollback: true) }
|
235
265
|
end
|
236
266
|
merge_contexts(results.map(&:value))
|
237
267
|
end
|