activeinteractor 1.1.6 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9590abce809d47171ae43dcba47b6f587b90b0d77d598e47536904dba645b101
4
- data.tar.gz: 0d4141a041eb62497c42a15500258c4b1c5fce7c02a8dc3ef78a1a5328f60c89
3
+ metadata.gz: 7d574fdd7c5e1d8666f8d61c4b6acd9aca316ca1789aa84950233f151fe4f9ca
4
+ data.tar.gz: 9589d5a2a8e04681d30bcda448d8459007b941d38f5756b12ed1ae2fee478d12
5
5
  SHA512:
6
- metadata.gz: 8302c677e05036f6412b9cc32dc43be19e829442a4350c5e93f135ed84ee6f0e0e823c4a809c19b393fdaef5677495aa1bbfbf85e87521a31dc6b5045a8d83ec
7
- data.tar.gz: 2f4ff4d83e90881d5f255783953a513540e023b6249c6f6bba0ebd52b5e73ed87490324ecb1718da63fc51ad3da7df526b76a25c5b6be2176043630f30f1544a
6
+ metadata.gz: 99401e868682e3fad2f702da4bf38e711e8637584210622fc70e0970f4600d8713da3ce2539019bea231953e88257ea4b9d62db026f9a90ce6aa8c9461d76c1e
7
+ data.tar.gz: 9a81aff115c7351de89fa45689a7fc2e3b225ad15ad9a437acfa18dc2ff58839491447f77b8593c9c8098d71058d681323caed1054fbbdc518f4ea5bd705989e
data/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning].
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [v1.2.0] - 2022-09-08
11
+
12
+ ### Added
13
+
14
+ - `ActiveInteractor::Base.defer_after_callbacks_when_organized`
15
+ - `ActiveInteractor::Organizer::Base.after_all_perform`
16
+ - `ActiveInteractor::Organizer::Base.around_all_perform`
17
+ - `ActiveInteractor::Organizer::Base.before_all_perform`
18
+
10
19
  ## [v1.1.6] - 2022-04-25
11
20
 
12
21
  ### Changed
@@ -249,7 +258,8 @@ and this project adheres to [Semantic Versioning].
249
258
 
250
259
  <!-- versions -->
251
260
 
