activeinteractor 1.0.0.beta.7 → 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/.yardopts +12 -0
- data/CHANGELOG.md +50 -158
- data/README.md +13 -856
- data/lib/active_interactor.rb +61 -4
- data/lib/active_interactor/base.rb +26 -20
- data/lib/active_interactor/config.rb +36 -18
- data/lib/active_interactor/configurable.rb +17 -9
- data/lib/active_interactor/context/attributes.rb +73 -26
- data/lib/active_interactor/context/base.rb +236 -65
- data/lib/active_interactor/context/loader.rb +20 -15
- data/lib/active_interactor/context/status.rb +38 -56
- data/lib/active_interactor/error.rb +15 -7
- data/lib/active_interactor/interactor/callbacks.rb +174 -160
- data/lib/active_interactor/interactor/context.rb +279 -87
- data/lib/active_interactor/interactor/perform.rb +256 -0
- data/lib/active_interactor/interactor/worker.rb +19 -14
- data/lib/active_interactor/models.rb +65 -0
- data/lib/active_interactor/organizer/base.rb +18 -0
- data/lib/active_interactor/organizer/callbacks.rb +153 -0
- data/lib/active_interactor/organizer/interactor_interface.rb +38 -26
- data/lib/active_interactor/organizer/interactor_interface_collection.rb +35 -32
- data/lib/active_interactor/organizer/organize.rb +67 -0
- data/lib/active_interactor/organizer/perform.rb +93 -0
- data/lib/active_interactor/rails.rb +0 -10
- data/lib/active_interactor/rails/orm/active_record.rb +1 -1
- data/lib/active_interactor/rails/railtie.rb +8 -11
- data/lib/active_interactor/version.rb +2 -1
- data/lib/rails/generators/active_interactor.rb +1 -38
- data/lib/rails/generators/active_interactor/application_context_generator.rb +21 -0
- data/lib/rails/generators/active_interactor/application_interactor_generator.rb +5 -15
- data/lib/rails/generators/active_interactor/application_organizer_generator.rb +21 -0
- data/lib/rails/generators/active_interactor/base.rb +29 -0
- data/lib/rails/generators/active_interactor/generator.rb +21 -0
- data/lib/rails/generators/active_interactor/install_generator.rb +2 -9
- data/lib/rails/generators/interactor/context/rspec_generator.rb +3 -10
- data/lib/rails/generators/interactor/context/test_unit_generator.rb +4 -11
- data/lib/rails/generators/interactor/context_generator.rb +7 -10
- data/lib/rails/generators/interactor/generates_context.rb +28 -0
- data/lib/rails/generators/interactor/interactor_generator.rb +8 -10
- data/lib/rails/generators/interactor/organizer_generator.rb +8 -12
- data/lib/rails/generators/interactor/rspec_generator.rb +2 -9
- data/lib/rails/generators/interactor/test_unit_generator.rb +3 -10
- data/lib/rails/generators/{active_interactor/templates/initializer.erb → templates/active_interactor.erb} +3 -11
- data/lib/rails/generators/{active_interactor/templates → templates}/application_context.rb +0 -0
- data/lib/rails/generators/{active_interactor/templates → templates}/application_interactor.rb +0 -0
- data/lib/rails/generators/templates/application_organizer.rb +4 -0
- data/lib/rails/generators/{interactor/templates → templates}/context.erb +0 -0
- data/lib/rails/generators/{interactor/context/templates/rspec.erb → templates/context_spec.erb} +0 -0
- data/lib/rails/generators/{interactor/context/templates/test_unit.erb → templates/context_test_unit.erb} +0 -0
- data/lib/rails/generators/{interactor/templates → templates}/interactor.erb +0 -0
- data/lib/rails/generators/{interactor/templates/rspec.erb → templates/interactor_spec.erb} +0 -0
- data/lib/rails/generators/{interactor/templates/test_unit.erb → templates/interactor_text_unit.erb} +0 -0
- data/lib/rails/generators/{interactor/templates → templates}/organizer.erb +0 -0
- data/spec/active_interactor/base_spec.rb +3 -3
- data/spec/active_interactor/interactor/{perform_options_spec.rb → perform/options_spec.rb} +1 -1
- data/spec/active_interactor/interactor/worker_spec.rb +14 -15
- data/spec/active_interactor/{organizer_spec.rb → organizer/base_spec.rb} +27 -17
- data/spec/integration/a_basic_interactor_spec.rb +106 -0
- data/spec/integration/a_basic_organizer_spec.rb +97 -0
- data/spec/integration/a_failing_interactor_spec.rb +42 -0
- data/spec/integration/active_record_integration_spec.rb +9 -9
- data/spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb +69 -0
- data/spec/integration/an_interactor_with_after_perform_callbacks_spec.rb +30 -0
- data/spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb +33 -0
- data/spec/integration/an_interactor_with_an_existing_context_class_spec.rb +49 -0
- data/spec/integration/an_interactor_with_around_perform_callbacks_spec.rb +35 -0
- data/spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb +39 -0
- data/spec/integration/an_interactor_with_before_perform_callbacks_spec.rb +30 -0
- data/spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb +33 -0
- data/spec/integration/an_interactor_with_validations_on_called_spec.rb +40 -0
- data/spec/integration/an_interactor_with_validations_on_calling_spec.rb +36 -0
- data/spec/integration/an_interactor_with_validations_spec.rb +93 -0
- data/spec/integration/an_organizer_performing_in_parallel_spec.rb +48 -0
- data/spec/integration/an_organizer_with_after_each_callbacks_spec.rb +34 -0
- data/spec/integration/an_organizer_with_around_each_callbacks_spec.rb +39 -0
- data/spec/integration/an_organizer_with_before_each_callbacks_spec.rb +34 -0
- data/spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb +314 -0
- data/spec/spec_helper.rb +8 -12
- data/spec/support/coverage.rb +4 -0
- data/spec/support/coverage/reporters.rb +11 -0
- data/spec/support/coverage/reporters/codacy.rb +39 -0
- data/spec/support/coverage/reporters/simple_cov.rb +54 -0
- data/spec/support/coverage/runner.rb +66 -0
- data/spec/support/helpers/factories.rb +1 -1
- data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +8 -8
- data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +5 -5
- data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +2 -2
- data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +3 -3
- metadata +83 -40
- data/lib/active_interactor/interactor.rb +0 -84
- data/lib/active_interactor/interactor/perform_options.rb +0 -29
- data/lib/active_interactor/organizer.rb +0 -269
- data/lib/active_interactor/rails/config.rb +0 -45
- data/lib/active_interactor/rails/models.rb +0 -58
- data/lib/rails/generators/active_interactor/templates/application_organizer.rb +0 -4
- data/spec/active_interactor/rails/config_spec.rb +0 -29
- data/spec/active_interactor/rails_spec.rb +0 -24
- data/spec/integration/basic_callback_integration_spec.rb +0 -355
- data/spec/integration/basic_context_integration_spec.rb +0 -73
- data/spec/integration/basic_integration_spec.rb +0 -570
- data/spec/integration/basic_validations_integration_spec.rb +0 -204
@@ -2,21 +2,24 @@
|
|
2
2
|
|
3
3
|
module ActiveInteractor
|
4
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
|
+
#
|
5
8
|
# @api private
|
6
|
-
# Thread safe execution of interactor {Interactor#perform #perform} and
|
7
|
-
# {Interactor#rollback #rollback} methods.
|
8
9
|
# @author Aaron Allen <hello@aaronmallen.me>
|
9
|
-
# @since 0.0
|
10
|
+
# @since 0.1.0
|
10
11
|
class Worker
|
11
|
-
#
|
12
|
+
# Initialize a new instance of {Worker}
|
13
|
+
#
|
14
|
+
# @param interactor [Base] an {Base interactor} instance
|
12
15
|
# @return [Worker] a new instance of {Worker}
|
13
16
|
def initialize(interactor)
|
14
|
-
|
15
|
-
@interactor = interactor.dup.with_options(options)
|
17
|
+
@interactor = interactor.deep_dup
|
16
18
|
end
|
17
19
|
|
18
|
-
#
|
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
|
20
23
|
def execute_perform
|
21
24
|
execute_perform!
|
22
25
|
rescue Error::ContextFailure => e
|
@@ -24,18 +27,20 @@ module ActiveInteractor
|
|
24
27
|
context
|
25
28
|
end
|
26
29
|
|
27
|
-
#
|
28
|
-
#
|
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
|
30
35
|
def execute_perform!
|
31
36
|
execute_context!
|
32
37
|
rescue StandardError => e
|
33
38
|
handle_error(e)
|
34
39
|
end
|
35
40
|
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
41
|
+
# Run the {Base interactor} instance's {Interactor::Perform#rollback #rollback} with callbacks
|
42
|
+
#
|
43
|
+
# @return [Boolean] `true` if context was successfully rolled back
|
39
44
|
def execute_rollback
|
40
45
|
return if interactor.options.skip_rollback
|
41
46
|
|
@@ -0,0 +1,65 @@
|
|
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(attributes = nil)
|
17
|
+
copy_flags!(attributes) if attributes
|
18
|
+
copy_called!(attributes) if attributes
|
19
|
+
attributes_as_hash = context_attributes_as_hash(attributes)
|
20
|
+
super(attributes_as_hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Merge an instance of model class into the calling model class instance
|
24
|
+
#
|
25
|
+
# @see Context::Attributes#merge!
|
26
|
+
#
|
27
|
+
# @param context [Class] a {Base context} instance to be merged
|
28
|
+
# @return [self] the {Base context} instance
|
29
|
+
def merge!(context)
|
30
|
+
copy_flags!(context)
|
31
|
+
context.each_pair do |key, value|
|
32
|
+
self[key] = value unless value.nil?
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def context_attributes_as_hash(attributes)
|
40
|
+
return attributes.to_h if attributes&.respond_to?(:to_h)
|
41
|
+
return attributes.attributes.to_h if attributes.respond_to?(:attributes)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Include methods needed for a {Context::Base context} class to function properly.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# class User
|
49
|
+
# extend ActiveInteractor::Models
|
50
|
+
# acts_as_context
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# class MyInteractor < ActiveInteractor::Base
|
54
|
+
# contextualize_with :user
|
55
|
+
# end
|
56
|
+
def acts_as_context
|
57
|
+
class_eval do
|
58
|
+
include ActiveModel::Validations
|
59
|
+
include ActiveInteractor::Models::InstanceMethods
|
60
|
+
include ActiveInteractor::Context::Status
|
61
|
+
delegate :each_pair, to: :attributes
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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
|
@@ -0,0 +1,153 @@
|
|
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
|
+
end
|
145
|
+
|
146
|
+
def self.included(base)
|
147
|
+
base.class_eval do
|
148
|
+
define_callbacks :each_perform
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -1,49 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/core_ext/string/inflections'
|
4
|
-
|
5
3
|
module ActiveInteractor
|
6
|
-
|
4
|
+
module Organizer
|
5
|
+
# An interface object to facilitate conditionally calling {Interactor::Perform::ClassMethods#perform .perform} on
|
6
|
+
# an {ActiveInteractor::Base interactor}
|
7
|
+
#
|
7
8
|
# @api private
|
8
|
-
# An interface for an interactor's to allow conditional invokation of an
|
9
|
-
# interactor's {Interactor#perform #perform} method.
|
10
9
|
# @author Aaron Allen <hello@aaronmallen.me>
|
11
10
|
# @since 1.0.0
|
11
|
+
#
|
12
12
|
# @!attribute [r] filters
|
13
|
-
#
|
14
|
-
#
|
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
|
+
#
|
15
17
|
# @!attribute [r] interactor_class
|
16
|
-
#
|
18
|
+
# An {ActiveInteractor::Base interactor} class
|
19
|
+
#
|
20
|
+
# @return [Const] an {ActiveInteractor::Base interactor} class
|
21
|
+
#
|
17
22
|
# @!attribute [r] perform_options
|
18
|
-
#
|
19
|
-
#
|
23
|
+
# {Interactor::Perform::Options} for the {ActiveInteractor::Base interactor} {Interactor::Perform#perform #perform}
|
24
|
+
#
|
25
|
+
# @see Interactor::Perform::Options
|
26
|
+
#
|
27
|
+
# @return [Hash{Symbol=>*}] {Interactor::Perform::Options} for the {ActiveInteractor::Base interactor}
|
28
|
+
# {Interactor::Perform#perform #perform}
|
20
29
|
class InteractorInterface
|
21
30
|
attr_reader :filters, :interactor_class, :perform_options
|
22
31
|
|
23
|
-
#
|
24
|
-
#
|
32
|
+
# Keywords for conditional filters
|
33
|
+
# @return [Array<Symbol>]
|
25
34
|
CONDITIONAL_FILTERS = %i[if unless].freeze
|
26
35
|
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# @
|
30
|
-
#
|
36
|
+
# Initialize a new instance of {InteractorInterface}
|
37
|
+
#
|
38
|
+
# @param interactor_class [Const] an {ActiveInteractor::Base interactor} class
|
39
|
+
# @param options [Hash] options to use for the {ActiveInteractor::Base interactor's}
|
40
|
+
# {Interactor::Perform::ClassMethods#perform .perform}. See {Interactor::Perform::Options}.
|
41
|
+
# @return [InteractorInterface] a new instance of {InteractorInterface}
|
31
42
|
def initialize(interactor_class, options = {})
|
32
43
|
@interactor_class = interactor_class.to_s.classify.safe_constantize
|
33
44
|
@filters = options.select { |key, _value| CONDITIONAL_FILTERS.include?(key) }
|
34
45
|
@perform_options = options.reject { |key, _value| CONDITIONAL_FILTERS.include?(key) }
|
35
46
|
end
|
36
47
|
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# @param
|
41
|
-
# @param
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# @param perform_options [Hash{
|
45
|
-
# @
|
46
|
-
#
|
48
|
+
# Call the {#interactor_class} {Interactor::Perform::ClassMethods#perform .perform} or
|
49
|
+
# {Interactor::Perform::ClassMethods#perform! .perform!} method if all conditions in {#filters} are properly met.
|
50
|
+
#
|
51
|
+
# @param target [Class] the calling {Base organizer} instance
|
52
|
+
# @param context [Class] an instance of {Context::Base context}
|
53
|
+
# @param fail_on_error [Boolean] if `true` {Interactor::Perform::ClassMethods#perform! .perform!} will be called
|
54
|
+
# on the {#interactor_class} other wise {Interactor::Perform::ClassMethods#perform .perform} will be called.
|
55
|
+
# @param perform_options [Hash] additional {Interactor::Perform::Options} to merge with {#perform_options}
|
56
|
+
# @raise [Error::ContextFailure] if `fail_on_error` is `true` and the {#interactor_class}
|
57
|
+
# {Context::Status#fail! fails} its {Context::Base context}.
|
58
|
+
# @return [Class] an instance of {Context::Base context}
|
47
59
|
def perform(target, context, fail_on_error = false, perform_options = {})
|
48
60
|
return if check_conditionals(target, filters[:if]) == false
|
49
61
|
return if check_conditionals(target, filters[:unless]) == true
|
@@ -1,56 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_interactor/organizer/interactor_interface'
|
4
|
-
|
5
3
|
module ActiveInteractor
|
6
|
-
|
4
|
+
module Organizer
|
5
|
+
# A collection of {InteractorInterface}
|
6
|
+
#
|
7
7
|
# @api private
|
8
|
-
# A collection of ordered interactors for an {Organizer}
|
9
8
|
# @author Aaron Allen <hello@aaronmallen.me>
|
10
9
|
# @since 1.0.0
|
10
|
+
#
|
11
11
|
# @!attribute [r] collection
|
12
|
-
#
|
12
|
+
# An array of {InteractorInterface}
|
13
|
+
#
|
14
|
+
# @return [Array<InteractorInterface>] the {InteractorInterface} collection
|
13
15
|
class InteractorInterfaceCollection
|
14
16
|
attr_reader :collection
|
15
|
-
|
16
|
-
# @!method each(&block)
|
17
|
-
# Calls the given block once for each element of {#collection}, passing that
|
18
|
-
# element as a parameter
|
19
|
-
# @yield [.collection] the {#collection}
|
20
|
-
# @return [Array<InteractorInterface>] the {#collection}
|
21
|
-
|
22
17
|
# @!method map(&block)
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
delegate :each, :map, to: :collection
|
18
|
+
# Invokes the given block once for each element of {#collection}.
|
19
|
+
# @return [Array] a new array containing the values returned by the block.
|
20
|
+
delegate :map, to: :collection
|
27
21
|
|
22
|
+
# Initialize a new instance of {InteractorInterfaceCollection}
|
28
23
|
# @return [InteractorInterfaceCollection] a new instance of {InteractorInterfaceCollection}
|
29
24
|
def initialize
|
30
25
|
@collection = []
|
31
26
|
end
|
32
27
|
|
33
28
|
# Add an {InteractorInterface} to the {#collection}
|
34
|
-
#
|
35
|
-
# @param
|
36
|
-
# @
|
37
|
-
#
|
38
|
-
# @option filters [Symbol
|
39
|
-
#
|
40
|
-
# @
|
41
|
-
#
|
42
|
-
|
43
|
-
|
29
|
+
#
|
30
|
+
# @param interactor_class [Const, Symbol, String] an {ActiveInteractor::Base interactor} class
|
31
|
+
# @param filters [Hash{Symbol=> Proc, Symbol}] conditional options for the {ActiveInteractor::Base interactor}
|
32
|
+
# class
|
33
|
+
# @option filters [Proc, Symbol] :if only call the {ActiveInteractor::Base interactor}
|
34
|
+
# {Interactor::Perform::ClassMethods#perform .perform} if `Proc` or `method` returns `true`
|
35
|
+
# @option filters [Proc, Symbol] :unless only call the {ActiveInteractor::Base interactor}
|
36
|
+
# {Interactor::Perform::ClassMethods#perform .perform} if `Proc` or `method` returns `false` or `nil`
|
37
|
+
# @return [self] the {InteractorInterfaceCollection} instance
|
38
|
+
def add(interactor_class, filters = {})
|
39
|
+
interface = ActiveInteractor::Organizer::InteractorInterface.new(interactor_class, filters)
|
44
40
|
collection << interface if interface.interactor_class
|
45
41
|
self
|
46
42
|
end
|
47
43
|
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
# @return [
|
52
|
-
def concat(
|
53
|
-
|
44
|
+
# Add multiple {InteractorInterface} to the {#collection}
|
45
|
+
#
|
46
|
+
# @param interactor_classes [Array<Const, Symbol, String>] the {ActiveInteractor::Base interactor} classes
|
47
|
+
# @return [self] the {InteractorInterfaceCollection} instance
|
48
|
+
def concat(interactor_classes)
|
49
|
+
interactor_classes.flatten.each { |interactor_class| add(interactor_class) }
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Calls the given block once for each element in {#collection}, passing that element as a parameter.
|
54
|
+
# @return [self] the {InteractorInterfaceCollection} instance
|
55
|
+
def each(&block)
|
56
|
+
collection.each(&block) if block
|
54
57
|
self
|
55
58
|
end
|
56
59
|
end
|