activeinteractor 0.1.7 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -1
  3. data/README.md +397 -395
  4. data/lib/active_interactor.rb +12 -30
  5. data/lib/active_interactor/base.rb +18 -8
  6. data/lib/active_interactor/context.rb +4 -181
  7. data/lib/active_interactor/context/attributes.rb +37 -149
  8. data/lib/active_interactor/context/base.rb +141 -0
  9. data/lib/active_interactor/context/loader.rb +45 -0
  10. data/lib/active_interactor/error.rb +22 -15
  11. data/lib/active_interactor/interactor.rb +24 -57
  12. data/lib/active_interactor/interactor/callbacks.rb +64 -76
  13. data/lib/active_interactor/interactor/context.rb +97 -63
  14. data/lib/active_interactor/interactor/worker.rb +22 -65
  15. data/lib/active_interactor/organizer.rb +180 -164
  16. data/lib/active_interactor/version.rb +2 -3
  17. data/lib/rails/generators/active_interactor.rb +2 -37
  18. data/lib/rails/generators/active_interactor/application_interactor_generator.rb +23 -0
  19. data/lib/rails/generators/active_interactor/install_generator.rb +8 -12
  20. data/lib/rails/generators/active_interactor/templates/application_context.rb +4 -0
  21. data/lib/rails/generators/{templates/application_interactor.erb → active_interactor/templates/application_interactor.rb} +0 -0
  22. data/lib/rails/generators/active_interactor/templates/application_organizer.rb +4 -0
  23. data/lib/rails/generators/active_interactor/templates/initializer.erb +5 -0
  24. data/lib/rails/generators/interactor/context/rspec_generator.rb +19 -0
  25. data/lib/rails/generators/interactor/context/templates/rspec.erb +7 -0
  26. data/lib/rails/generators/interactor/context/templates/test_unit.erb +9 -0
  27. data/lib/rails/generators/interactor/context/test_unit_generator.rb +19 -0
  28. data/lib/rails/generators/interactor/context_generator.rb +19 -0
  29. data/lib/rails/generators/interactor/interactor_generator.rb +8 -3
  30. data/lib/rails/generators/interactor/organizer_generator.rb +8 -3
  31. data/lib/rails/generators/interactor/rspec_generator.rb +4 -3
  32. data/lib/rails/generators/interactor/templates/context.erb +4 -0
  33. data/lib/rails/generators/{templates → interactor/templates}/interactor.erb +0 -0
  34. data/lib/rails/generators/{templates → interactor/templates}/organizer.erb +1 -1
  35. data/lib/rails/generators/{templates → interactor/templates}/rspec.erb +0 -0
  36. data/lib/rails/generators/{templates → interactor/templates}/test_unit.erb +0 -0
  37. data/lib/rails/generators/interactor/test_unit_generator.rb +4 -3
  38. data/spec/active_interactor/base_spec.rb +51 -0
  39. data/spec/active_interactor/context/base_spec.rb +229 -0
  40. data/spec/active_interactor/error_spec.rb +43 -0
  41. data/spec/active_interactor/interactor/worker_spec.rb +89 -0
  42. data/spec/active_interactor/organizer_spec.rb +178 -0
  43. data/spec/active_interactor_spec.rb +26 -0
  44. data/spec/integration/basic_callback_integration_spec.rb +355 -0
  45. data/spec/integration/basic_context_integration_spec.rb +73 -0
  46. data/spec/integration/basic_integration_spec.rb +220 -0
  47. data/spec/integration/basic_validations_integration_spec.rb +204 -0
  48. data/spec/spec_helper.rb +44 -0
  49. data/spec/support/helpers/factories.rb +41 -0
  50. data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +99 -0
  51. data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +58 -0
  52. data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +21 -0
  53. data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +39 -0
  54. data/spec/support/spec_helpers.rb +7 -0
  55. metadata +68 -138
  56. data/lib/active_interactor/configuration.rb +0 -38
  57. data/lib/active_interactor/interactor/execution.rb +0 -24
  58. data/lib/rails/generators/templates/initializer.erb +0 -15
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+ require 'ostruct'
5
+
6
+ require 'active_interactor/context/attributes'
7
+
8
+ module ActiveInteractor
9
+ module Context
10
+ # The base context class. All interactor contexts should inherit from
11
+ # {Context::Base}.
12
+ # @author Aaron Allen <hello@aaronmallen.me>
13
+ # @since 0.0.1
14
+ class Base < OpenStruct
15
+ include ActiveModel::Validations
16
+ include Attributes
17
+
18
+ # @!method valid?(context = nil)
19
+ # @see
20
+ # https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations.rb#L305
21
+ # ActiveModel::Validations#valid?
22
+
23
+ # @api private
24
+ # Track that an Interactor has been called. The {#called!} method
25
+ # is used by the interactor being invoked with this context. After an
26
+ # interactor is successfully called, the interactor instance is tracked in
27
+ # the context for the purpose of potential future rollback
28
+ # @param interactor [ActiveInteractor::Base] the called interactor
29
+ # @return [Array<ActiveInteractor::Base>] all called interactors
30
+ def called!(interactor)
31
+ _called << interactor
32
+ end
33
+
34
+ # Fail the context instance. Failing a context raises an error
35
+ # that may be rescued by the calling interactor. The context is also flagged
36
+ # as having failed
37
+ #
38
+ # @example Fail an interactor context
39
+ # class MyInteractor < ActiveInteractor::Base
40
+ # def perform
41
+ # context.fail!
42
+ # end
43
+ # end
44
+ #
45
+ # MyInteractor.perform!
46
+ # #=> ActiveInteractor::Error::ContextFailure: <#MyInteractor::Context>
47
+ # @param errors [ActiveModel::Errors|nil] errors to add to the context on failure
48
+ # @see https://api.rubyonrails.org/classes/ActiveModel/Errors.html ActiveModel::Errors
49
+ # @raise [Error::ContextFailure]
50
+ def fail!(errors = nil)
51
+ merge_errors!(errors) if errors
52
+ @_failed = true
53
+ raise Error::ContextFailure, self
54
+ end
55
+
56
+ # Whether the context instance has failed. By default, a new
57
+ # context is successful and only changes when explicitly failed
58
+ # @note The {#failure?} method is the inverse of the {#success?} method
59
+ # @example Check if a context has failed
60
+ # class MyInteractor < ActiveInteractor::Base
61
+ # def perform; end
62
+ # end
63
+ #
64
+ # result = MyInteractor.perform
65
+ # #=> <#MyInteractor::Context>
66
+ #
67
+ # result.failure?
68
+ # #=> false
69
+ # @return [Boolean] `false` by default or `true` if failed
70
+ def failure?
71
+ @_failed || false
72
+ end
73
+ alias fail? failure?
74
+
75
+ # Roll back an interactor context. Any interactors to which this
76
+ # context has been passed and which have been successfully called are asked
77
+ # to roll themselves back by invoking their
78
+ # {ActiveInteractor::Base#rollback} instance methods.
79
+ # @example Rollback an interactor's context
80
+ # class MyInteractor < ActiveInteractor::Base
81
+ # def perform
82
+ # context.fail!
83
+ # end
84
+ #
85
+ # def rollback
86
+ # context.user&.destroy
87
+ # end
88
+ # end
89
+ #
90
+ # user = User.create
91
+ # #=> <#User>
92
+ #
93
+ # result = MyInteractor.perform(user: user)
94
+ # #=> <#MyInteractor::Context user=<#User>>
95
+ #
96
+ # result.user.destroyed?
97
+ # #=> true
98
+ # @return [Boolean] `true` if rolled back successfully or `false` if already
99
+ # rolled back
100
+ def rollback!
101
+ return false if @_rolled_back
102
+
103
+ _called.reverse_each(&:rollback)
104
+ @_rolled_back = true
105
+ end
106
+
107
+ # Whether the context instance is successful. By default, a new
108
+ # context is successful and only changes when explicitly failed
109
+ # @note the {#success?} method is the inverse of the {#failure?} method
110
+ # @example Check if a context is successful
111
+ # class MyInteractor < ActiveInteractor::Base
112
+ # def perform; end
113
+ # end
114
+ #
115
+ # result = MyInteractor.perform
116
+ # #=> <#MyInteractor::Context>
117
+ #
118
+ # result.success?
119
+ # #=> true
120
+ # @return [Boolean] `true` by default or `false` if failed
121
+ def success?
122
+ !failure?
123
+ end
124
+ alias successful? success?
125
+
126
+ private
127
+
128
+ def _called
129
+ @_called ||= []
130
+ end
131
+
132
+ def merge_errors!(errors)
133
+ if errors.is_a? String
134
+ self.errors.add(:context, errors)
135
+ else
136
+ self.errors.merge!(errors)
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module ActiveInteractor
6
+ module Context
7
+ # @api private
8
+ # Load, find or create {Context::Base} classes for a given interactor.
9
+ # @author Aaron Allen <hello@aaronmallen.me>
10
+ # @since 1.0.0
11
+ module Loader
12
+ # @return [Array<Class>] ActiveInteractor base classes
13
+ BASE_CLASSES = [ActiveInteractor::Base, ActiveInteractor::Organizer].freeze
14
+ # @return [Class] the base context class
15
+ BASE_CONTEXT = ActiveInteractor::Context::Base
16
+
17
+ # Create a new context class on an interactor
18
+ # @param context_class_name [String] the name of the class to create
19
+ # @param interactor_class [Class] the interactor class to create the context for
20
+ # @return [Class] the created context class
21
+ def self.create(context_class_name, interactor_class)
22
+ interactor_class.const_set(context_class_name.to_s.classify, Class.new(BASE_CONTEXT))
23
+ end
24
+
25
+ # Find or create a new context class for an interactor
26
+ # @note the loader will attempt to find an existing context given the naming conventions:
27
+ # `MyInteractor::Context` or `MyInteractorContext`
28
+ # @param interactor_class [Class] the interactor class to find or create the context for
29
+ def self.find_or_create(interactor_class)
30
+ return BASE_CONTEXT if BASE_CLASSES.include?(interactor_class)
31
+
32
+ klass = possible_classes(interactor_class).first
33
+ klass || create('Context', interactor_class)
34
+ end
35
+
36
+ def self.possible_classes(interactor_class)
37
+ ["#{interactor_class.name}::Context", "#{interactor_class.name}Context"]
38
+ .map(&:safe_constantize)
39
+ .compact
40
+ .reject { |klass| klass&.name&.include?('ActiveInteractor') }
41
+ end
42
+ private_class_method :possible_classes
43
+ end
44
+ end
45
+ end
@@ -1,30 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveInteractor
4
- # ActiveInteractor::Error module
5
- #
4
+ # ActiveInteractor errors
6
5
  # @author Aaron Allen <hello@aaronmallen.me>