252
- [Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.1.6...HEAD
261
+ [Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.2.0...HEAD
262
+ [v1.2.0]: https://github.com/aaronmallen/activeinteractor/compare/v1.1.6...v1.2.0
253
263
  [v1.1.6]: https://github.com/aaronmallen/activeinteractor/compare/v1.1.4...v1.1.6
254
264
  [v1.1.4]: https://github.com/aaronmallen/activeinteractor/compare/v1.1.3...v1.1.4
255
265
  [v1.1.3]: https://github.com/aaronmallen/activeinteractor/compare/v1.1.2...v1.1.3
@@ -249,6 +249,24 @@ module ActiveInteractor
249
249
  set_callback(:rollback, :before, *filters, &block)
250
250
  end
251
251
 
252
+ # Set {.after_callbacks_deferred_when_organized} to `true`
253
+ #
254
+ # @since v1.2.0
255
+ #
256
+ # @example a basic {Base organizer} set to defer 'after' callbacks when organized
257
+ # class MyOrganizer < ActiveInteractor::Organizer::Base
258
+ # defer_after_callbacks_when_organized
259
+ # end
260
+ def defer_after_callbacks_when_organized
261
+ self.after_callbacks_deferred_when_organized = true
262
+ end
263
+
264
+ def self.extended(base)
265
+ base.class_eval do
266
+ class_attribute :after_callbacks_deferred_when_organized, instance_writer: false, default: false
267
+ end
268
+ end
269
+
252
270
  private
253
271
 
254
272
  def normalize_options(options)
@@ -141,11 +141,133 @@ module ActiveInteractor
141
141
  def before_each_perform(*filters, &block)
142
142
  set_callback(:each_perform, :before, *filters, &block)
143
143
  end
144
+
145
+ # Define a callback to call after all {Organizer::Organize::ClassMethods#organized organized}
146
+ # {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} methods have been called.
147
+ #
148
+ # @since v1.2.0
149
+ #
150
+ # @example
151
+ # class MyInteractor1 < ActiveInteractor::Base
152
+ # def perform
153
+ # puts 'MyInteractor1'
154
+ # end
155
+ # end
156
+ #
157
+ # class MyInteractor2 < ActiveInteractor::Base
158
+ # def perform
159
+ # puts 'MyInteractor2'
160
+ # end
161
+ # end
162
+ #
163
+ # class MyOrganizer < ActiveInteractor::Organizer
164
+ # after_all_perform :print_done
165
+ #
166
+ # organized MyInteractor1, MyInteractor2
167
+ #
168
+ # private
169
+ #
170
+ # def print_done
171
+ # puts 'Done'
172
+ # end
173
+ # end
174
+ #
175
+ # MyOrganizer.perform
176
+ # "MyInteractor1"
177
+ # "MyInteractor2"
178
+ # "Done"
179
+ # #=> <MyOrganizer::Context>
180
+ def after_all_perform(*filters, &block)
181
+ set_callback(:all_perform, :after, *filters, &block)
182
+ end
183
+
184
+ # Define a callback to call around all {Organizer::Organize::ClassMethods#organized organized}
185
+ # {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} method calls.
186
+ #
187
+ # @since v1.2.0
188
+ #
189
+ # @example
190
+ # class MyInteractor1 < ActiveInteractor::Base
191
+ # def perform
192
+ # puts 'MyInteractor1'
193
+ # sleep(1)
194
+ # end
195
+ # end
196
+ #
197
+ # class MyInteractor2 < ActiveInteractor::Base
198
+ # def perform
199
+ # puts 'MyInteractor2'
200
+ # sleep(1)
201
+ # end
202
+ # end
203
+ #
204
+ # class MyOrganizer < ActiveInteractor::Organizer
205
+ # around_all_perform :print_time
206
+ #
207
+ # organized MyInteractor1, MyInteractor2
208
+ #
209
+ # private
210
+ #
211
+ # def print_time
212
+ # puts Time.now.utc
213
+ # yield
214
+ # puts Time.now.utc
215
+ # end
216
+ # end
217
+ #
218
+ # MyOrganizer.perform
219
+ # "2019-04-01 00:00:00 UTC"
220
+ # "MyInteractor1"
221
+ # "MyInteractor2"
222
+ # "2019-04-01 00:00:02 UTC"
223
+ # #=> <MyOrganizer::Context>
224
+ def around_all_perform(*filters, &block)
225
+ set_callback(:all_perform, :around, *filters, &block)
226
+ end
227
+
228
+ # Define a callback to call before all {Organizer::Organize::ClassMethods#organized organized}
229
+ # {ActiveInteractor::Base interactors'} {Interactor::Perform#perform #perform} methods have been called.
230
+ #
231
+ # @since v1.2.0
232
+ #
233
+ # @example
234
+ # class MyInteractor1 < ActiveInteractor::Base
235
+ # def perform
236
+ # puts 'MyInteractor1'
237
+ # end
238
+ # end
239
+ #
240
+ # class MyInteractor2 < ActiveInteractor::Base
241
+ # def perform
242
+ # puts 'MyInteractor2'
243
+ # end
244
+ # end
245
+ #
246
+ # class MyOrganizer < ActiveInteractor::Organizer
247
+ # before_all_perform :print_starting
248
+ #
249
+ # organized MyInteractor1, MyInteractor2
250
+ #
251
+ # private
252
+ #
253
+ # def print_starting
254
+ # puts 'Starting'
255
+ # end
256
+ # end
257
+ #
258
+ # MyOrganizer.perform
259
+ # "Starting"
260
+ # "MyInteractor1"
261
+ # "MyInteractor2"
262
+ # #=> <MyOrganizer::Context>
263
+ def before_all_perform(*filters, &block)
264
+ set_callback(:all_perform, :before, *filters, &block)
265
+ end
144
266
  end
145
267
 
146
268
  def self.included(base)
147
269
  base.class_eval do
148
- define_callbacks :each_perform
270
+ define_callbacks :each_perform, :all_perform
149
271
  end
150
272
  end
151
273
  end
@@ -33,8 +33,14 @@ module ActiveInteractor
33
33
  #
34
34
  # @return [Hash{Symbol=>*}] {Interactor::Perform::Options} for the {ActiveInteractor::Base interactor}
35
35
  # {Interactor::Perform#perform #perform}
36
+ #
37
+ # @!attribute [r] deferred_after_perform_callbacks
38
+ # Deffered callbacks for the interactor_class
39
+ # @since 1.2.0
40
+ #
41
+ # @return [Hash{Symbol=>*}] the interactor callbacks
36
42
  class InteractorInterface
37
- attr_reader :filters, :callbacks, :interactor_class, :perform_options
43
+ attr_reader :filters, :callbacks, :interactor_class, :perform_options, :deferred_after_perform_callbacks
38
44
 
39
45
  # Keywords for conditional filters
40
46
  # @return [Array<Symbol>]
@@ -52,6 +58,7 @@ module ActiveInteractor
52
58
  @filters = options.select { |key, _value| CONDITIONAL_FILTERS.include?(key) }
53
59
  @callbacks = options.select { |key, _value| CALLBACKS.include?(key) }
54
60
  @perform_options = options.reject { |key, _value| CONDITIONAL_FILTERS.include?(key) || CALLBACKS.include?(key) }
61
+ init_deferred_after_perform_callbacks
55
62
  end
56
63
 
57
64
  # Call the {#interactor_class} {Interactor::Perform::ClassMethods#perform .perform} or
@@ -69,6 +76,8 @@ module ActiveInteractor
69
76
  return if check_conditionals(target, :if) == false
70
77
  return if check_conditionals(target, :unless) == true
71
78
 
79
+ skip_deferred_after_perform_callbacks
80
+
72
81
  method = fail_on_error ? :perform! : :perform
73
82
  options = self.perform_options.merge(perform_options)
74
83
  interactor_class.send(method, context, options)
@@ -78,8 +87,31 @@ module ActiveInteractor
78
87
  resolve_option(target, callbacks[callback])
79
88
  end
80
89
 
90
+ def execute_deferred_after_perform_callbacks(context)
91
+ return unless deferred_after_perform_callbacks.present?
92
+
93
+ interactor = interactor_class.new(context)
94
+ env = ActiveSupport::Callbacks::Filters::Environment.new(interactor, false, nil)
95
+ deferred_after_perform_callbacks.compile.invoke_after(env)
96
+ interactor.send(:context)
97
+ end
98
+
81
99
  private
82
100
 
101
+ def init_deferred_after_perform_callbacks
102
+ after_callbacks_deferred = interactor_class.present? &&
103
+ interactor_class.after_callbacks_deferred_when_organized
104
+ @deferred_after_perform_callbacks = after_callbacks_deferred ? interactor_class._perform_callbacks : nil
105
+ end
106
+
107
+ def skip_deferred_after_perform_callbacks
108
+ return unless deferred_after_perform_callbacks.present?
109
+
110
+ deferred_after_perform_callbacks.each do |callback|
111
+ interactor_class.skip_callback(:perform, :after, callback.filter, raise: false)
112
+ end
113
+ end
114
+
83
115
  def check_conditionals(target, filter)
84
116
  resolve_option(target, filters[filter])
85
117
  end
@@ -46,11 +46,14 @@ module ActiveInteractor
46
46
  # {Interactor::Perform#perform #perform}. An {Base organizer} is expected not to define its own
47
47
  # {Interactor::Perform#perform #perform} method in favor of this default implementation.
48
48
  def perform
49
- if self.class.parallel
50
- perform_in_parallel
51
- else
52
- perform_in_order
49
+ run_callbacks :all_perform do
50
+ if self.class.parallel
51
+ perform_in_parallel
52
+ else
53
+ perform_in_order
54
+ end
53
55
  end
56
+ run_after_perform_callbacks_on_interactors if context.success?
54
57
  end
55
58
 
56
59
  private
@@ -97,6 +100,14 @@ module ActiveInteractor
97
100
  end
98
101
  merge_contexts(results.map(&:value))
99
102
  end
103
+
104
+ def run_after_perform_callbacks_on_interactors
105
+ self.class.organized.each do |interface|
106
+ next unless interface.interactor_class.after_callbacks_deferred_when_organized
107
+
108
+ context.merge!(interface.execute_deferred_after_perform_callbacks(context))
109
+ end
110
+ end
100
111
  end
101
112
  end
102
113
  end
@@ -12,11 +12,11 @@ module ActiveInteractor
12
12
 
13
13
  # The ActiveInterctor minor version number
14
14
  # @return [Integer] The ActiveInteractor minor version number
15
- MINOR = 1
15
+ MINOR = 2
16
16
 
17
17
  # The ActiveInterctor patch version number
18
18
  # @return [Integer] The ActiveInteractor patch version number
19
- PATCH = 6
19
+ PATCH = 0
20
20
 
21
21
  # The ActiveInterctor pre-release version
22
22
  # @return [String | nil] The ActiveInteractor pre-release version
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'An interactor with deferred after callbacks', type: :integration do
6
+ let!(:interactor_with_config) do
7
+ build_interactor('InteractorWithConfig') do
8
+ defer_after_callbacks_when_organized
9
+
10
+ def perform
11
+ context.test_field_1 = 'test'
12
+ end
13
+ end
14
+ end
15
+
16
+ let!(:interactor_without_config) do
17
+ build_interactor('InteractorWithoutConfig') do
18
+
19
+ def perform
20
+ context.test_field_2 = 'test'
21
+ end
22
+ end
23
+ end
24
+
25
+ it 'is expected to have true for InteractorWithConfig#after_callbacks_deferred_when_organized' do
26
+ expect(InteractorWithConfig).to have_attributes(after_callbacks_deferred_when_organized: true)
27
+ end
28
+
29
+ it 'is expected to have false for InteractorWithoutConfig#after_callbacks_deferred_when_organized' do
30
+ expect(InteractorWithoutConfig).to have_attributes(after_callbacks_deferred_when_organized: false)
31
+ end
32
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'An organizer containing an organizer with after callbacks deferred', type: :integration do
6
+ let!(:test_interactor_1) do
7
+ build_interactor('TestInteractor1') do
8
+ defer_after_callbacks_when_organized
9
+
10
+ after_perform do
11
+ context.after_perform_1a = context.after_perform_1b + 1
12
+ end
13
+
14
+ after_perform do
15
+ context.after_perform_1b = context.after_perform_2 + 1
16
+ end
17
+
18
+ def perform
19
+ context.perform_1 = 1
20
+ end
21
+ end
22
+ end
23
+
24
+ let!(:test_interactor_2) do
25
+ build_interactor('TestInteractor2') do
26
+ after_perform do
27
+ context.after_perform_2 = context.perform_2 + 1
28
+ end
29
+
30
+ def perform
31
+ context.perform_2 = context.after_perform_3a + 1
32
+ end
33
+ end
34
+ end
35
+
36
+ let!(:test_interactor_3) do
37
+ build_interactor('TestInteractor3') do
38
+ defer_after_callbacks_when_organized
39
+
40
+ after_perform do
41
+ context.after_perform_3a = context.after_perform_3b + 1
42
+ end
43
+
44
+ after_perform do
45
+ context.after_perform_3b = context.after_perform_4a + 1
46
+ end
47
+
48
+ def perform
49
+ context.perform_3 = context.perform_1 + 1
50
+ end
51
+ end
52
+ end
53
+
54
+ let!(:test_interactor_4) do
55
+ build_interactor('TestInteractor4') do
56
+ after_perform do
57
+ context.after_perform_4a = context.after_perform_4b + 1
58
+ end
59
+
60
+ after_perform do
61
+ context.after_perform_4b = context.perform_4 + 1
62
+ end
63
+
64
+ def perform
65
+ context.perform_4 = context.perform_3 + 1
66
+ end
67
+ end
68
+ end
69
+
70
+ let!(:test_sub_organizer_5) do
71
+ build_organizer('TestSubOrganizer5') do
72
+ defer_after_callbacks_when_organized
73
+
74
+ after_perform do
75
+ context.after_perform_5a = context.after_perform_5b + 1
76
+ end
77
+
78
+ after_perform do
79
+ context.after_perform_5b = context.after_perform_1a + 1
80
+ end
81
+
82
+ organize TestInteractor3, TestInteractor4
83
+ end
84
+ end
85
+
86
+ let(:interactor_class) do
87
+ build_organizer do
88
+ organize TestInteractor1, TestSubOrganizer5, TestInteractor2
89
+ end
90
+ end
91
+
92
+ include_examples 'a class with interactor methods'
93
+ include_examples 'a class with interactor callback methods'
94
+ include_examples 'a class with interactor context methods'
95
+ include_examples 'a class with organizer callback methods'
96
+
97
+ describe '.context_class' do
98
+ subject { interactor_class.context_class }
99
+
100
+ it { is_expected.to eq TestOrganizer::Context }
101
+ it { is_expected.to be < ActiveInteractor::Context::Base }
102
+ end
103
+
104
+ describe '.perform' do
105
+ subject { interactor_class.perform }
106
+
107
+ it { is_expected.to be_a interactor_class.context_class }
108
+ it { is_expected.to be_successful }
109
+ it { is_expected.to have_attributes(
110
+ perform_1: 1,
111
+ perform_3: 2,
112
+ perform_4: 3,
113
+ after_perform_4b: 4,
114
+ after_perform_4a: 5,
115
+ after_perform_3b: 6,
116
+ after_perform_3a: 7,
117
+ perform_2: 8,
118
+ after_perform_2: 9,
119
+ after_perform_1b: 10,
120
+ after_perform_1a: 11,
121
+ after_perform_5b: 12,
122
+ after_perform_5a: 13,
123
+ ) }
124
+ end
125
+ end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'An organizer with after callbacks deferred', type: :integration do
6
+ let!(:test_interactor_1) do
7
+ build_interactor('TestInteractor1') do
8
+ defer_after_callbacks_when_organized
9
+
10
+ after_perform do
11
+ context.after_perform_1a = context.after_perform_1b + 1
12
+ end
13
+
14
+ after_perform do
15
+ context.after_perform_1b = context.after_perform_3a + 1
16
+ end
17
+
18
+ def perform
19
+ context.perform_1 = 1
20
+ end
21
+ end
22
+ end
23
+
24
+ let!(:test_interactor_2) do
25
+ build_interactor('TestInteractor2') do
26
+ defer_after_callbacks_when_organized
27
+
28
+ after_perform do
29
+ context.after_perform_2 = context.after_perform_1a + 1
30
+ end
31
+
32
+ def perform
33
+ context.perform_2 = context.perform_1 + 1
34
+ end
35
+ end
36
+ end
37
+
38
+ let!(:test_interactor_3) do
39
+ build_interactor('TestInteractor3') do
40
+ after_perform do
41
+ context.after_perform_3a = context.after_perform_3b + 1
42
+ end
43
+
44
+ after_perform do
45
+ context.after_perform_3b = context.perform_3 + 1
46
+ end
47
+
48
+ def perform
49
+ context.perform_3 = context.perform_2 + 1
50
+ end
51
+ end
52
+ end
53
+
54
+ let(:interactor_class) do
55
+ build_organizer do
56
+ organize TestInteractor1, TestInteractor2, TestInteractor3
57
+ end
58
+ end
59
+
60
+ include_examples 'a class with interactor methods'
61
+ include_examples 'a class with interactor callback methods'
62
+ include_examples 'a class with interactor context methods'
63
+ include_examples 'a class with organizer callback methods'
64
+
65
+ describe '.context_class' do
66
+ subject { interactor_class.context_class }
67
+
68
+ it { is_expected.to eq TestOrganizer::Context }
69
+ it { is_expected.to be < ActiveInteractor::Context::Base }
70
+ end
71
+
72
+ describe '.perform' do
73
+ subject { interactor_class.perform }
74
+
75
+ it { is_expected.to be_a interactor_class.context_class }
76
+ it { is_expected.to be_successful }
77
+ it { is_expected.to have_attributes(
78
+ perform_1: 1,
79
+ perform_2: 2,
80
+ perform_3: 3,
81
+ after_perform_3b: 4,
82
+ after_perform_3a: 5,
83
+ after_perform_1b: 6,
84
+ after_perform_1a: 7,
85
+ after_perform_2: 8,
86
+ ) }
87
+
88
+ context 'when last interactor fails' do
89
+ let!(:failing_interactor) do
90
+ build_interactor('FailingInteractor') do
91
+ def perform
92
+ context.fail!
93
+ end
94
+ end
95
+ end
96
+
97
+ let(:interactor_class) do
98
+ build_organizer do
99
+ organize TestInteractor1, TestInteractor2, FailingInteractor
100
+ end
101
+ end
102
+
103
+ subject { interactor_class.perform}
104
+
105
+ it { is_expected.to have_attributes(
106
+ perform_1: 1,
107
+ perform_2: 2,
108
+ )}
109
+
110
+ it { is_expected.to_not respond_to(
111
+ :after_perform_1a,
112
+ :after_perform_1b,
113
+ )}
114
+ end
115
+
116
+ context 'when after_perform in first interactor fails' do
117
+ let!(:failing_interactor) do
118
+ build_interactor('FailingInteractor') do
119
+ defer_after_callbacks_when_organized
120
+
121
+ after_perform do
122
+ context.fail!
123
+ end
124
+
125
+ def perform
126
+ context.perform_1 = 1
127
+ end
128
+ end
129
+ end
130
+
131
+ let(:interactor_class) do
132
+ build_organizer do
133
+ organize FailingInteractor, TestInteractor2, TestInteractor3
134
+ end
135
+ end
136
+
137
+ subject { interactor_class.perform}
138
+
139
+ it { is_expected.to have_attributes(
140
+ perform_1: 1,
141
+ perform_2: 2,
142
+ perform_3: 3,
143
+ after_perform_3b: 4,
144
+ after_perform_3a: 5,
145
+ )}
146
+
147
+ it { is_expected.to_not respond_to(
148
+ :after_perform_1a,
149
+ :after_perform_1b,
150
+ :after_perform_2,
151
+ )}
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'An organizer with around all callbacks', type: :integration do
6
+ let!(:test_interactor_1) do
7
+ build_interactor('TestInteractor1') do
8
+ before_perform do
9
+ context.before_perform_1 = context.around_all_perform_start + 1
10
+ end
11
+
12
+ after_perform do
13
+ context.after_perform_1 = context.around_perform_1_end + 1
14
+ end
15
+
16
+ around_perform :around
17
+ def around
18
+ context.around_perform_1_start = context.before_perform_1 + 1
19
+ yield
20
+ context.around_perform_1_end = context.perform_1 + 1
21
+ end
22
+
23
+ def perform
24
+ context.perform_1 = context.around_perform_1_start + 1
25
+ end
26
+ end
27
+ end
28
+
29
+ let!(:test_interactor_2) do
30
+ build_interactor('TestInteractor2') do
31
+ defer_after_callbacks_when_organized
32
+
33
+ before_perform do
34
+ context.before_perform_2 = context.after_perform_1 + 1
35
+ end
36
+
37
+ after_perform do
38
+ context.after_perform_2 = context.after_all_perform + 1
39
+ end
40
+
41
+ around_perform :around
42
+ def around
43
+ context.around_perform_2_start = context.before_perform_2 + 1
44
+ yield
45
+ context.around_perform_2_end = context.perform_2 + 1
46
+ end
47
+
48
+ def perform
49
+ context.perform_2 = context.around_perform_2_start + 1
50
+ end
51
+ end
52
+ end
53
+
54
+ let(:interactor_class) do
55
+ build_organizer do
56
+ before_all_perform do
57
+ context.before_all_perform = 1
58
+ end
59
+
60
+ after_all_perform do
61
+ context.after_all_perform = context.around_all_perform_end + 1
62
+ end
63
+
64
+ around_all_perform :around_all
65
+ def around_all
66
+ context.around_all_perform_start = context.before_all_perform + 1
67
+ yield
68
+ context.around_all_perform_end = context.around_perform_2_end + 1
69
+ end
70
+
71
+ organize TestInteractor1, TestInteractor2
72
+ end
73
+ end
74
+
75
+ include_examples 'a class with interactor methods'
76
+ include_examples 'a class with interactor callback methods'
77
+ include_examples 'a class with interactor context methods'
78
+ include_examples 'a class with organizer callback methods'
79
+
80
+ describe '.context_class' do
81
+ subject { interactor_class.context_class }
82
+
83
+ it { is_expected.to eq TestOrganizer::Context }
84
+ it { is_expected.to be < ActiveInteractor::Context::Base }
85
+ end
86
+
87
+ describe '.perform' do
88
+ subject { interactor_class.perform }
89
+
90
+ it { is_expected.to be_a interactor_class.context_class }
91
+ it { is_expected.to be_successful }
92
+ it { is_expected.to have_attributes(
93
+ before_all_perform: 1,
94
+ around_all_perform_start: 2,
95
+
96
+ before_perform_1: 3,
97
+ around_perform_1_start: 4,
98
+ perform_1: 5,
99
+ around_perform_1_end: 6,
100
+ after_perform_1: 7,
101
+
102
+ before_perform_2: 8,
103
+ around_perform_2_start: 9,
104
+ perform_2: 10,
105
+ around_perform_2_end: 11,
106
+
107
+ around_all_perform_end: 12,
108
+ after_all_perform: 13,
109
+ after_perform_2: 14,
110
+ ) }
111
+ end
112
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeinteractor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Allen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-25 00:00:00.000000000 Z
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -17,9 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
- - - "<="
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 7.0.2.3
22
+ version: '8'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +27,9 @@ dependencies:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: '4.2'
30
- - - "<="
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 7.0.2.3
32
+ version: '8'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -37,9 +37,9 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '4.2'
40
- - - "<="
40
+ - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: 7.0.2.3
42
+ version: '8'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -47,23 +47,23 @@ dependencies:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '4.2'
50
- - - "<="
50
+ - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: 7.0.2.3
52
+ version: '8'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: bundler
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '2.0'
59
+ version: '2.3'
60
60
  type: :development
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '2.0'
66
+ version: '2.3'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: rake
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -84,14 +84,14 @@ dependencies:
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '3.9'
87
+ version: '3.11'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '3.9'
94
+ version: '3.11'
95
95
  description: |
96
96
  An implementation of the Command Pattern for Ruby with ActiveModel::Validations inspired by the interactor gem.
97
97
  Rich support for attributes, callbacks, and validations, and thread safe performance methods.
@@ -181,11 +181,15 @@ files:
181
181
  - spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb
182
182
  - spec/integration/an_interactor_with_before_perform_callbacks_spec.rb
183
183
  - spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb
184
+ - spec/integration/an_interactor_with_deferred_after_callbacks.rb
184
185
  - spec/integration/an_interactor_with_validations_on_called_spec.rb
185
186
  - spec/integration/an_interactor_with_validations_on_calling_spec.rb
186
187
  - spec/integration/an_interactor_with_validations_spec.rb
188
+ - spec/integration/an_organizer_containing_organizer_with_after_callbacks_deferred_spec.rb
187
189
  - spec/integration/an_organizer_performing_in_parallel_spec.rb
190
+ - spec/integration/an_organizer_with_after_callbacks_deferred_spec.rb
188
191
  - spec/integration/an_organizer_with_after_each_callbacks_spec.rb
192
+ - spec/integration/an_organizer_with_all_perform_callbacks.rb
189
193
  - spec/integration/an_organizer_with_around_each_callbacks_spec.rb
190
194
  - spec/integration/an_organizer_with_before_each_callbacks_spec.rb
191
195
  - spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb
@@ -205,10 +209,10 @@ licenses:
205
209
  - MIT
206
210
  metadata:
207
211
  bug_tracker_uri: https://github.com/aaronmallen/activeinteractor/issues
208
- changelog_uri: https://github.com/aaronmallen/activeinteractor/blob/v1.1.6/CHANGELOG.md
209
- documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.1.6
212
+ changelog_uri: https://github.com/aaronmallen/activeinteractor/blob/v1.2.0/CHANGELOG.md
213
+ documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.2.0
210
214
  hompage_uri: https://github.com/aaronmallen/activeinteractor
211
- source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.1.6
215
+ source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.2.0
212
216
  wiki_uri: https://github.com/aaronmallen/activeinteractor/wiki
213
217
  post_install_message:
214
218
  rdoc_options: []
@@ -230,45 +234,49 @@ signing_key:
230
234
  specification_version: 4
231
235
  summary: Ruby interactors with ActiveModel::Validations
232
236
  test_files:
233
- - spec/spec_helper.rb
234
- - spec/integration/an_organizer_with_after_each_callbacks_spec.rb
235
- - spec/integration/an_organizer_with_options_callbacks_spec.rb
236
- - spec/integration/an_interactor_with_before_perform_callbacks_spec.rb
237
- - spec/integration/an_organizer_performing_in_parallel_spec.rb
237
+ - spec/integration/an_interactor_with_deferred_after_callbacks.rb
238
+ - spec/integration/an_interactor_with_validations_spec.rb
239
+ - spec/integration/an_organizer_with_after_callbacks_deferred_spec.rb
238
240
  - spec/integration/an_organizer_with_before_each_callbacks_spec.rb
239
- - spec/integration/an_interactor_with_an_existing_context_class_spec.rb
240
- - spec/integration/an_organizer_with_failing_nested_organizer_spec.rb
241
+ - spec/integration/an_organizer_performing_in_parallel_spec.rb
241
242
  - spec/integration/an_organizer_with_around_each_callbacks_spec.rb
242
- - spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb
243
- - spec/integration/an_interactor_with_validations_on_called_spec.rb
244
- - spec/integration/an_interactor_with_validations_on_calling_spec.rb
245
- - spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb
246
- - spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb
247
- - spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb
248
- - spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb
249
- - spec/integration/a_failing_interactor_spec.rb
250
243
  - spec/integration/a_basic_interactor_spec.rb
251
- - spec/integration/an_interactor_with_validations_spec.rb
244
+ - spec/integration/an_interactor_with_an_existing_context_class_spec.rb
245
+ - spec/integration/an_interactor_with_validations_on_calling_spec.rb
246
+ - spec/integration/an_interactor_with_before_perform_callbacks_spec.rb
247
+ - spec/integration/an_organizer_with_options_callbacks_spec.rb
252
248
  - spec/integration/an_interactor_with_around_perform_callbacks_spec.rb
249
+ - spec/integration/an_organizer_with_all_perform_callbacks.rb
250
+ - spec/integration/an_organizer_containing_organizer_with_after_callbacks_deferred_spec.rb
251
+ - spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb
253
252
  - spec/integration/active_record_integration_spec.rb
253
+ - spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb
254
+ - spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb
255
+ - spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb
256
+ - spec/integration/an_interactor_with_validations_on_called_spec.rb
254
257
  - spec/integration/an_interactor_with_after_perform_callbacks_spec.rb
258
+ - spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb
259
+ - spec/integration/an_organizer_with_failing_nested_organizer_spec.rb
260
+ - spec/integration/a_failing_interactor_spec.rb
261
+ - spec/integration/an_organizer_with_after_each_callbacks_spec.rb
255
262
  - spec/integration/a_basic_organizer_spec.rb
256
- - spec/active_interactor_spec.rb
257
- - spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb
258
- - spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb
259
- - spec/support/shared_examples/a_class_with_interactor_methods_example.rb
260
- - spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb
261
- - spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb
262
- - spec/support/spec_helpers.rb
263
- - spec/support/coverage.rb
264
- - spec/support/helpers/factories.rb
265
- - spec/active_interactor/interactor/worker_spec.rb
266
- - spec/active_interactor/interactor/perform/options_spec.rb
267
- - spec/active_interactor/version_spec.rb
268
- - spec/active_interactor/organizer/interactor_interface_spec.rb
269
263
  - spec/active_interactor/organizer/interactor_interface_collection_spec.rb
270
264
  - spec/active_interactor/organizer/base_spec.rb
265
+ - spec/active_interactor/organizer/interactor_interface_spec.rb
271
266
  - spec/active_interactor/config_spec.rb
267
+ - spec/active_interactor/base_spec.rb
272
268
  - spec/active_interactor/context/base_spec.rb
273
269
  - spec/active_interactor/error_spec.rb
274
- - spec/active_interactor/base_spec.rb
270
+ - spec/active_interactor/interactor/worker_spec.rb
271
+ - spec/active_interactor/interactor/perform/options_spec.rb
272
+ - spec/active_interactor/version_spec.rb
273
+ - spec/support/helpers/factories.rb
274
+ - spec/support/spec_helpers.rb
275
+ - spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb
276
+ - spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb
277
+ - spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb
278
+ - spec/support/shared_examples/a_class_with_interactor_methods_example.rb
279
+ - spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb
280
+ - spec/support/coverage.rb
281
+ - spec/active_interactor_spec.rb
282
+ - spec/spec_helper.rb