activeinteractor 1.1.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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