7
6
  # @since 0.1.5
8
- # @version 0.1
9
7
  module Error
10
- # Raised when an interactor context fails
11
- #
12
- # @author Aaron Allen <hello@aaronmallen.me>
13
- # @since 0.1.5
14
- # @version 0.1
15
- #
8
+ # Raised when an interactor context fails.
16
9
  # @!attribute [r] context
17
- # @return [Base] an instance of {Base}
10
+ # @return [Context::Base] an instance of {Context::Base}
18
11
  class ContextFailure < StandardError
19
12
  attr_reader :context
20
13
 
21
- # A new instance of {ContextFailure}
22
- # @param context [ActiveInteractor::Context::Base] an
23
- # instance of {ActiveInteractor::Context::Base}
24
- # @return [ContextFailure] a new instance of {ContextFailure}
14
+ # @param context [Context::Base] the failed context instance.
15
+ # @return [ContextFailure] a new instance of {ContextFailure}.
25
16
  def initialize(context = nil)
26
17
  @context = context
27
- super
18
+ context_class_name = context&.class&.name || 'Context'
19
+ super("#{context_class_name} failed!")
20
+ end
21
+ end
22
+
23
+ # Raised when an invalid context class is assigned to an interactor.
24
+ # @since 1.0.0
25
+ # @!attribute [r] class_name
26
+ # @return [String|nil] the class name of the context
27
+ class InvalidContextClass < StandardError
28
+ attr_reader :class_name
29
+
30
+ # @param class_name [String] the context class name
31
+ # @return [InvalidContextClass] a new instance of {InvalidContextClass}
32
+ def initialize(class_name = nil)
33
+ @class_name = class_name
34
+ super("invalid context class #{class_name}")
28
35
  end
