activeinteractor 1.2.2 → 2.0.0.alpha.1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/LICENSE +1 -1
- data/README.md +4 -64
- data/lib/active_interactor/base.rb +77 -29
- data/lib/active_interactor/errors.rb +12 -0
- data/lib/active_interactor/result.rb +73 -0
- data/lib/active_interactor.rb +3 -101
- data/sig/active_interactor.rbs +3 -0
- metadata +23 -86
- data/.yardopts +0 -12
- data/lib/active_interactor/config.rb +0 -60
- data/lib/active_interactor/configurable.rb +0 -53
- data/lib/active_interactor/context/attributes.rb +0 -179
- data/lib/active_interactor/context/base.rb +0 -333
- data/lib/active_interactor/context/errors.rb +0 -57
- data/lib/active_interactor/context/loader.rb +0 -50
- data/lib/active_interactor/context/status.rb +0 -106
- data/lib/active_interactor/error.rb +0 -46
- data/lib/active_interactor/interactor/callbacks.rb +0 -293
- data/lib/active_interactor/interactor/context.rb +0 -378
- data/lib/active_interactor/interactor/perform.rb +0 -260
- data/lib/active_interactor/interactor/worker.rb +0 -120
- data/lib/active_interactor/models.rb +0 -50
- data/lib/active_interactor/organizer/base.rb +0 -18
- data/lib/active_interactor/organizer/callbacks.rb +0 -275
- data/lib/active_interactor/organizer/interactor_interface.rb +0 -127
- data/lib/active_interactor/organizer/interactor_interface_collection.rb +0 -62
- data/lib/active_interactor/organizer/organize.rb +0 -67
- data/lib/active_interactor/organizer/perform.rb +0 -112
- data/lib/active_interactor/rails/orm/active_record.rb +0 -5
- data/lib/active_interactor/rails/orm/dynamoid.rb +0 -5
- data/lib/active_interactor/rails/orm/mongoid.rb +0 -5
- data/lib/active_interactor/rails/railtie.rb +0 -21
- data/lib/active_interactor/rails.rb +0 -4
- data/lib/active_interactor/version.rb +0 -45
- data/lib/rails/generators/active_interactor/application_context_generator.rb +0 -21
- data/lib/rails/generators/active_interactor/application_interactor_generator.rb +0 -21
- data/lib/rails/generators/active_interactor/application_organizer_generator.rb +0 -21
- data/lib/rails/generators/active_interactor/base.rb +0 -29
- data/lib/rails/generators/active_interactor/generator.rb +0 -21
- data/lib/rails/generators/active_interactor/install_generator.rb +0 -16
- data/lib/rails/generators/active_interactor.rb +0 -5
- data/lib/rails/generators/interactor/context/rspec_generator.rb +0 -17
- data/lib/rails/generators/interactor/context/test_unit_generator.rb +0 -17
- data/lib/rails/generators/interactor/context_generator.rb +0 -22
- data/lib/rails/generators/interactor/generates_context.rb +0 -28
- data/lib/rails/generators/interactor/interactor_generator.rb +0 -25
- data/lib/rails/generators/interactor/organizer_generator.rb +0 -39
- data/lib/rails/generators/interactor/rspec_generator.rb +0 -15
- data/lib/rails/generators/interactor/test_unit_generator.rb +0 -15
- data/lib/rails/generators/templates/active_interactor.erb +0 -17
- data/lib/rails/generators/templates/application_context.rb +0 -4
- data/lib/rails/generators/templates/application_interactor.rb +0 -4
- data/lib/rails/generators/templates/application_organizer.rb +0 -4
- data/lib/rails/generators/templates/context.erb +0 -7
- data/lib/rails/generators/templates/context_spec.erb +0 -7
- data/lib/rails/generators/templates/context_test_unit.erb +0 -9
- data/lib/rails/generators/templates/interactor.erb +0 -15
- data/lib/rails/generators/templates/interactor_spec.erb +0 -7
- data/lib/rails/generators/templates/interactor_test_unit.erb +0 -9
- data/lib/rails/generators/templates/organizer.erb +0 -13
@@ -1,120 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Interactor
|
5
|
-
# A worker class to call {Base interactor} {Interactor::Perform#perform #perform} and
|
6
|
-
# {Interactor::Perform#rollback #rollback} methods in a thread safe manner.
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
10
|
-
# @since 0.1.0
|
11
|
-
class Worker
|
12
|
-
# Initialize a new instance of {Worker}
|
13
|
-
#
|
14
|
-
# @param interactor [Base] an {Base interactor} instance
|
15
|
-
# @return [Worker] a new instance of {Worker}
|
16
|
-
def initialize(interactor)
|
17
|
-
@interactor = interactor.deep_dup
|
18
|
-
end
|
19
|
-
|
20
|
-
# Run the {Base interactor} instance's {Interactor::Perform#perform #perform} with callbacks and validation.
|
21
|
-
#
|
22
|
-
# @return [Class] a {ActiveInteractor::Context::Base context} instance
|
23
|
-
def execute_perform
|
24
|
-
execute_perform!
|
25
|
-
rescue Error::ContextFailure => e
|
26
|
-
ActiveInteractor.logger.error("ActiveInteractor: #{e}")
|
27
|
-
context
|
28
|
-
end
|
29
|
-
|
30
|
-
# Run the {Base interactor} instance's {Interactor::Perform#perform #perform} with callbacks and validation
|
31
|
-
# without rescuing {Error::ContextFailure}.
|
32
|
-
#
|
33
|
-
# @raise [Error::ContextFailure] if the {Base interactor} fails it's {ActiveInteractor::Context::Base context}
|
34
|
-
# @return [Class] a {ActiveInteractor::Context::Base context} instance
|
35
|
-
def execute_perform!
|
36
|
-
execute_context!
|
37
|
-
rescue StandardError => e
|
38
|
-
handle_error(e)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Run the {Base interactor} instance's {Interactor::Perform#rollback #rollback} with callbacks
|
42
|
-
#
|
43
|
-
# @return [Boolean] `true` if context was successfully rolled back
|
44
|
-
def execute_rollback
|
45
|
-
return if interactor.options.skip_rollback
|
46
|
-
|
47
|
-
execute_interactor_rollback!
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
attr_reader :context, :interactor
|
53
|
-
|
54
|
-
def execute_context!
|
55
|
-
if interactor.options.skip_perform_callbacks
|
56
|
-
execute_context_with_validation_check!
|
57
|
-
else
|
58
|
-
execute_context_with_callbacks!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def execute_context_with_callbacks!
|
63
|
-
result = interactor.run_callbacks :perform do
|
64
|
-
execute_context_with_validation_check!
|
65
|
-
@context = interactor.finalize_context!
|
66
|
-
end
|
67
|
-
|
68
|
-
if context&.success? && interactor.respond_to?(:run_deferred_after_perform_callbacks_on_children)
|
69
|
-
interactor.run_deferred_after_perform_callbacks_on_children
|
70
|
-
end
|
71
|
-
|
72
|
-
result
|
73
|
-
end
|
74
|
-
|
75
|
-
def execute_context_with_validation!
|
76
|
-
validate_on_calling
|
77
|
-
interactor.perform
|
78
|
-
validate_on_called
|
79
|
-
end
|
80
|
-
|
81
|
-
def execute_context_with_validation_check!
|
82
|
-
return interactor.perform unless interactor.options.validate
|
83
|
-
|
84
|
-
execute_context_with_validation!
|
85
|
-
end
|
86
|
-
|
87
|
-
def execute_interactor_rollback!
|
88
|
-
return interactor.context_rollback! if interactor.options.skip_rollback_callbacks
|
89
|
-
|
90
|
-
interactor.run_callbacks :rollback do
|
91
|
-
interactor.context_rollback!
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def handle_error(exception)
|
96
|
-
@context = interactor.finalize_context!
|
97
|
-
execute_rollback
|
98
|
-
raise exception
|
99
|
-
end
|
100
|
-
|
101
|
-
def validate_context(validation_context = nil)
|
102
|
-
interactor.run_callbacks :validation do
|
103
|
-
interactor.context_valid?(validation_context)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def validate_on_calling
|
108
|
-
return unless interactor.options.validate_on_calling
|
109
|
-
|
110
|
-
interactor.context_fail! unless validate_context(:calling)
|
111
|
-
end
|
112
|
-
|
113
|
-
def validate_on_called
|
114
|
-
return unless interactor.options.validate_on_called
|
115
|
-
|
116
|
-
interactor.context_fail! unless validate_context(:called)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
# Helper methods for using classes that do not inherit from {Context::Base} as {Context::Base context} objects
|
5
|
-
# for {Base interactors}. Classes should extend {Models}.
|
6
|
-
#
|
7
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
8
|
-
# @since 1.0.0
|
9
|
-
module Models
|
10
|
-
# Instance methods needed for a {Context::Base context} class to function properly.
|
11
|
-
#
|
12
|
-
# @private
|
13
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
14
|
-
# @since 1.0.0
|
15
|
-
module InstanceMethods
|
16
|
-
def initialize(*)
|
17
|
-
@attributes = self.class._default_attributes&.deep_dup
|
18
|
-
super
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Include methods needed for a {Context::Base context} class to function properly.
|
23
|
-
#
|
24
|
-
# @note You must include ActiveModel::Model and ActiveModel::Attributes or a similar implementation for
|
25
|
-
# the object to function properly.
|
26
|
-
#
|
27
|
-
# @example
|
28
|
-
# class User
|
29
|
-
# include ActiveModel::Model
|
30
|
-
# include ActiveModel::Attributes
|
31
|
-
# extend ActiveInteractor::Models
|
32
|
-
# acts_as_context
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# class MyInteractor < ActiveInteractor::Base
|
36
|
-
# contextualize_with :user
|
37
|
-
# end
|
38
|
-
def acts_as_context
|
39
|
-
class_eval do
|
40
|
-
extend ActiveInteractor::Context::Attributes::ClassMethods
|
41
|
-
|
42
|
-
include ActiveInteractor::Context::Attributes
|
43
|
-
include ActiveInteractor::Context::Errors
|
44
|
-
include ActiveInteractor::Context::Status
|
45
|
-
include ActiveInteractor::Models::InstanceMethods
|
46
|
-
delegate :each_pair, to: :attributes
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Organizer
|
5
|
-
# The base {Base organizer} class all {Base organizers} should inherit from.
|
6
|
-
#
|
7
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
8
|
-
# @since 1.0.0
|
9
|
-
class Base < ActiveInteractor::Base
|
10
|
-
extend ActiveInteractor::Organizer::Callbacks::ClassMethods
|
11
|
-
extend ActiveInteractor::Organizer::Organize::ClassMethods
|
12
|
-
extend ActiveInteractor::Organizer::Perform::ClassMethods
|
13
|
-
|
14
|
-
include ActiveInteractor::Organizer::Callbacks
|
15
|
-
include ActiveInteractor::Organizer::Perform
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,275 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Organizer
|
5
|
-
# Organizer callback methods. Because {Callbacks} is a module classes should include {Callbacks} rather than
|
6
|
-
# inherit from it.
|
7
|
-
#
|
8
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
9
|
-
# @since 1.0.0
|
10
|
-
# @see https://github.com/aaronmallen/activeinteractor/wiki/Callbacks Callbacks
|
11
|
-
# @see https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html ActiveSupport::Callbacks
|
12
|
-
module Callbacks
|
13
|
-
# Organizer callback class methods. Because {ClassMethods} is a module classes should extend {ClassMethods}
|
14
|
-
# rather than inherit from it.
|
15
|
-
#
|
16
|
-
# @author Aaron Allen
|
17
|
-
# @since 1.0.0
|
18
|
-
module ClassMethods
|
19
|
-
# Define a callback to call after each {Organizer::Organize::ClassMethods#organized organized}
|
20
|
-
# {ActiveInteractor::Base interactor's} {Interactor::Perform#perform #perform} method has been called.
|
21
|
-
#
|
22
|
-
# @since 0.1.3
|
23
|
-
#
|
24
|
-
# @example
|
25
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
26
|
-
# def perform
|
27
|
-
# puts 'MyInteractor1'
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
32
|
-
# def perform
|
33
|
-
# puts 'MyInteractor2'
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
38
|
-
# after_each_perform :print_done
|
39
|
-
#
|
40
|
-
# organized MyInteractor1, MyInteractor2
|
41
|
-
#
|
42
|
-
# private
|
43
|
-
#
|
44
|
-
# def print_done
|
45
|
-
# puts 'Done'
|
46
|
-
# end
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# MyOrganizer.perform
|
50
|
-
# "MyInteractor1"
|
51
|
-
# "Done"
|
52
|
-
# "MyInteractor2"
|
53
|
-
# "Done"
|
54
|
-
# #=> <MyOrganizer::Context>
|
55
|
-
def after_each_perform(*filters, &block)
|
56
|
-
set_callback(:each_perform, :after, *filters, &block)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Define a callback to call around each {Organizer::Organize::ClassMethods#organized organized}
|
60
|
-
# {ActiveInteractor::Base interactor's} {Interactor::Perform#perform #perform} method call.
|
61
|
-
#
|
62
|
-
# @since 0.1.3
|
63
|
-
#
|
64
|
-
# @example
|
65
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
66
|
-
# def perform
|
67
|
-
# puts 'MyInteractor1'
|
68
|
-
# sleep(1)
|
69
|
-
# end
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
73
|
-
# def perform
|
74
|
-
# puts 'MyInteractor2'
|
75
|
-
# sleep(1)
|
76
|
-
# end
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
80
|
-
# around_each_perform :print_time
|
81
|
-
#
|
82
|
-
# organized MyInteractor1, MyInteractor2
|
83
|
-
#
|
84
|
-
# private
|
85
|
-
#
|
86
|
-
# def print_time
|
87
|
-
# puts Time.now.utc
|
88
|
-
# yield
|
89
|
-
# puts Time.now.utc
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
#
|
93
|
-
# MyOrganizer.perform
|
94
|
-
# "2019-04-01 00:00:00 UTC"
|
95
|
-
# "MyInteractor1"
|
96
|
-
# "2019-04-01 00:00:01 UTC"
|
97
|
-
# "2019-04-01 00:00:01 UTC"
|
98
|
-
# "MyInteractor2"
|
99
|
-
# "2019-04-01 00:00:02 UTC"
|
100
|
-
# #=> <MyOrganizer::Context>
|
101
|
-
def around_each_perform(*filters, &block)
|
102
|
-
set_callback(:each_perform, :around, *filters, &block)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Define a callback to call before each {Organizer::Organize::ClassMethods#organized organized}
|
106
|
-
# {ActiveInteractor::Base interactor's} {Interactor::Perform#perform #perform} method has been called.
|
107
|
-
#
|
108
|
-
# @since 0.1.3
|
109
|
-
#
|
110
|
-
# @example
|
111
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
112
|
-
# def perform
|
113
|
-
# puts 'MyInteractor1'
|
114
|
-
# end
|
115
|
-
# end
|
116
|
-
#
|
117
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
118
|
-
# def perform
|
119
|
-
# puts 'MyInteractor2'
|
120
|
-
# end
|
121
|
-
# end
|
122
|
-
#
|
123
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
124
|
-
# before_each_perform :print_starting
|
125
|
-
#
|
126
|
-
# organized MyInteractor1, MyInteractor2
|
127
|
-
#
|
128
|
-
# private
|
129
|
-
#
|
130
|
-
# def print_starting
|
131
|
-
# puts 'Starting'
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# MyOrganizer.perform
|
136
|
-
# "Starting"
|
137
|
-
# "MyInteractor1"
|
138
|
-
# "Starting"
|
139
|
-
# "MyInteractor2"
|
140
|
-
# #=> <MyOrganizer::Context>
|
141
|
-
def before_each_perform(*filters, &block)
|
142
|
-
set_callback(:each_perform, :before, *filters, &block)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Define a callback to call after all {Organizer::Organize::ClassMethods#organized organized}
|
146
|
-
# {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} methods have been called.
|
147
|
-
#
|
148
|
-
# @since v1.2.0
|
149
|
-
#
|
150
|
-
# @example
|
151
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
152
|
-
# def perform
|
153
|
-
# puts 'MyInteractor1'
|
154
|
-
# end
|
155
|
-
# end
|
156
|
-
#
|
157
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
158
|
-
# def perform
|
159
|
-
# puts 'MyInteractor2'
|
160
|
-
# end
|
161
|
-
# end
|
162
|
-
#
|
163
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
164
|
-
# after_all_perform :print_done
|
165
|
-
#
|
166
|
-
# organized MyInteractor1, MyInteractor2
|
167
|
-
#
|
168
|
-
# private
|
169
|
-
#
|
170
|
-
# def print_done
|
171
|
-
# puts 'Done'
|
172
|
-
# end
|
173
|
-
# end
|
174
|
-
#
|
175
|
-
# MyOrganizer.perform
|
176
|
-
# "MyInteractor1"
|
177
|
-
# "MyInteractor2"
|
178
|
-
# "Done"
|
179
|
-
# #=> <MyOrganizer::Context>
|
180
|
-
def after_all_perform(*filters, &block)
|
181
|
-
set_callback(:all_perform, :after, *filters, &block)
|
182
|
-
end
|
183
|
-
|
184
|
-
# Define a callback to call around all {Organizer::Organize::ClassMethods#organized organized}
|
185
|
-
# {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} method calls.
|
186
|
-
#
|
187
|
-
# @since v1.2.0
|
188
|
-
#
|
189
|
-
# @example
|
190
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
191
|
-
# def perform
|
192
|
-
# puts 'MyInteractor1'
|
193
|
-
# sleep(1)
|
194
|
-
# end
|
195
|
-
# end
|
196
|
-
#
|
197
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
198
|
-
# def perform
|
199
|
-
# puts 'MyInteractor2'
|
200
|
-
# sleep(1)
|
201
|
-
# end
|
202
|
-
# end
|
203
|
-
#
|
204
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
205
|
-
# around_all_perform :print_time
|
206
|
-
#
|
207
|
-
# organized MyInteractor1, MyInteractor2
|
208
|
-
#
|
209
|
-
# private
|
210
|
-
#
|
211
|
-
# def print_time
|
212
|
-
# puts Time.now.utc
|
213
|
-
# yield
|
214
|
-
# puts Time.now.utc
|
215
|
-
# end
|
216
|
-
# end
|
217
|
-
#
|
218
|
-
# MyOrganizer.perform
|
219
|
-
# "2019-04-01 00:00:00 UTC"
|
220
|
-
# "MyInteractor1"
|
221
|
-
# "MyInteractor2"
|
222
|
-
# "2019-04-01 00:00:02 UTC"
|
223
|
-
# #=> <MyOrganizer::Context>
|
224
|
-
def around_all_perform(*filters, &block)
|
225
|
-
set_callback(:all_perform, :around, *filters, &block)
|
226
|
-
end
|
227
|
-
|
228
|
-
# Define a callback to call before all {Organizer::Organize::ClassMethods#organized organized}
|
229
|
-
# {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} methods have been called.
|
230
|
-
#
|
231
|
-
# @since v1.2.0
|
232
|
-
#
|
233
|
-
# @example
|
234
|
-
# class MyInteractor1 < ActiveInteractor::Base
|
235
|
-
# def perform
|
236
|
-
# puts 'MyInteractor1'
|
237
|
-
# end
|
238
|
-
# end
|
239
|
-
#
|
240
|
-
# class MyInteractor2 < ActiveInteractor::Base
|
241
|
-
# def perform
|
242
|
-
# puts 'MyInteractor2'
|
243
|
-
# end
|
244
|
-
# end
|
245
|
-
#
|
246
|
-
# class MyOrganizer < ActiveInteractor::Organizer
|
247
|
-
# before_all_perform :print_starting
|
248
|
-
#
|
249
|
-
# organized MyInteractor1, MyInteractor2
|
250
|
-
#
|
251
|
-
# private
|
252
|
-
#
|
253
|
-
# def print_starting
|
254
|
-
# puts 'Starting'
|
255
|
-
# end
|
256
|
-
# end
|
257
|
-
#
|
258
|
-
# MyOrganizer.perform
|
259
|
-
# "Starting"
|
260
|
-
# "MyInteractor1"
|
261
|
-
# "MyInteractor2"
|
262
|
-
# #=> <MyOrganizer::Context>
|
263
|
-
def before_all_perform(*filters, &block)
|
264
|
-
set_callback(:all_perform, :before, *filters, &block)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def self.included(base)
|
269
|
-
base.class_eval do
|
270
|
-
define_callbacks :each_perform, :all_perform
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
@@ -1,127 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Organizer
|
5
|
-
# An interface object to facilitate conditionally calling {Interactor::Perform::ClassMethods#perform .perform} on
|
6
|
-
# an {ActiveInteractor::Base interactor}
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
10
|
-
# @since 1.0.0
|
11
|
-
#
|
12
|
-
# @!attribute [r] filters
|
13
|
-
# Conditional options for the {ActiveInteractor::Base interactor} class
|
14
|
-
#
|
15
|
-
# @return [Hash{Symbol=>Proc, Symbol}] conditional options for the {ActiveInteractor::Base interactor} class
|
16
|
-
#
|
17
|
-
# @!attribute [r] callbacks
|
18
|
-
# Callbacks for the interactor_class
|
19
|
-
#
|
20
|
-
# @since 1.1.0
|
21
|
-
#
|
22
|
-
# @return [Hash{Symbol=>*}] the interactor callbacks
|
23
|
-
#
|
24
|
-
# @!attribute [r] interactor_class
|
25
|
-
# An {ActiveInteractor::Base interactor} class
|
26
|
-
#
|
27
|
-
# @return [Const] an {ActiveInteractor::Base interactor} class
|
28
|
-
#
|
29
|
-
# @!attribute [r] perform_options
|
30
|
-
# {Interactor::Perform::Options} for the {ActiveInteractor::Base interactor} {Interactor::Perform#perform #perform}
|
31
|
-
#
|
32
|
-
# @see Interactor::Perform::Options
|
33
|
-
#
|
34
|
-
# @return [Hash{Symbol=>*}] {Interactor::Perform::Options} for the {ActiveInteractor::Base interactor}
|
35
|
-
# {Interactor::Perform#perform #perform}
|
36
|
-
#
|
37
|
-
# @!attribute [r] deferred_after_perform_callbacks
|
38
|
-
# Deffered callbacks for the interactor_class
|
39
|
-
# @since 1.2.0
|
40
|
-
#
|
41
|
-
# @return [Hash{Symbol=>*}] the interactor callbacks
|
42
|
-
class InteractorInterface
|
43
|
-
attr_reader :filters, :callbacks, :interactor_class, :perform_options, :deferred_after_perform_callbacks
|
44
|
-
|
45
|
-
# Keywords for conditional filters
|
46
|
-
# @return [Array<Symbol>]
|
47
|
-
CONDITIONAL_FILTERS = %i[if unless].freeze
|
48
|
-
CALLBACKS = %i[before after].freeze
|
49
|
-
|
50
|
-
# Initialize a new instance of {InteractorInterface}
|
51
|
-
#
|
52
|
-
# @param interactor_class [Const] an {ActiveInteractor::Base interactor} class
|
53
|
-
# @param options [Hash] options to use for the {ActiveInteractor::Base interactor's}
|
54
|
-
# {Interactor::Perform::ClassMethods#perform .perform}. See {Interactor::Perform::Options}.
|
55
|
-
# @return [InteractorInterface] a new instance of {InteractorInterface}
|
56
|
-
def initialize(interactor_class, options = {})
|
57
|
-
@interactor_class = interactor_class.to_s.camelize.safe_constantize
|
58
|
-
@filters = options.select { |key, _value| CONDITIONAL_FILTERS.include?(key) }
|
59
|
-
@callbacks = options.select { |key, _value| CALLBACKS.include?(key) }
|
60
|
-
@perform_options = options.reject { |key, _value| CONDITIONAL_FILTERS.include?(key) || CALLBACKS.include?(key) }
|
61
|
-
init_deferred_after_perform_callbacks
|
62
|
-
end
|
63
|
-
|
64
|
-
# Call the {#interactor_class} {Interactor::Perform::ClassMethods#perform .perform} or
|
65
|
-
# {Interactor::Perform::ClassMethods#perform! .perform!} method if all conditions in {#filters} are properly met.
|
66
|
-
#
|
67
|
-
# @param target [Class] the calling {Base organizer} instance
|
68
|
-
# @param context [Class] an instance of {Context::Base context}
|
69
|
-
# @param fail_on_error [Boolean] if `true` {Interactor::Perform::ClassMethods#perform! .perform!} will be called
|
70
|
-
# on the {#interactor_class} other wise {Interactor::Perform::ClassMethods#perform .perform} will be called.
|
71
|
-
# @param perform_options [Hash] additional {Interactor::Perform::Options} to merge with {#perform_options}
|
72
|
-
# @raise [Error::ContextFailure] if `fail_on_error` is `true` and the {#interactor_class}
|
73
|
-
# {Context::Status#fail! fails} its {Context::Base context}.
|
74
|
-
# @return [Class] an instance of {Context::Base context}
|
75
|
-
def perform(target, context, fail_on_error = false, perform_options = {})
|
76
|
-
return if check_conditionals(target, :if) == false
|
77
|
-
return if check_conditionals(target, :unless) == true
|
78
|
-
|
79
|
-
skip_deferred_after_perform_callbacks
|
80
|
-
|
81
|
-
method = fail_on_error ? :perform! : :perform
|
82
|
-
options = self.perform_options.merge(perform_options)
|
83
|
-
interactor_class.send(method, context, options)
|
84
|
-
end
|
85
|
-
|
86
|
-
def execute_inplace_callback(target, callback)
|
87
|
-
resolve_option(target, callbacks[callback])
|
88
|
-
end
|
89
|
-
|
90
|
-
def execute_deferred_after_perform_callbacks(context)
|
91
|
-
return unless deferred_after_perform_callbacks.present?
|
92
|
-
|
93
|
-
interactor = interactor_class.new(context)
|
94
|
-
env = ActiveSupport::Callbacks::Filters::Environment.new(interactor, false, nil)
|
95
|
-
deferred_after_perform_callbacks.compile.invoke_after(env)
|
96
|
-
interactor.send(:context)
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
def init_deferred_after_perform_callbacks
|
102
|
-
after_callbacks_deferred = interactor_class.present? &&
|
103
|
-
interactor_class.after_callbacks_deferred_when_organized
|
104
|
-
@deferred_after_perform_callbacks = after_callbacks_deferred ? interactor_class._perform_callbacks : nil
|
105
|
-
end
|
106
|
-
|
107
|
-
def skip_deferred_after_perform_callbacks
|
108
|
-
return unless deferred_after_perform_callbacks.present?
|
109
|
-
|
110
|
-
deferred_after_perform_callbacks.each do |callback|
|
111
|
-
interactor_class.skip_callback(:perform, :after, callback.filter, raise: false)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def check_conditionals(target, filter)
|
116
|
-
resolve_option(target, filters[filter])
|
117
|
-
end
|
118
|
-
|
119
|
-
def resolve_option(target, opt)
|
120
|
-
return unless opt
|
121
|
-
|
122
|
-
return target.send(opt) if opt.is_a?(Symbol)
|
123
|
-
return target.instance_exec(&opt) if opt.is_a?(Proc)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Organizer
|
5
|
-
# A collection of {InteractorInterface}
|
6
|
-
#
|
7
|
-
# @api private
|
8
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
9
|
-
# @since 1.0.0
|
10
|
-
#
|
11
|
-
# @!attribute [r] collection
|
12
|
-
# An array of {InteractorInterface}
|
13
|
-
#
|
14
|
-
# @return [Array<InteractorInterface>] the {InteractorInterface} collection
|
15
|
-
class InteractorInterfaceCollection
|
16
|
-
attr_reader :collection
|
17
|
-
|
18
|
-
# @!method map(&block)
|
19
|
-
# Invokes the given block once for each element of {#collection}.
|
20
|
-
# @return [Array] a new array containing the values returned by the block.
|
21
|
-
delegate :map, to: :collection
|
22
|
-
|
23
|
-
# Initialize a new instance of {InteractorInterfaceCollection}
|
24
|
-
# @return [InteractorInterfaceCollection] a new instance of {InteractorInterfaceCollection}
|
25
|
-
def initialize
|
26
|
-
@collection = []
|
27
|
-
end
|
28
|
-
|
29
|
-
# Add an {InteractorInterface} to the {#collection}
|
30
|
-
#
|
31
|
-
# @param interactor_class [Const, Symbol, String] an {ActiveInteractor::Base interactor} class
|
32
|
-
# @param filters [Hash{Symbol=> Proc, Symbol}] conditional options for the {ActiveInteractor::Base interactor}
|
33
|
-
# class
|
34
|
-
# @option filters [Proc, Symbol] :if only call the {ActiveInteractor::Base interactor}
|
35
|
-
# {Interactor::Perform::ClassMethods#perform .perform} if `Proc` or `method` returns `true`
|
36
|
-
# @option filters [Proc, Symbol] :unless only call the {ActiveInteractor::Base interactor}
|
37
|
-
# {Interactor::Perform::ClassMethods#perform .perform} if `Proc` or `method` returns `false` or `nil`
|
38
|
-
# @return [self] the {InteractorInterfaceCollection} instance
|
39
|
-
def add(interactor_class, filters = {})
|
40
|
-
interface = ActiveInteractor::Organizer::InteractorInterface.new(interactor_class, filters)
|
41
|
-
collection << interface if interface.interactor_class
|
42
|
-
self
|
43
|
-
end
|
44
|
-
|
45
|
-
# Add multiple {InteractorInterface} to the {#collection}
|
46
|
-
#
|
47
|
-
# @param interactor_classes [Array<Const, Symbol, String>] the {ActiveInteractor::Base interactor} classes
|
48
|
-
# @return [self] the {InteractorInterfaceCollection} instance
|
49
|
-
def concat(interactor_classes)
|
50
|
-
interactor_classes.flatten.each { |interactor_class| add(interactor_class) }
|
51
|
-
self
|
52
|
-
end
|
53
|
-
|
54
|
-
# Calls the given block once for each element in {#collection}, passing that element as a parameter.
|
55
|
-
# @return [self] the {InteractorInterfaceCollection} instance
|
56
|
-
def each(&block)
|
57
|
-
collection.each(&block) if block
|
58
|
-
self
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|