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
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ApplicationOrganizer < ActiveInteractor::Organizer
4
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- begin
5
- require 'active_interactor/rails'
6
-
7
- RSpec.describe ActiveInteractor::Rails::Config do
8
- subject { described_class.new }
9
-
10
- it { is_expected.to respond_to :directory }
11
- it { is_expected.to respond_to :generate_context_classes }
12
-
13
- describe '.defaults' do
14
- subject { described_class.defaults }
15
-
16
- it 'is expected to have attributes :directory => "interactors"' do
17
- expect(subject[:directory]).to eq 'interactors'
18
- end
19
-
20
- it 'is expected to have attributes :generate_context_classes => true' do
21
- expect(subject[:generate_context_classes]).to eq true
22
- end
23
- end
24
- end
25
- rescue LoadError
26
- RSpec.describe 'ActiveInteractor::Rails::Config' do
27
- pending 'Rails not found skipping specs...'
28
- end
29
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- begin
5
- require 'active_interactor/rails'
6
-
7
- RSpec.describe ActiveInteractor::Rails do
8
- describe '.config' do
9
- subject { described_class.config }
10
-
11
- it { is_expected.to be_a ActiveInteractor::Rails::Config }
12
- end
13
-
14
- describe '.configure' do
15
- it 'is expected to yield config' do
16
- expect { |b| described_class.configure(&b) }.to yield_control
17
- end
18
- end
19
- end
20
- rescue LoadError
21
- RSpec.describe 'ActiveInteractor::Rails' do
22
- pending 'Rails not found skipping specs...'
23
- end
24
- end
@@ -1,355 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe 'Basic Callback Integration', type: :integration do
6
- describe 'An interactor with after context validation callbacks' do
7
- let(:interactor_class) do
8
- build_interactor do
9
- context_validates :test_field, presence: true
10
- after_context_validation :downcase_test_field
11
-
12
- private
13
-
14
- def downcase_test_field
15
- context.test_field = context.test_field.downcase
16
- end
17
- end
18
- end
19
-
20
- include_examples 'a class with interactor methods'
21
- include_examples 'a class with interactor callback methods'
22
- include_examples 'a class with interactor context methods'
23
-
24
- describe '.perform' do
25
- subject { interactor_class.perform(context_attributes) }
26
-
27
- context 'with valid context attributes' do
28
- let(:context_attributes) { { test_field: 'TEST' } }
29
-
30
- it { is_expected.to be_a interactor_class.context_class }
31
- it { is_expected.to be_successful }
32
- it { is_expected.to have_attributes(test_field: 'test') }
33
- end
34
- end
35
- end
36
-
37
- describe 'An interactor with conditional after context validation callbacks' do
38
- let(:interactor_class) do
39
- build_interactor do
40
- context_validates :test_field, presence: true
41
- after_context_validation :downcase_test_field, if: -> { context.should_downcase }
42
-
43
- private
44
-
45
- def downcase_test_field
46
- context.test_field = context.test_field.downcase
47
- end
48
- end
49
- end
50
-
51
- include_examples 'a class with interactor methods'
52
- include_examples 'a class with interactor callback methods'
53
- include_examples 'a class with interactor context methods'
54
-
55
- describe '.perform' do
56
- subject { interactor_class.perform(context_attributes) }
57
-
58
- context 'with :test_field "TEST" and :should_downcase true' do
59
- let(:context_attributes) { { test_field: 'TEST', should_downcase: true } }
60
-
61
- it { is_expected.to be_a interactor_class.context_class }
62
- it { is_expected.to be_successful }
63
- it { is_expected.to have_attributes(test_field: 'test') }
64
- end
65
-
66
- context 'with :test_field "TEST" and :should_downcase false' do
67
- let(:context_attributes) { { test_field: 'TEST', should_downcase: false } }
68
-
69
- it { is_expected.to be_a interactor_class.context_class }
70
- it { is_expected.to be_successful }
71
- it { is_expected.to have_attributes(test_field: 'TEST') }
72
- end
73
- end
74
- end
75
-
76
- describe 'An interactor with after perform callbacks' do
77
- let(:interactor_class) do
78
- build_interactor do
79
- after_perform :test_after_perform
80
-
81
- private
82
-
83
- def test_after_perform; end
84
- end
85
- end
86
-
87
- include_examples 'a class with interactor methods'
88
- include_examples 'a class with interactor callback methods'
89
- include_examples 'a class with interactor context methods'
90
-
91
- describe '.perform' do
92
- subject { interactor_class.perform }
93
-
94
- it { is_expected.to be_a interactor_class.context_class }
95
- it { is_expected.to be_successful }
96
- it 'is expected to call #test_after_perform' do
97
- expect_any_instance_of(interactor_class).to receive(:test_after_perform)
98
- subject
99
- end
100
- end
101
- end
102
-
103
- describe 'An interactor with after rollback callbacks' do
104
- let(:interactor_class) do
105
- build_interactor do
106
- after_rollback :test_after_rollback
107
-
108
- def perform
109
- context.fail!
110
- end
111
-
112
- private
113
-
114
- def test_after_rollback; end
115
- end
116
- end
117
-
118
- include_examples 'a class with interactor methods'
119
- include_examples 'a class with interactor callback methods'
120
- include_examples 'a class with interactor context methods'
121
-
122
- describe '.perform' do
123
- subject { interactor_class.perform }
124
-
125
- it { is_expected.to be_a interactor_class.context_class }
126
- it 'is expected to call #test_after_rollback' do
127
- expect_any_instance_of(interactor_class).to receive(:test_after_rollback)
128
- subject
129
- end
130
- end
131
- end
132
-
133
- describe 'An interactor with around perform callbacks' do
134
- let(:interactor_class) do
135
- build_interactor do
136
- around_perform :test_around_perform
137
-
138
- def perform
139
- context.perform_step << 2
140
- end
141
-
142
- private
143
-
144
- def test_around_perform
145
- context.perform_step = []
146
- context.perform_step << 1
147
- yield
148
- context.perform_step << 3
149
- end
150
- end
151
- end
152
-
153
- include_examples 'a class with interactor methods'
154
- include_examples 'a class with interactor callback methods'
155
- include_examples 'a class with interactor context methods'
156
-
157
- describe '.perform' do
158
- subject { interactor_class.perform }
159
-
160
- it { is_expected.to be_a interactor_class.context_class }
161
- it { is_expected.to have_attributes(perform_step: [1, 2, 3]) }
162
- end
163
- end
164
-
165
- describe 'An interactor with around rollback callbacks' do
166
- let(:interactor_class) do
167
- build_interactor do
168
- around_rollback :test_around_rollback
169
-
170
- def perform
171
- context.fail!
172
- end
173
-
174
- def rollback
175
- context.rollback_step << 2
176
- end
177
-
178
- private
179
-
180
- def test_around_rollback
181
- context.rollback_step = []
182
- context.rollback_step << 1
183
- yield
184
- context.rollback_step << 3
185
- end
186
- end
187
- end
188
-
189
- include_examples 'a class with interactor methods'
190
- include_examples 'a class with interactor callback methods'
191
- include_examples 'a class with interactor context methods'
192
-
193
- describe '.perform' do
194
- subject { interactor_class.perform }
195
-
196
- it { is_expected.to be_a interactor_class.context_class }
197
- it { is_expected.to have_attributes(rollback_step: [1, 2, 3]) }
198
- end
199
- end
200
-
201
- describe 'An interactor with before perform callbacks' do
202
- let(:interactor_class) do
203
- build_interactor do
204
- before_perform :test_before_perform
205
-
206
- private
207
-
208
- def test_before_perform; end
209
- end
210
- end
211
-
212
- include_examples 'a class with interactor methods'
213
- include_examples 'a class with interactor callback methods'
214
- include_examples 'a class with interactor context methods'
215
-
216
- describe '.perform' do
217
- subject { interactor_class.perform }
218
-
219
- it { is_expected.to be_a interactor_class.context_class }
220
- it { is_expected.to be_successful }
221
- it 'is expected to call #test_before_perform' do
222
- expect_any_instance_of(interactor_class).to receive(:test_before_perform)
223
- subject
224
- end
225
- end
226
- end
227
-
228
- describe 'An interactor with before rollback callbacks' do
229
- let(:interactor_class) do
230
- build_interactor do
231
- before_rollback :test_before_rollback
232
-
233
- def perform
234
- context.fail!
235
- end
236
-
237
- private
238
-
239
- def test_before_rollback; end
240
- end
241
- end
242
-
243
- include_examples 'a class with interactor methods'
244
- include_examples 'a class with interactor callback methods'
245
- include_examples 'a class with interactor context methods'
246
-
247
- describe '.perform' do
248
- subject { interactor_class.perform }
249
-
250
- it { is_expected.to be_a interactor_class.context_class }
251
- it 'is expected to call #test_before_rollback' do
252
- expect_any_instance_of(interactor_class).to receive(:test_before_rollback)
253
- subject
254
- end
255
- end
256
- end
257
-
258
- describe 'An organizer with after each callbacks' do
259
- let!(:interactor1) { build_interactor('TestInteractor1') }
260
- let!(:interactor2) { build_interactor('TestInteractor2') }
261
- let(:interactor_class) do
262
- build_organizer do
263
- after_each_perform :test_after_each_perform
264
- organize TestInteractor1, TestInteractor2
265
-
266
- private
267
-
268
- def test_after_each_perform; end
269
- end
270
- end
271
-
272
- include_examples 'a class with interactor methods'
273
- include_examples 'a class with interactor callback methods'
274
- include_examples 'a class with interactor context methods'
275
- include_examples 'a class with organizer callback methods'
276
-
277
- describe '.perform' do
278
- subject { interactor_class.perform }
279
-
280
- it { is_expected.to be_a interactor_class.context_class }
281
- it 'is expected to call #test_after_each_perform twice' do
282
- expect_any_instance_of(interactor_class).to receive(:test_after_each_perform)
283
- .exactly(:twice)
284
- subject
285
- end
286
- end
287
- end
288
-
289
- describe 'An organizer with around each callbacks' do
290
- let!(:interactor1) { build_interactor('TestInteractor1') }
291
- let!(:interactor2) { build_interactor('TestInteractor2') }
292
- let(:interactor_class) do
293
- build_organizer do
294
- around_each_perform :test_around_each_perform
295
- organize TestInteractor1, TestInteractor2
296
-
297
- private
298
-
299
- def find_index
300
- (context.around_each_step.last || 0) + 1
301
- end
302
-
303
- def test_around_each_perform
304
- context.around_each_step ||= []
305
- context.around_each_step << find_index
306
- yield
307
- context.around_each_step << find_index
308
- end
309
- end
310
- end
311
-
312
- include_examples 'a class with interactor methods'
313
- include_examples 'a class with interactor callback methods'
314
- include_examples 'a class with interactor context methods'
315
- include_examples 'a class with organizer callback methods'
316
-
317
- describe '.perform' do
318
- subject { interactor_class.perform }
319
-
320
- it { is_expected.to be_a interactor_class.context_class }
321
- it { is_expected.to have_attributes(around_each_step: [1, 2, 3, 4]) }
322
- end
323
- end
324
-
325
- describe 'An organizer with before each callbacks' do
326
- let!(:interactor1) { build_interactor('TestInteractor1') }
327
- let!(:interactor2) { build_interactor('TestInteractor2') }
328
- let(:interactor_class) do
329
- build_organizer do
330
- before_each_perform :test_before_each_perform
331
- organize TestInteractor1, TestInteractor2
332
-
333
- private
334
-
335
- def test_before_each_perform; end
336
- end
337
- end
338
-
339
- include_examples 'a class with interactor methods'
340
- include_examples 'a class with interactor callback methods'
341
- include_examples 'a class with interactor context methods'
342
- include_examples 'a class with organizer callback methods'
343
-
344
- describe '.perform' do
345
- subject { interactor_class.perform }
346
-
347
- it { is_expected.to be_a interactor_class.context_class }
348
- it 'is expected to call #test_before_each_perform twice' do
349
- expect_any_instance_of(interactor_class).to receive(:test_before_each_perform)
350
- .exactly(:twice)
351
- subject
352
- end
353
- end
354
- end
355
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe 'Basic Context Integration', type: :integration do
6
- describe 'An interactor with context attributes' do
7
- let(:interactor_class) do
8
- build_interactor do
9
- context_attributes :test_field
10
-
11
- def perform
12
- context.test_field = 'test'
13
- context.some_other_field = 'test 2'
14
- end
15
- end
16
- end
17
-
18
- include_examples 'a class with interactor methods'
19
- include_examples 'a class with interactor callback methods'
20
- include_examples 'a class with interactor context methods'
21
-
22
- describe '.perform' do
23
- subject(:result) { interactor_class.perform }
24
-
25
- it { is_expected.to be_a interactor_class.context_class }
26
- it { is_expected.to be_successful }
27
- it { is_expected.to have_attributes(test_field: 'test', some_other_field: 'test 2') }
28
-
29
- describe '.attributes' do
30
- subject { result.attributes }
31
-
32
- it { is_expected.to eq(test_field: 'test') }
33
- end
34
- end
35
- end
36
-
37
- describe 'An interactor with a defined context class named "AnInteractor"' do
38
- let(:interactor_class) { build_interactor('AnInteractor') }
39
- let!(:context_class) { build_context('AnInteractorContext') }
40
-
41
- include_examples 'a class with interactor methods'
42
- include_examples 'a class with interactor callback methods'
43
- include_examples 'a class with interactor context methods'
44
-
45
- describe '.context_class' do
46
- subject { interactor_class.context_class }
47
-
48
- it { is_expected.to eq AnInteractorContext }
49
- it { is_expected.to be < ActiveInteractor::Context::Base }
50
- end
51
- end
52
-
53
- describe 'An interactor contextualized with ATestContext' do
54
- let(:interactor_class) do
55
- build_interactor do
56
- contextualize_with :a_test_context
57
- end
58
- end
59
-
60
- let!(:context_class) { build_context('ATestContext') }
61
-
62
- include_examples 'a class with interactor methods'
63
- include_examples 'a class with interactor callback methods'
64
- include_examples 'a class with interactor context methods'
65
-
66
- describe '.context_class' do
67
- subject { interactor_class.context_class }
68
-
69
- it { is_expected.to eq ATestContext }
70
- it { is_expected.to be < ActiveInteractor::Context::Base }
71
- end
72
- end
73
- end