29
36
  end
30
37
  end
@@ -1,65 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveInteractor
4
- # Provides interactor methods to included classes
5
- #
4
+ # Interactor methods. {Base} includes {Interactor} all interactors
5
+ # should inherit from {Base}.
6
6
  # @author Aaron Allen <hello@aaronmallen.me>
7
7
  # @since 0.0.1
8
- # @version 0.1
9
8
  module Interactor
10
- extend ActiveSupport::Concern
11
-
12
- included do
13
- extend ClassMethods
14
- include Callbacks
15
- include Context
16
- include Execution
17
-
18
- private
19
-
20
- attr_accessor :context
9
+ def self.included(base)
10
+ base.class_eval do
11
+ extend ClassMethods
12
+ include Callbacks
13
+ include Context
14
+ delegate :execute_perform, :execute_perform!, :execute_rollback, to: :worker
15
+ end
21
16
  end
22
-
17
+ # Interactor class methods.
23
18
  module ClassMethods
24
- # Invoke an interactor. This is the primary public API method to an
25
- # interactor.
26
- #
19
+ # Run an interactor context. This it the primary API method for
20
+ # interacting with interactors.
27
21
  # @example Run an interactor
28
22
  # MyInteractor.perform(name: 'Aaron')
29
23
  # #=> <#MyInteractor::Context name='Aaron'>
