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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.md +50 -158
  4. data/README.md +13 -856
  5. data/lib/active_interactor.rb +61 -4
  6. data/lib/active_interactor/base.rb +26 -20
  7. data/lib/active_interactor/config.rb +36 -18
  8. data/lib/active_interactor/configurable.rb +17 -9
  9. data/lib/active_interactor/context/attributes.rb +73 -26
  10. data/lib/active_interactor/context/base.rb +236 -65
  11. data/lib/active_interactor/context/loader.rb +20 -15
  12. data/lib/active_interactor/context/status.rb +38 -56
  13. data/lib/active_interactor/error.rb +15 -7
  14. data/lib/active_interactor/interactor/callbacks.rb +174 -160
  15. data/lib/active_interactor/interactor/context.rb +279 -87
  16. data/lib/active_interactor/interactor/perform.rb +256 -0
  17. data/lib/active_interactor/interactor/worker.rb +19 -14
  18. data/lib/active_interactor/models.rb +65 -0
  19. data/lib/active_interactor/organizer/base.rb +18 -0
  20. data/lib/active_interactor/organizer/callbacks.rb +153 -0
  21. data/lib/active_interactor/organizer/interactor_interface.rb +38 -26
  22. data/lib/active_interactor/organizer/interactor_interface_collection.rb +35 -32
  23. data/lib/active_interactor/organizer/organize.rb +67 -0
  24. data/lib/active_interactor/organizer/perform.rb +93 -0
  25. data/lib/active_interactor/rails.rb +0 -10
  26. data/lib/active_interactor/rails/orm/active_record.rb +1 -1
  27. data/lib/active_interactor/rails/railtie.rb +8 -11
  28. data/lib/active_interactor/version.rb +2 -1
  29. data/lib/rails/generators/active_interactor.rb +1 -38
  30. data/lib/rails/generators/active_interactor/application_context_generator.rb +21 -0
  31. data/lib/rails/generators/active_interactor/application_interactor_generator.rb +5 -15
  32. data/lib/rails/generators/active_interactor/application_organizer_generator.rb +21 -0
  33. data/lib/rails/generators/active_interactor/base.rb +29 -0
  34. data/lib/rails/generators/active_interactor/generator.rb +21 -0
  35. data/lib/rails/generators/active_interactor/install_generator.rb +2 -9
  36. data/lib/rails/generators/interactor/context/rspec_generator.rb +3 -10
  37. data/lib/rails/generators/interactor/context/test_unit_generator.rb +4 -11
  38. data/lib/rails/generators/interactor/context_generator.rb +7 -10
  39. data/lib/rails/generators/interactor/generates_context.rb +28 -0
  40. data/lib/rails/generators/interactor/interactor_generator.rb +8 -10
  41. data/lib/rails/generators/interactor/organizer_generator.rb +8 -12
  42. data/lib/rails/generators/interactor/rspec_generator.rb +2 -9
  43. data/lib/rails/generators/interactor/test_unit_generator.rb +3 -10
  44. data/lib/rails/generators/{active_interactor/templates/initializer.erb → templates/active_interactor.erb} +3 -11
  45. data/lib/rails/generators/{active_interactor/templates → templates}/application_context.rb +0 -0
  46. data/lib/rails/generators/{active_interactor/templates → templates}/application_interactor.rb +0 -0
  47. data/lib/rails/generators/templates/application_organizer.rb +4 -0
  48. data/lib/rails/generators/{interactor/templates → templates}/context.erb +0 -0
  49. data/lib/rails/generators/{interactor/context/templates/rspec.erb → templates/context_spec.erb} +0 -0
  50. data/lib/rails/generators/{interactor/context/templates/test_unit.erb → templates/context_test_unit.erb} +0 -0
  51. data/lib/rails/generators/{interactor/templates → templates}/interactor.erb +0 -0
  52. data/lib/rails/generators/{interactor/templates/rspec.erb → templates/interactor_spec.erb} +0 -0
  53. data/lib/rails/generators/{interactor/templates/test_unit.erb → templates/interactor_text_unit.erb} +0 -0
  54. data/lib/rails/generators/{interactor/templates → templates}/organizer.erb +0 -0
  55. data/spec/active_interactor/base_spec.rb +3 -3
  56. data/spec/active_interactor/interactor/{perform_options_spec.rb → perform/options_spec.rb} +1 -1
  57. data/spec/active_interactor/interactor/worker_spec.rb +14 -15
  58. data/spec/active_interactor/{organizer_spec.rb → organizer/base_spec.rb} +27 -17
  59. data/spec/integration/a_basic_interactor_spec.rb +106 -0
  60. data/spec/integration/a_basic_organizer_spec.rb +97 -0
  61. data/spec/integration/a_failing_interactor_spec.rb +42 -0
  62. data/spec/integration/active_record_integration_spec.rb +9 -9
  63. data/spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb +69 -0
  64. data/spec/integration/an_interactor_with_after_perform_callbacks_spec.rb +30 -0
  65. data/spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb +33 -0
  66. data/spec/integration/an_interactor_with_an_existing_context_class_spec.rb +49 -0
  67. data/spec/integration/an_interactor_with_around_perform_callbacks_spec.rb +35 -0
  68. data/spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb +39 -0
  69. data/spec/integration/an_interactor_with_before_perform_callbacks_spec.rb +30 -0
  70. data/spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb +33 -0
  71. data/spec/integration/an_interactor_with_validations_on_called_spec.rb +40 -0
  72. data/spec/integration/an_interactor_with_validations_on_calling_spec.rb +36 -0
  73. data/spec/integration/an_interactor_with_validations_spec.rb +93 -0
  74. data/spec/integration/an_organizer_performing_in_parallel_spec.rb +48 -0
  75. data/spec/integration/an_organizer_with_after_each_callbacks_spec.rb +34 -0
  76. data/spec/integration/an_organizer_with_around_each_callbacks_spec.rb +39 -0
  77. data/spec/integration/an_organizer_with_before_each_callbacks_spec.rb +34 -0
  78. data/spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb +314 -0
  79. data/spec/spec_helper.rb +8 -12
  80. data/spec/support/coverage.rb +4 -0
  81. data/spec/support/coverage/reporters.rb +11 -0
  82. data/spec/support/coverage/reporters/codacy.rb +39 -0
  83. data/spec/support/coverage/reporters/simple_cov.rb +54 -0
  84. data/spec/support/coverage/runner.rb +66 -0
  85. data/spec/support/helpers/factories.rb +1 -1
  86. data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +8 -8
  87. data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +5 -5
  88. data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +2 -2
  89. data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +3 -3
  90. metadata +83 -40
  91. data/lib/active_interactor/interactor.rb +0 -84
  92. data/lib/active_interactor/interactor/perform_options.rb +0 -29
  93. data/lib/active_interactor/organizer.rb +0 -269
  94. data/lib/active_interactor/rails/config.rb +0 -45
  95. data/lib/active_interactor/rails/models.rb +0 -58
  96. data/lib/rails/generators/active_interactor/templates/application_organizer.rb +0 -4
  97. data/spec/active_interactor/rails/config_spec.rb +0 -29
  98. data/spec/active_interactor/rails_spec.rb +0 -24
  99. data/spec/integration/basic_callback_integration_spec.rb +0 -355
  100. data/spec/integration/basic_context_integration_spec.rb +0 -73
  101. data/spec/integration/basic_integration_spec.rb +0 -570
  102. 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.2
