activeinteractor 1.2.2 → 2.0.0.alpha.1.0.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 +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,106 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Context
|
5
|
-
# Context status methods. Because {Status} is a module classes should include {Status} rather than inherit from it.
|
6
|
-
#
|
7
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
8
|
-
# @since 1.0.0
|
9
|
-
module Status
|
10
|
-
# Add an instance of {ActiveInteractor::Base interactor} to the list of {ActiveInteractor::Base interactors}
|
11
|
-
# called on the {Base context}. This list is used when {#rollback!} is called on a {Base context} instance.
|
12
|
-
#
|
13
|
-
# @since 0.1.0
|
14
|
-
#
|
15
|
-
# @param interactor [Class] an {ActiveInteractor::Base interactor} instance
|
16
|
-
# @return [Array<Class>] the list of called {ActiveInteractor::Base interactors}
|
17
|
-
def called!(interactor)
|
18
|
-
_called << interactor
|
19
|
-
end
|
20
|
-
|
21
|
-
# Fail the {Base context} instance. Failing an instance raises an error that may be rescued by the calling
|
22
|
-
# {ActiveInteractor::Base interactor}. The instance is also flagged as having failed.
|
23
|
-
#
|
24
|
-
# @since 0.1.0
|
25
|
-
#
|
26
|
-
# @example Fail an interactor context
|
27
|
-
# class MyInteractor < ActiveInteractor::Base
|
28
|
-
# def perform
|
29
|
-
# context.fail!
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# MyInteractor.perform!
|
34
|
-
# ActiveInteractor::Error::ContextFailure "<#MyInteractor::Context>"
|
35
|
-
#
|
36
|
-
# @param errors [ActiveModel::Errors, String] error messages for the failure
|
37
|
-
# @see https://api.rubyonrails.org/classes/ActiveModel/Errors.html ActiveModel::Errors
|
38
|
-
# @raise [Error::ContextFailure]
|
39
|
-
def fail!(errors = nil)
|
40
|
-
handle_errors(errors) if errors
|
41
|
-
@_failed = true
|
42
|
-
resolve
|
43
|
-
raise ActiveInteractor::Error::ContextFailure, self
|
44
|
-
end
|
45
|
-
|
46
|
-
# Whether the {Base context} instance has {#fail! failed}. By default, a new instance is successful and only
|
47
|
-
# changes when explicitly {#fail! failed}.
|
48
|
-
#
|
49
|
-
# @since 0.1.0
|
50
|
-
# @note The {#failure?} method is the inverse of the {#success?} method
|
51
|
-
#
|
52
|
-
# @example Check if a context has failed
|
53
|
-
# result = MyInteractor.perform
|
54
|
-
# result.failure?
|
55
|
-
# #=> false
|
56
|
-
#
|
57
|
-
# @return [Boolean] `false` by default or `true` if {#fail! failed}.
|
58
|
-
def failure?
|
59
|
-
@_failed || false
|
60
|
-
end
|
61
|
-
alias fail? failure?
|
62
|
-
|
63
|
-
# Resolve an instance of {Base context}. Called when an interactor
|
64
|
-
# is finished with it's context.
|
65
|
-
#
|
66
|
-
# @since 1.0.3
|
67
|
-
# @return [self] the instance of {Base context}
|
68
|
-
def resolve
|
69
|
-
resolve_errors
|
70
|
-
self
|
71
|
-
end
|
72
|
-
|
73
|
-
# {#rollback! Rollback} an instance of {Base context}. Any {ActiveInteractor::Base interactors} the instance has
|
74
|
-
# been passed via the {#called!} method are asked to roll themselves back by invoking their
|
75
|
-
# {Interactor::Perform#rollback #rollback} methods. The instance is also flagged as rolled back.
|
76
|
-
#
|
77
|
-
# @since 0.1.0
|
78
|
-
#
|
79
|
-
# @return [Boolean] `true` if {#rollback! rolled back} successfully or `false` if already
|
80
|
-
# {#rollback! rolled back}
|
81
|
-
def rollback!
|
82
|
-
return false if @_rolled_back
|
83
|
-
|
84
|
-
_called.reverse_each(&:rollback)
|
85
|
-
@_rolled_back = true
|
86
|
-
end
|
87
|
-
|
88
|
-
# Whether the {Base context} instance is successful. By default, a new instance is successful and only changes
|
89
|
-
# when explicitly {#fail! failed}.
|
90
|
-
#
|
91
|
-
# @since 0.1.0
|
92
|
-
# @note The {#success?} method is the inverse of the {#failure?} method
|
93
|
-
#
|
94
|
-
# @example Check if a context has failed
|
95
|
-
# result = MyInteractor.perform
|
96
|
-
# result.success?
|
97
|
-
# #=> true
|
98
|
-
#
|
99
|
-
# @return [Boolean] `true` by default or `false` if {#fail! failed}
|
100
|
-
def success?
|
101
|
-
!failure?
|
102
|
-
end
|
103
|
-
alias successful? success?
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
# ActiveInteractor errors
|
5
|
-
#
|
6
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
7
|
-
# @since 0.1.5
|
8
|
-
module Error
|
9
|
-
# Raised when an {Base interactor} {Context::Base context} {Context::Status#fail! fails}.
|
10
|
-
#
|
11
|
-
# @!attribute [r] context
|
12
|
-
# An instance of {Context::Base context} used for debugging.
|
13
|
-
#
|
14
|
-
# @return [Context::Base] an instance of {Context::Base}
|
15
|
-
class ContextFailure < StandardError
|
16
|
-
attr_reader :context
|
17
|
-
|
18
|
-
# Initialize a new instance of {ContextFailure}
|
19
|
-
#
|
20
|
-
# @param context [Class, nil] an instance of {Context::Base context}
|
21
|
-
# @return [ContextFailure] a new instance of {ContextFailure}
|
22
|
-
def initialize(context = nil)
|
23
|
-
@context = context
|
24
|
-
context_class_name = context&.class&.name || 'Context'
|
25
|
-
super("#{context_class_name} failed!")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Raised when an invalid {Context::Base context} class is assigned to an {Base interactor}.
|
30
|
-
#
|
31
|
-
# @since 1.0.0
|
32
|
-
#
|
33
|
-
# @!attribute [r] class_name
|
34
|
-
# The class name of the {Context::Base context} used for debugging.
|
35
|
-
#
|
36
|
-
# @return [String|nil] the class name of the {Context::Base context}
|
37
|
-
class InvalidContextClass < StandardError
|
38
|
-
attr_reader :class_name
|
39
|
-
|
40
|
-
def initialize(class_name = nil)
|
41
|
-
@class_name = class_name
|
42
|
-
super("invalid context class #{class_name}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,293 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveInteractor
|
4
|
-
module Interactor
|
5
|
-
# Interactor 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 0.1.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
|
-
# Interactor 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 0.1.0
|
18
|
-
module ClassMethods
|
19
|
-
# Define a callback to call after validation has been run on an {Base interactor} instance's
|
20
|
-
# {ActiveInteractor::Context::Base context} instance.
|
21
|
-
#
|
22
|
-
# @example
|
23
|
-
# class MyInteractor < ActiveInteractor::Base
|
24
|
-
# after_context_validation :ensure_name_is_aaron
|
25
|
-
# context_validates :name, presence: true
|
26
|
-
#
|
27
|
-
# private
|
28
|
-
#
|
29
|
-
# def ensure_name_is_aaron
|
30
|
-
# context.name = 'Aaron'
|
31
|
-
# end
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# result = MyInteractor.perform(name: 'Bob')
|
35
|
-
# result.name
|
36
|
-
# #=> 'Aaron'
|
37
|
-
#
|
38
|
-
# result = MyInteractor.perform({ name: 'Bob' }, { validate: false })
|
39
|
-
# result.name
|
40
|
-
# #=> 'Bob'
|
41
|
-
def after_context_validation(*args, &block)
|
42
|
-
options = normalize_options(args.extract_options!.dup.merge(prepend: true))
|
43
|
-
set_callback(:validation, :after, *args, options, &block)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Define a callback to call after {Interactor::Perform#perform #perform} has been called on an
|
47
|
-
# {Base interactor} instance.
|
48
|
-
#
|
49
|
-
# @example
|
50
|
-
# class MyInteractor < ActiveInteractor::Base
|
51
|
-
# after_perform :print_done
|
52
|
-
#
|
53
|
-
# def perform
|
54
|
-
# puts 'Performing'
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# private
|
58
|
-
#
|
59
|
-
# def print_done
|
60
|
-
# puts 'Done'
|
61
|
-
# end
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# MyInteractor.perform
|
65
|
-
# "Performing"
|
66
|
-
# "Done"
|
67
|
-
# #=> <#MyInteractor::Context>
|
68
|
-
def after_perform(*filters, &block)
|
69
|
-
set_callback(:perform, :after, *filters, &block)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Define a callback to call after {Interactor::Perform#rollback #rollback} has been called on an
|
73
|
-
# {Base interactor} instance.
|
74
|
-
#
|
75
|
-
# @example
|
76
|
-
# class MyInteractor < ActiveInteractor::Base
|
77
|
-
# after_rollback :print_done
|
78
|
-
#
|
79
|
-
# def perform
|
80
|
-
# context.fail!
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# def rollback
|
84
|
-
# puts 'Rolling Back'
|
85
|
-
# end
|
86
|
-
#
|
87
|
-
# private
|
88
|
-
#
|
89
|
-
# def print_done
|
90
|
-
# puts 'Done'
|
91
|
-
# end
|
92
|
-
# end
|
93
|
-
#
|
94
|
-
# MyInteractor.perform
|
95
|
-
# "Rolling Back"
|
96
|
-
# "Done"
|
97
|
-
# #=> <MyInteractor::Context>
|
98
|
-
def after_rollback(*filters, &block)
|
99
|
-
set_callback(:rollback, :after, *filters, &block)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Define a callback to call around {Interactor::Perform#perform #perform} invokation on an {Base interactor}
|
103
|
-
# instance.
|
104
|
-
#
|
105
|
-
# @example
|
106
|
-
# class MyInteractor < ActiveInteractor::Base
|
107
|
-
# around_perform :track_time
|
108
|
-
#
|
109
|
-
# def perform
|
110
|
-
# sleep(1)
|
111
|
-
# end
|
112
|
-
#
|
113
|
-
# private
|
114
|
-
#
|
115
|
-
# def track_time
|
116
|
-
# context.start_time = Time.now.utc
|
117
|
-
# yield
|
118
|
-
# context.end_time = Time.now.utc
|
119
|
-
# end
|
120
|
-
# end
|
121
|
-
#
|
122
|
-
# result = MyInteractor.perform
|
123
|
-
# result.start_time
|
124
|
-
# #=> 2019-01-01 00:00:00 UTC
|
125
|
-
#
|
126
|
-
# result.end_time
|
127
|
-
# #=> 2019-01-01 00:00:01 UTC
|
128
|
-
def around_perform(*filters, &block)
|
129
|
-
set_callback(:perform, :around, *filters, &block)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Define a callback to call around {Interactor::Perform#rollback #rollback} invokation on an {Base interactor}
|
133
|
-
# instance.
|
134
|
-
#
|
135
|
-
# @example
|
136
|
-
# class MyInteractor < ActiveInteractor::Base
|
137
|
-
# around_rollback :track_time
|
138
|
-
#
|
139
|
-
# def perform
|
140
|
-
# context.fail!
|
141
|
-
# end
|
142
|
-
#
|
143
|
-
# def rollback
|
144
|
-
# sleep(1)
|
145
|
-
# end
|
146
|
-
#
|
147
|
-
# private
|
148
|
-
#
|
149
|
-
# def track_time
|
150
|
-
# context.start_time = Time.now.utc
|
151
|
-
# yield
|
152
|
-
# context.end_time = Time.now.utc
|
153
|
-
# end
|
154
|
-
# end
|
155
|
-
#
|
156
|
-
# result = MyInteractor.perform
|
157
|
-
# result.start_time
|
158
|
-
# #=> 2019-01-01 00:00:00 UTC
|
159
|
-
#
|
160
|
-
# result.end_time
|
161
|
-
# #=> 2019-01-01 00:00:01 UTC
|
162
|
-
def around_rollback(*filters, &block)
|
163
|
-
set_callback(:rollback, :around, *filters, &block)
|
164
|
-
end
|
165
|
-
|
166
|
-
# Define a callback to call before validation has been run on an {Base interactor} instance's
|
167
|
-
# {ActiveInteractor::Context::Base context} instance.
|
168
|
-
#
|
169
|
-
# @example
|
170
|
-
# class MyInteractor < ActiveInteractor::Base
|
171
|
-
# before_context_validation :ensure_name_is_aaron
|
172
|
-
# context_validates :name, inclusion: { in: %w[Aaron] }
|
173
|
-
#
|
174
|
-
# private
|
175
|
-
#
|
176
|
-
# def ensure_name_is_aaron
|
177
|
-
# context.name = 'Aaron'
|
178
|
-
# end
|
179
|
-
# end
|
180
|
-
#
|
181
|
-
# result = MyInteractor.perform(name: 'Bob')
|
182
|
-
# result.successful?
|
183
|
-
# #=> true
|
184
|
-
#
|
185
|
-
# result.name
|
186
|
-
# #=> 'Aaron'
|
187
|
-
#
|
188
|
-
# result = MyInteractor.perform({ name: 'Bob' }, { validate: false })
|
189
|
-
# result.name
|
190
|
-
# #=> 'Bob'
|
191
|
-
def before_context_validation(*args, &block)
|
192
|
-
options = normalize_options(args.extract_options!.dup)
|
193
|
-
set_callback(:validation, :before, *args, options, &block)
|
194
|
-
end
|
195
|
-
|
196
|
-
# Define a callback to call before {Interactor::Perform#perform #perform} has been called on an
|
197
|
-
# {Base interactor} instance
|
198
|
-
#
|
199
|
-
# @example
|
200
|
-
# class MyInteractor < ActiveInteractor::Base
|
201
|
-
# before_perform :print_starting
|
202
|
-
#
|
203
|
-
# def perform
|
204
|
-
# puts 'Performing'
|
205
|
-
# end
|
206
|
-
#
|
207
|
-
# private
|
208
|
-
#
|
209
|
-
# def print_starting
|
210
|
-
# puts 'Starting'
|
211
|
-
# end
|
212
|
-
# end
|
213
|
-
#
|
214
|
-
# MyInteractor.perform
|
215
|
-
# "Starting"
|
216
|
-
# "Performing"
|
217
|
-
# #=> <#MyInteractor::Context>
|
218
|
-
def before_perform(*filters, &block)
|
219
|
-
set_callback(:perform, :before, *filters, &block)
|
220
|
-
end
|
221
|
-
|
222
|
-
# Define a callback to call before {Interactor::Perform#rollback #rollback} has been called on an
|
223
|
-
# {Base interactor} instance.
|
224
|
-
#
|
225
|
-
# @example
|
226
|
-
# class MyInteractor < ActiveInteractor::Base
|
227
|
-
# before_rollback :print_starting
|
228
|
-
#
|
229
|
-
# def perform
|
230
|
-
# context.fail!
|
231
|
-
# end
|
232
|
-
#
|
233
|
-
# def rollback
|
234
|
-
# puts 'Rolling Back'
|
235
|
-
# end
|
236
|
-
#
|
237
|
-
# private
|
238
|
-
#
|
239
|
-
# def print_starting
|
240
|
-
# puts 'Starting'
|
241
|
-
# end
|
242
|
-
# end
|
243
|
-
#
|
244
|
-
# MyInteractor.perform
|
245
|
-
# "Starting"
|
246
|
-
# "Rolling Back"
|
247
|
-
# #=> <#MyInteractor::Context>
|
248
|
-
def before_rollback(*filters, &block)
|
249
|
-
set_callback(:rollback, :before, *filters, &block)
|
250
|
-
end
|
251
|
-
|
252
|
-
# Set {.after_callbacks_deferred_when_organized} to `true`
|
253
|
-
#
|
254
|
-
# @since v1.2.0
|
255
|
-
#
|
256
|
-
# @example a basic {Base organizer} set to defer 'after' callbacks when organized
|
257
|
-
# class MyOrganizer < ActiveInteractor::Organizer::Base
|
258
|
-
# defer_after_callbacks_when_organized
|
259
|
-
# end
|
260
|
-
def defer_after_callbacks_when_organized
|
261
|
-
self.after_callbacks_deferred_when_organized = true
|
262
|
-
end
|
263
|
-
|
264
|
-
def self.extended(base)
|
265
|
-
base.class_eval do
|
266
|
-
class_attribute :after_callbacks_deferred_when_organized, instance_writer: false, default: false
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
private
|
271
|
-
|
272
|
-
def normalize_options(options)
|
273
|
-
if options.key?(:on)
|
274
|
-
options[:on] = Array(options[:on])
|
275
|
-
options[:if] = Array(options[:if])
|
276
|
-
options[:if].unshift { |o| !(options[:on] & Array(o.validation_context)).empty? }
|
277
|
-
end
|
278
|
-
|
279
|
-
options
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def self.included(base)
|
284
|
-
base.class_eval do
|
285
|
-
define_callbacks :validation,
|
286
|
-
skip_after_callbacks_if_terminated: true,
|
287
|
-
scope: %i[kind name]
|
288
|
-
define_callbacks :perform, :rollback
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
end
|