30
- #
31
- # @param context [Hash] properties to assign to the interactor context
32
- # @return [ActiveInteractor::Context::Base] an instance of context
24
+ # @param context [Hash|Context::Base] properties to assign to
25
+ # an interactor's context.
26
+ # @return [Context::Base] an instance of context.
33
27
  def perform(context = {})
34
28
  new(context).execute_perform
35
29
  end
36
30
 
37
- # Invoke an Interactor. The {.perform!} method behaves identically to
31
+ # Run an interactor context. The {.perform!} method behaves identically to
38
32
  # the {.perform} method with one notable exception. If the context is failed
39
- # during invocation of the interactor, the {ActiveInteractor::Error::ContextFailure}
33
+ # during invocation of the interactor, the {Error::ContextFailure}
40
34
  # is raised.
41
- #
42
35
  # @example Run an interactor
43
36
  # MyInteractor.perform!(name: 'Aaron')
44
37
  # #=> <#MyInteractor::Context name='Aaron'>
45
- #
46
- # @param context [Hash] properties to assign to the interactor context
47
- # @return [ActiveInteractor::Context::Base] an instance of context
38
+ # @param context [Hash|Context::Base] properties to assign to the interactor context.
39
+ # @raise [Error::ContextFailure] if the context fails.
40
+ # @return [Context::Base] an instance of context.
48
41
  def perform!(context = {})
49
42
  new(context).execute_perform!
50
43
  end
51
44
  end
52
45
 
53
- # Whether or not the context should fail when invalid
54
- # this will return false if
55
- # {Interactor::Callbacks::ClassMethods#allow_context_to_be_invalid}
56
- # has been invoked on the class.
57
- # @return [Boolean] `true` if the context should fail
58
- # `false` if it should not.
59
- def fail_on_invalid_context?
60
- self.class.__fail_on_invalid_context
61
- end
62
-
63
46
  # Invoke an Interactor instance without any hooks, tracking, or rollback
64
47
  # @abstract It is expected that the {#perform} method is overwritten
65
48
  # for each interactor class.
@@ -70,28 +53,12 @@ module ActiveInteractor
70
53
  # failure is expected to overwrite the {#rollback} method.
71
54
  def rollback; end
72
55
 
