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