10
+ # @since 0.1.0
10
11
  class Worker
11
- # @param interactor [Base] an instance of interactor
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
- options = interactor.options.dup
15
- @interactor = interactor.dup.with_options(options)
17
+ @interactor = interactor.deep_dup
16
18
  end
17
19
 
18
- # Calls {#execute_perform!} and rescues {Error::ContextFailure}
19
- # @return [Context::Base] an instance of {Context::Base}
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
- # Calls {Interactor#perform} with callbacks and context validation
28
- # @raise [Error::ContextFailure] if the context fails
29
- # @return [Context::Base] an instance of {Context::Base}
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
- # Calls {Interactor#rollback} with callbacks
37
- # @return [Boolean] `true` if rolled back successfully or `false` if already
38
- # rolled back
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
- class Organizer < ActiveInteractor::Base
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
- # @return [Hash{Symbol=>*}] conditional filters for an interactor's
14
- # {Interactor#perform #perform} invocation.
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
- # @return [Class] an interactor class
18
+ # An {ActiveInteractor::Base interactor} class
19
+ #
20
+ # @return [Const] an {ActiveInteractor::Base interactor} class
21
+ #
17
22
  # @!attribute [r] perform_options
18
- # @return [Hash{Symbol=>*}] perform options to use for an interactor's
19
- # {Interactor#perform #perform} invocation.
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
- # @return [Array<Symbol>] keywords that indicate an option is a
24
- # conditional.
32
+ # Keywords for conditional filters
33
+ # @return [Array<Symbol>]
25
34
  CONDITIONAL_FILTERS = %i[if unless].freeze
26
35
 
27
- # @param interactor_class [Class|Symbol|String] the {.interactor_class}
28
- # @param options [Hash{Symbol=>*}] the {.filters} and {.perform_options}
29
- # @return [InteractorInterface|nil] a new instance of {InteractorInterface} if
30
- # the {#interactor_class} exists
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
- # Check conditional filters on an interactor and invoke it's {Interactor#perform #perform}
38
- # method if conditions are met.
39
- # @param target [Class] an instance of {Organizer}
40
- # @param context [Context::Base] the organizer's {Context::Base context} instance
41
- # @param fail_on_error [Boolean] if `true` {Interactor::ClassMethods#perform! .perform!}
42
- # will be invoked on the interactor. If `false` {Interactor::ClassMethods#perform .perform}
43
- # will be invokded on the interactor.
44
- # @param perform_options [Hash{Symbol=>*}] options for perform
45
- # @return [Context::Base|nil] an instance of {Context::Base} if an interactor's
46
- # {Interactor#perform #perform} is invoked
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
- class Organizer < ActiveInteractor::Base
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
- # @return [Array<Hash{Symbol=>*}] the organized interactors and filters
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
- # Invokes the given block once fore each element of {#collection}.
24
- # @yield [.collection] the {#collection}
25
- # @return [Array] a new array containing the values returned by the block.
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
- # @param interactor [Class|Symbol|String] an interactor class name
35
- # @param filters [Hash{Symbol=>*}] conditions and {Interactor::PerformOptions} for the interactor
36
- # @option filters [Symbol|Proc] :if only invoke the interactor's perform method
37
- # if method or block returns `true`
38
- # @option filters [Symbol|Proc] :unless only invoke the interactor's perform method
39
- # if method or block returns `false`
40
- # @see Interactor::PerformOptions
41
- # @return [InteractorInterface] the {InteractorInterface} instance
42
- def add(interactor, filters = {})
43
- interface = InteractorInterface.new(interactor, filters)
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
- # Concat multiple {InteractorInterface} to the {#collection}
49
- # @param interactors [Array<Class>] the interactor classes to add
50
- # to the collection
51
- # @return [InteractorInterface] the {InteractorInterface} instance
52
- def concat(interactors)
53
- interactors.flatten.each { |interactor| add(interactor) }
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