73
- # Whether or not the context should be cleaned after {#perform}
74
- # if {#skip_clean_context!} has not been invoked on the instance
75
- # and {Interactor::Callbacks::ClassMethods#clean_context_on_completion}
76
- # is invoked on the class this will return `true`.
77
- #
78
- # @return [Boolean] `true` if the context should be cleaned
79
- # `false` if it should not be cleaned.
80
- def should_clean_context?
81
- @should_clean_context.nil? && self.class.__clean_after_perform
82
- end
56
+ private
83
57
 
84
- # Skip {ActiveInteractor::Context::Attributes#clean! #clean! on an interactor
85
- # context that calls the {Callbacks.clean_context_on_completion} class method.
86
- # This method is meant to be invoked by organizer interactors
87
- # to ensure contexts are approriately passed between interactors.
88
- #
89
- # @return [Boolean] `true` if the context should be cleaned
90
- # `false` if it should not.
91
- def skip_clean_context!
92
- @should_clean_context = false
58
+ def worker
59
+ Worker.new(self)
93
60
  end
94
61
  end
95
62
  end
96
63
 
97
- Dir[File.expand_path('interactor/*.rb', __dir__)].each { |file| require file }
64
+ Dir[File.expand_path('interactor/*.rb', __dir__)].sort.each { |file| require file }
@@ -1,62 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/callbacks'
3
4
  require 'active_support/core_ext/array/extract_options'
4
5
  require 'active_support/core_ext/class/attribute'
5
6
 
6
7
  module ActiveInteractor
7
8
  module Interactor
8
- # Provides context attribute assignment methods to included classes
9
- #
9
+ # Interactor callback methods included by all {Base}
10
10
  # @author Aaron Allen <hello@aaronmallen.me>
11
11
  # @since 0.0.1
12
- # @version 0.1
13
12
  module Callbacks
14
- extend ActiveSupport::Concern
13
+ def self.included(base)
14
+ base.class_eval do
15
+ extend ClassMethods
16
+ include ActiveSupport::Callbacks
15
17
 
16
- included do
17
- extend ClassMethods
18
- include ActiveSupport::Callbacks
19
-
20
- class_attribute :__clean_after_perform, instance_writer: false, default: false
21
- class_attribute :__fail_on_invalid_context, instance_writer: false, default: true
22
- define_callbacks :validation,
23
- skip_after_callbacks_if_terminated: true,
24
- scope: %i[kind name]
25
- define_callbacks :perform, :rollback
18
+ define_callbacks :validation,
19
+ skip_after_callbacks_if_terminated: true,
20
+ scope: %i[kind name]
21
+ define_callbacks :perform, :rollback
22
+ end
26
23
  end
27
24
 
25
+ # Interactor callback class methods extended by all {Base}
28
26
  module ClassMethods
29
- # Define a callback to call after `#valid?` has been invoked on an
27
+ # Define a callback to call after {ActiveInteractor::Context::Base#valid? #valid?} has been invoked on an
30
28
  # interactor's context
31
- #
32
29
  # @example Implement an after_context_validation callback
33
30
  # class MyInteractor < ActiveInteractor::Base
34
- # after_context_validation :ensure_name_is_aaron
35
- # context_validates :name, inclusion: { in: %w[Aaron] }
31
+ # after_context_validation :downcase_name
32
+ #
33
+ # private
36
34
  #
37
- # def ensure_name_is_aaron
38
- # context.name = 'Aaron'
35
+ # def downcase_name
36
+ # context.name.downcase!
39
37
  # end
40
38
  # end
41
39
  #
42
- # context = MyInteractor.perform(name: 'Bob')
43
- # #=> <MyInteractor::Context name='Bob'>
40
+ # result = MyInteractor.perform(name: 'Aaron')
41
+ # #=> <MyInteractor::Context name='aaron'>
44
42
  #
45
- # context.valid?
46
- # #=> false
47
- #
48
- # context.name
49
- # #=> 'Aaron'
50
- #
51
- # context.valid?
43
+ # result.valid?
52
44
  # #=> true
45
+ #
46
+ # result.name
47
+ # #=> 'aaron'
53
48
  def after_context_validation(*args, &block)
54
49
  options = normalize_options(args.extract_options!.dup.merge(prepend: true))
55
50
  set_callback(:validation, :after, *args, options, &block)
56
51
  end
57
52
 
58
- # Define a callback to call after {ActiveInteractor::Base.perform} has been invoked
59
- #
53
+ # Define a callback to call after {Interactor#perform #perform} has been invoked
60
54
  # @example
61
55
  # class MyInteractor < ActiveInteractor::Base
62
56
  # after_perform :print_done
@@ -65,6 +59,8 @@ module ActiveInteractor
65
59
  # puts 'Performing'
66
60
  # end
67
61
  #
62
+ # private
63
+ #
68
64
  # def print_done
69
65
  # puts 'Done'
70
66
  # end
@@ -78,16 +74,21 @@ module ActiveInteractor
78
74
  set_callback(:perform, :after, *filters, &block)
79
75
  end
80
76
 
81
- # Define a callback to call after {ActiveInteractor::Base#rollback} has been invoked
82
- #
77
+ # Define a callback to call after {Interactor#rollback #rollback} has been invoked
83
78
  # @example
84
79
  # class MyInteractor < ActiveInteractor::Base
85
80
  # after_rollback :print_done
86
81
  #
82
+ # def perform
83
+ # context.fail!
84
+ # end
85
+ #
87
86
  # def rollback
88
87
  # puts 'Rolling back'
89
88
  # end
90
89
  #
90
+ # private
91
+ #
91
92
  # def print_done
92
93
  # puts 'Done'
93
94
  # end
@@ -103,17 +104,7 @@ module ActiveInteractor
103
104
  set_callback(:rollback, :after, *filters, &block)
104
105
  end
105
106
 
106
- # By default an interactor context will fail if it is deemed
107
- # invalid before or after the {ActiveInteractor::Base.perform} method
108
- # is invoked. Calling this method on an interactor class
109
- # will not invoke {ActiveInteractor::Context::Base#fail!} if the
110
- # context is invalid.
111
- def allow_context_to_be_invalid
112
- self.__fail_on_invalid_context = false
113
- end
114
-
115
- # Define a callback to call around {ActiveInteractor::Base.perform} invokation
116
- #
107
+ # Define a callback to call around {Interactor#perform #perform} invokation
117
108
  # @example
118
109
  # class MyInteractor < ActiveInteractor::Base
119
110
  # around_perform :track_time
@@ -122,6 +113,8 @@ module ActiveInteractor
122
113
  # sleep(1)
123
114
  # end
124
115
  #
116
+ # private
117
+ #
125
118
  # def track_time
126
119
  # context.start_time = Time.now.utc
127
120
  # yield
@@ -129,20 +122,19 @@ module ActiveInteractor
129
122
  # end
130
123
  # end
131
124
  #
132
- # context = MyInteractor.perform(name: 'Aaron')
125
+ # result = MyInteractor.perform(name: 'Aaron')
133
126
  # #=> <MyInteractor::Context name='Aaron'>
134
127
  #
135
- # context.start_time
128
+ # result.start_time
136
129
  # #=> 2019-01-01 00:00:00 UTC
137
130
  #
138
- # context.end_time
131
+ # result.end_time
139
132
  # #=> 2019-01-01 00:00:01 UTC
140
133
  def around_perform(*filters, &block)
141
134
  set_callback(:perform, :around, *filters, &block)
142
135
  end
143
136
 
144
- # Define a callback to call around {ActiveInteractor::Base#rollback} invokation
145
- #
137
+ # Define a callback to call around {Interactor#rollback #rollback} invokation
146
138
  # @example
147
139
  # class MyInteractor < ActiveInteractor::Base
148
140
  # around_rollback :track_time
@@ -151,6 +143,8 @@ module ActiveInteractor
151
143
  # sleep(1)
152
144
  # end
153
145
  #
146
+ # private
147
+ #
154
148
  # def track_time
155
149
  # context.start_time = Time.now.utc
156
150
  # yield
@@ -158,49 +152,48 @@ module ActiveInteractor
158
152
  # end
159
153
  # end
160
154
  #
161
- # context = MyInteractor.perform(name: 'Aaron')
155
+ # result = MyInteractor.perform(name: 'Aaron')
162
156
  # #=> <MyInteractor::Context name='Aaron'>
163
157
  #
164
- # context.rollback!
158
+ # result.rollback!
165
159
  # #=> true
166
160
  #
167
- # context.start_time
161
+ # result.start_time
168
162
  # #=> 2019-01-01 00:00:00 UTC
169
163
  #
170
- # context.end_time
164
+ # result.end_time
171
165
  # #=> 2019-01-01 00:00:01 UTC
172
166
  def around_rollback(*filters, &block)
173
167
  set_callback(:rollback, :around, *filters, &block)
174
168
  end
175
169
 
176
- # Define a callback to call before `#valid?` has been invoked on an
170
+ # Define a callback to call before {ActiveInteractor::Context::Base#valid? #valid?} has been invoked on an
177
171
  # interactor's context
178
- #
179
172
  # @example Implement an after_context_validation callback
180
173
  # class MyInteractor < ActiveInteractor::Base
181
- # before_context_validation :set_name_aaron
182
- # context_validates :name, inclusion: { in: %w[Aaron] }
174
+ # before_context_validation :downcase_name
183
175
  #
184
- # def set_name_aaron
185
- # context.name = 'Aaron'
176
+ # private
177
+ #
178
+ # def downcase_name
179
+ # context.name.downcase!
186
180
  # end
187
181
  # end
188
182
  #
189
- # context = MyInteractor.perform(name: 'Bob')
190
- # #=> <MyInteractor::Context name='Bob'>
183
+ # result = MyInteractor.perform(name: 'Aaron')
184
+ # #=> <MyInteractor::Context name='aaron'>
191
185
  #
192
- # context.valid?
186
+ # result.valid?
193
187
  # #=> true
194
188
  #
195
- # context.name
196
- # #=> 'Aaron'
189
+ # result.name
190
+ # #=> 'aaron'
197
191
  def before_context_validation(*args, &block)
198
192
  options = normalize_options(args.extract_options!.dup)
199
193
  set_callback(:validation, :before, *args, options, &block)
200
194
  end
201
195
 
202
- # Define a callback to call before {ActiveInteractor::Base.perform} has been invoked
203
- #
196
+ # Define a callback to call before {Interactor#perform #perform} has been invoked
204
197
  # @example
205
198
  # class MyInteractor < ActiveInteractor::Base
206
199
  # before_perform :print_start
@@ -209,6 +202,8 @@ module ActiveInteractor
209
202
  # puts 'Performing'
210
203
  # end
211
204
  #
205
+ # private
206
+ #
212
207
  # def print_start
213
208
  # puts 'Start'
214
209
  # end
@@ -222,8 +217,7 @@ module ActiveInteractor
222
217
  set_callback(:perform, :before, *filters, &block)
223
218
  end
224
219
 
225
- # Define a callback to call before {ActiveInteractor::Base#rollback} has been invoked
226
- #
220
+ # Define a callback to call before {Interactor#rollback #rollback} has been invoked
227
221
  # @example
228
222
  # class MyInteractor < ActiveInteractor::Base
229
223
  # before_rollback :print_start
@@ -232,6 +226,8 @@ module ActiveInteractor
232
226
  # puts 'Rolling Back'
233
227
  # end
234
228
  #
229
+ # private
230
+ #
235
231
  # def print_start
236
232
  # puts 'Start'
237
233
  # end
@@ -248,14 +244,6 @@ module ActiveInteractor
248
244
  set_callback(:rollback, :before, *filters, &block)
249
245
  end
250
246
 
251
- # Calling this method on an interactor class will invoke
252
- # {ActiveInteractor::Context::Base#clean!} on the interactor's
253
- # context instance after {ActiveInteractor::Base.perform}
254
- # is invoked.
255
- def clean_context_on_completion
256
- self.__clean_after_perform = true
257
- end
258
-
259
247
  private
260
248
 
261
249
  def normalize_options(options)