active_interaction 5.2.0 → 5.4.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +11 -12
  4. data/lib/active_interaction/base.rb +2 -0
  5. data/lib/active_interaction/errors.rb +16 -16
  6. data/lib/active_interaction/filters/hash_filter.rb +5 -1
  7. data/lib/active_interaction/version.rb +1 -1
  8. metadata +26 -112
  9. data/spec/active_interaction/array_input_spec.rb +0 -166
  10. data/spec/active_interaction/base_spec.rb +0 -537
  11. data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -45
  12. data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -49
  13. data/spec/active_interaction/concerns/hashable_spec.rb +0 -46
  14. data/spec/active_interaction/concerns/missable_spec.rb +0 -99
  15. data/spec/active_interaction/concerns/runnable_spec.rb +0 -397
  16. data/spec/active_interaction/errors_spec.rb +0 -196
  17. data/spec/active_interaction/filter/column_spec.rb +0 -87
  18. data/spec/active_interaction/filter_spec.rb +0 -60
  19. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -13
  20. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -13
  21. data/spec/active_interaction/filters/array_filter_spec.rb +0 -250
  22. data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -87
  23. data/spec/active_interaction/filters/date_filter_spec.rb +0 -178
  24. data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -189
  25. data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -126
  26. data/spec/active_interaction/filters/file_filter_spec.rb +0 -40
  27. data/spec/active_interaction/filters/float_filter_spec.rb +0 -110
  28. data/spec/active_interaction/filters/hash_filter_spec.rb +0 -129
  29. data/spec/active_interaction/filters/integer_filter_spec.rb +0 -104
  30. data/spec/active_interaction/filters/interface_filter_spec.rb +0 -461
  31. data/spec/active_interaction/filters/object_filter_spec.rb +0 -237
  32. data/spec/active_interaction/filters/record_filter_spec.rb +0 -206
  33. data/spec/active_interaction/filters/string_filter_spec.rb +0 -60
  34. data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -46
  35. data/spec/active_interaction/filters/time_filter_spec.rb +0 -251
  36. data/spec/active_interaction/grouped_input_spec.rb +0 -17
  37. data/spec/active_interaction/hash_input_spec.rb +0 -58
  38. data/spec/active_interaction/i18n_spec.rb +0 -113
  39. data/spec/active_interaction/inputs_spec.rb +0 -266
  40. data/spec/active_interaction/integration/array_interaction_spec.rb +0 -88
  41. data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -5
  42. data/spec/active_interaction/integration/date_interaction_spec.rb +0 -5
  43. data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -5
  44. data/spec/active_interaction/integration/file_interaction_spec.rb +0 -18
  45. data/spec/active_interaction/integration/float_interaction_spec.rb +0 -5
  46. data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -76
  47. data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -5
  48. data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -19
  49. data/spec/active_interaction/integration/object_interaction_spec.rb +0 -14
  50. data/spec/active_interaction/integration/record_integration_spec.rb +0 -5
  51. data/spec/active_interaction/integration/string_interaction_spec.rb +0 -5
  52. data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -5
  53. data/spec/active_interaction/integration/time_interaction_spec.rb +0 -88
  54. data/spec/active_interaction/modules/validation_spec.rb +0 -57
  55. data/spec/spec_helper.rb +0 -20
  56. data/spec/support/concerns.rb +0 -13
  57. data/spec/support/filters.rb +0 -227
  58. data/spec/support/interactions.rb +0 -124
@@ -1,461 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module InterfaceModule; end
4
-
5
- class InterfaceClass; end # rubocop:disable Lint/EmptyClass
6
-
7
- describe ActiveInteraction::InterfaceFilter, :filter do
8
- include_context 'filters'
9
- it_behaves_like 'a filter' do
10
- let(:name) { :interface_module }
11
- end
12
-
13
- describe '#process' do
14
- let(:result) { filter.process(value, nil) }
15
-
16
- context 'with an implicit constant name' do
17
- context 'passed an instance' do
18
- context 'with the module included' do
19
- let(:name) { :interface_module }
20
- let(:value) do
21
- Class.new do
22
- include InterfaceModule
23
- end.new
24
- end
25
-
26
- it 'returns a the value' do
27
- expect(result.value).to eql value
28
- end
29
- end
30
-
31
- context 'with the class inherited from' do
32
- let(:name) { :interface_class }
33
- let(:value) do
34
- Class.new(InterfaceClass) {}.new # rubocop:disable Lint/EmptyBlock
35
- end
36
-
37
- it 'returns a the value' do
38
- expect(result.value).to eql value
39
- end
40
- end
41
-
42
- context 'that is extended by the ancestor' do
43
- let(:name) { :interface_module }
44
- let(:value) do
45
- Class.new {}.new.extend(InterfaceModule) # rubocop:disable Lint/EmptyBlock
46
- end
47
-
48
- it 'returns a the value' do
49
- expect(result.value).to eql value
50
- end
51
- end
52
-
53
- context 'that does not match' do
54
- let(:name) { :interface_module }
55
- let(:value) { Class.new }
56
-
57
- it 'indicates an error' do
58
- error = result.errors.first
59
-
60
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
61
- expect(error.type).to be :invalid_type
62
- end
63
- end
64
-
65
- context 'that is nil' do
66
- let(:name) { :interface_module }
67
- let(:value) { nil }
68
-
69
- it 'indicates an error' do
70
- error = result.errors.first
71
-
72
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
73
- expect(error.type).to be :missing
74
- end
75
- end
76
-
77
- context 'with the class itself' do
78
- let(:name) { :interface_class }
79
- let(:value) do
80
- InterfaceClass.new
81
- end
82
-
83
- it 'indicates an error' do
84
- error = result.errors.first
85
-
86
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
87
- expect(error.type).to be :invalid_type
88
- end
89
- end
90
- end
91
-
92
- context 'passed a class' do
93
- context 'with the class inherited from' do
94
- let(:name) { :interface_class }
95
- let(:value) do
96
- Class.new(InterfaceClass) {} # rubocop:disable Lint/EmptyBlock
97
- end
98
-
99
- it 'returns a the value' do
100
- expect(result.value).to eql value
101
- end
102
- end
103
-
104
- context 'that is extended by the ancestor' do
105
- let(:name) { :interface_module }
106
- let(:value) do
107
- Class.new do
108
- extend InterfaceModule
109
- end
110
- end
111
-
112
- it 'returns a the value' do
113
- expect(result.value).to eql value
114
- end
115
- end
116
-
117
- context 'that does not match' do
118
- let(:name) { :interface_class }
119
- let(:value) { Class }
120
-
121
- it 'indicates an error' do
122
- error = result.errors.first
123
-
124
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
125
- expect(error.type).to be :invalid_type
126
- end
127
- end
128
-
129
- context 'with the class itself' do
130
- let(:name) { :interface_class }
131
- let(:value) { InterfaceClass }
132
-
133
- it 'indicates an error' do
134
- error = result.errors.first
135
-
136
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
137
- expect(error.type).to be :invalid_type
138
- end
139
- end
140
- end
141
-
142
- context 'passed a module' do
143
- context 'that is extended by the ancestor' do
144
- let(:name) { :interface_module }
145
- let(:value) do
146
- Module.new do
147
- extend InterfaceModule
148
- end
149
- end
150
-
151
- it 'returns a the value' do
152
- expect(result.value).to eql value
153
- end
154
- end
155
-
156
- context 'that does not match' do
157
- let(:name) { :interface_module }
158
- let(:value) { Module.new }
159
-
160
- it 'indicates an error' do
161
- error = result.errors.first
162
-
163
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
164
- expect(error.type).to be :invalid_type
165
- end
166
- end
167
-
168
- context 'with the module itself' do
169
- let(:name) { :interface_module }
170
- let(:value) { InterfaceModule }
171
-
172
- it 'indicates an error' do
173
- error = result.errors.first
174
-
175
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
176
- expect(error.type).to be :invalid_type
177
- end
178
- end
179
- end
180
-
181
- context 'given an invalid name' do
182
- let(:name) { :invalid }
183
- let(:value) { Object }
184
-
185
- it 'raises an error' do
186
- expect do
187
- result
188
- end.to raise_error ActiveInteraction::InvalidNameError
189
- end
190
- end
191
- end
192
-
193
- context 'with a constant given' do
194
- context 'passed an instance' do
195
- context 'with the module included' do
196
- before { options.merge!(from: :interface_module) }
197
-
198
- let(:value) do
199
- Class.new do
200
- include InterfaceModule
201
- end.new
202
- end
203
-
204
- it 'returns a the value' do
205
- expect(result.value).to eql value
206
- end
207
- end
208
-
209
- context 'with the class inherited from' do
210
- before { options.merge!(from: :interface_class) }
211
-
212
- let(:value) do
213
- Class.new(InterfaceClass) {}.new # rubocop:disable Lint/EmptyBlock
214
- end
215
-
216
- it 'returns a the value' do
217
- expect(result.value).to eql value
218
- end
219
- end
220
-
221
- context 'that is extended by the ancestor' do
222
- before { options.merge!(from: :interface_module) }
223
-
224
- let(:value) do
225
- Class.new {}.new.extend(InterfaceModule) # rubocop:disable Lint/EmptyBlock
226
- end
227
-
228
- it 'returns a the value' do
229
- expect(result.value).to eql value
230
- end
231
- end
232
-
233
- context 'that does not match' do
234
- let(:name) { :interface_class }
235
- let(:value) { Class.new }
236
-
237
- it 'indicates an error' do
238
- error = result.errors.first
239
-
240
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
241
- expect(error.type).to be :invalid_type
242
- end
243
- end
244
-
245
- context 'with the class itself' do
246
- let(:name) { :interface_class }
247
- let(:value) { InterfaceClass.new }
248
-
249
- it 'indicates an error' do
250
- error = result.errors.first
251
-
252
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
253
- expect(error.type).to be :invalid_type
254
- end
255
- end
256
- end
257
-
258
- context 'passed a class' do
259
- context 'with the class inherited from' do
260
- before { options.merge!(from: :interface_class) }
261
-
262
- let(:value) do
263
- Class.new(InterfaceClass) {} # rubocop:disable Lint/EmptyBlock
264
- end
265
-
266
- it 'returns a the value' do
267
- expect(result.value).to eql value
268
- end
269
- end
270
-
271
- context 'that is extended by the ancestor' do
272
- before { options.merge!(from: :interface_module) }
273
-
274
- let(:value) do
275
- Class.new do
276
- extend InterfaceModule
277
- end
278
- end
279
-
280
- it 'returns a the value' do
281
- expect(result.value).to eql value
282
- end
283
- end
284
-
285
- context 'that does not match' do
286
- let(:name) { :interface_class }
287
- let(:value) { Class }
288
-
289
- it 'indicates an error' do
290
- error = result.errors.first
291
-
292
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
293
- expect(error.type).to be :invalid_type
294
- end
295
- end
296
-
297
- context 'with the class itself' do
298
- let(:name) { :interface_class }
299
- let(:value) { InterfaceClass }
300
-
301
- it 'indicates an error' do
302
- error = result.errors.first
303
-
304
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
305
- expect(error.type).to be :invalid_type
306
- end
307
- end
308
- end
309
-
310
- context 'passed a module' do
311
- context 'that is extended by the ancestor' do
312
- before { options.merge!(from: :interface_module) }
313
-
314
- let(:value) do
315
- Module.new do
316
- extend InterfaceModule
317
- end
318
- end
319
-
320
- it 'returns a the value' do
321
- expect(result.value).to eql value
322
- end
323
- end
324
-
325
- context 'that does not match' do
326
- let(:name) { :interface_module }
327
- let(:value) { Module.new }
328
-
329
- it 'indicates an error' do
330
- error = result.errors.first
331
-
332
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
333
- expect(error.type).to be :invalid_type
334
- end
335
- end
336
-
337
- context 'with the module itself' do
338
- let(:name) { :interface_module }
339
- let(:value) { InterfaceModule }
340
-
341
- it 'indicates an error' do
342
- error = result.errors.first
343
-
344
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
345
- expect(error.type).to be :invalid_type
346
- end
347
- end
348
- end
349
-
350
- context 'given an invalid name' do
351
- before { options.merge!(from: :invalid) }
352
-
353
- let(:value) { Object }
354
-
355
- it 'raises an error' do
356
- expect do
357
- result
358
- end.to raise_error ActiveInteraction::InvalidNameError
359
- end
360
- end
361
- end
362
-
363
- context 'with methods passed' do
364
- before { options[:methods] = %i[dump load] }
365
-
366
- context 'passed an valid instance' do
367
- let(:value) do
368
- Class.new do
369
- def dump; end
370
-
371
- def load; end
372
- end.new
373
- end
374
-
375
- it 'returns a the value' do
376
- expect(result.value).to eql value
377
- end
378
- end
379
-
380
- context 'passed an invalid instance' do
381
- let(:value) { Class.new }
382
-
383
- it 'indicates an error' do
384
- error = result.errors.first
385
-
386
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
387
- expect(error.type).to be :invalid_type
388
- end
389
- end
390
-
391
- context 'passed a class' do
392
- let(:value) do
393
- Class.new do
394
- def self.dump; end
395
-
396
- def self.load; end
397
- end
398
- end
399
-
400
- it 'returns a the value' do
401
- expect(result.value).to eql value
402
- end
403
- end
404
-
405
- context 'passed an invalid class' do
406
- let(:value) { Class }
407
-
408
- it 'indicates an error' do
409
- error = result.errors.first
410
-
411
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
412
- expect(error.type).to be :invalid_type
413
- end
414
- end
415
-
416
- context 'passed a module' do
417
- let(:value) do
418
- Module.new do
419
- def self.dump; end
420
-
421
- def self.load; end
422
- end
423
- end
424
-
425
- it 'returns a the value' do
426
- expect(result.value).to eql value
427
- end
428
- end
429
-
430
- context 'passed an invalid module' do
431
- let(:value) { Module.new }
432
-
433
- it 'indicates an error' do
434
- error = result.errors.first
435
-
436
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
437
- expect(error.type).to be :invalid_type
438
- end
439
- end
440
- end
441
-
442
- context 'with from and methods passed' do
443
- before do
444
- options[:from] = :module
445
- options[:methods] = %i[dump load]
446
- end
447
-
448
- it 'raises an error' do
449
- expect do
450
- filter
451
- end.to raise_error ActiveInteraction::InvalidFilterError
452
- end
453
- end
454
- end
455
-
456
- describe '#database_column_type' do
457
- it 'returns :string' do
458
- expect(filter.database_column_type).to be :string
459
- end
460
- end
461
- end
@@ -1,237 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class ObjectThing
4
- def self.converter(_)
5
- @converter ||= new
6
- end
7
-
8
- def self.converter_with_error(_)
9
- raise 'error'
10
- end
11
- end
12
-
13
- class ObjectThings; end # rubocop:disable Lint/EmptyClass
14
- BackupObjectThing = ObjectThing
15
-
16
- describe ActiveInteraction::ObjectFilter, :filter do
17
- include_context 'filters'
18
- before do
19
- options[:class] = ObjectThing
20
- end
21
-
22
- it_behaves_like 'a filter'
23
-
24
- describe '#process' do
25
- let(:value) { ObjectThing.new }
26
- let(:result) { filter.process(value, nil) }
27
-
28
- context 'with an instance of the class' do
29
- it 'returns the instance' do
30
- expect(result.value).to eql value
31
- end
32
-
33
- context 'with an instance that is a subclass' do
34
- let(:subclass) { Class.new(ObjectThing) }
35
- let(:value) { subclass.new }
36
-
37
- it 'returns the instance' do
38
- expect(result.value).to eql value
39
- end
40
- end
41
-
42
- it 'handles reconstantizing' do
43
- expect(result.value).to eql value
44
-
45
- Object.send(:remove_const, :ObjectThing)
46
- ObjectThing = BackupObjectThing # rubocop:disable Lint/ConstantDefinitionInBlock
47
- value = ObjectThing.new
48
-
49
- expect(filter.process(value, nil).value).to eql value
50
- end
51
-
52
- it 'handles reconstantizing subclasses' do
53
- filter
54
-
55
- Object.send(:remove_const, :ObjectThing)
56
- ObjectThing = BackupObjectThing # rubocop:disable Lint/ConstantDefinitionInBlock
57
- class SubObjectThing < ObjectThing; end # rubocop:disable Lint/ConstantDefinitionInBlock
58
- value = SubObjectThing.new
59
-
60
- expect(filter.process(value, nil).value).to eql value
61
- end
62
-
63
- context 'without the class available' do
64
- before { Object.send(:remove_const, :ObjectThing) }
65
-
66
- after { ObjectThing = BackupObjectThing } # rubocop:disable Lint/ConstantDefinitionInBlock
67
-
68
- it 'does not raise an error on initialization' do
69
- expect { filter }.to_not raise_error
70
- end
71
- end
72
- end
73
-
74
- context 'with class as a String' do
75
- before do
76
- options[:class] = ObjectThing.name
77
- end
78
-
79
- it 'returns the instance' do
80
- expect(result.value).to eql value
81
- end
82
- end
83
-
84
- context 'with a plural class' do
85
- let(:value) { ObjectThings.new }
86
-
87
- before { options[:class] = ObjectThings }
88
-
89
- it 'returns the instance' do
90
- expect(result.value).to eql value
91
- end
92
- end
93
-
94
- context 'with class as an invalid String' do
95
- before do
96
- options[:class] = 'invalid'
97
- end
98
-
99
- it 'raises an error' do
100
- expect do
101
- result
102
- end.to raise_error ActiveInteraction::InvalidNameError
103
- end
104
- end
105
-
106
- context 'with a converter' do
107
- let(:value) { '' }
108
-
109
- context 'that is a symbol' do
110
- before do
111
- options[:converter] = :converter
112
- end
113
-
114
- it 'calls the class method' do
115
- expect(result.value).to eql ObjectThing.converter(value)
116
- end
117
- end
118
-
119
- context 'that is a proc' do
120
- before do
121
- options[:converter] = ->(x) { ObjectThing.converter(x) }
122
- end
123
-
124
- it 'gets called' do
125
- expect(result.value).to eql ObjectThing.converter(value)
126
- end
127
- end
128
-
129
- context 'with an object of the correct class' do
130
- let(:value) { ObjectThing.new }
131
-
132
- it 'does not call the converter' do
133
- allow(ObjectThing).to receive(:converter)
134
- result.value
135
- expect(ObjectThing).to_not have_received(:converter)
136
- end
137
-
138
- it 'returns the correct value' do
139
- expect(result.value).to eql value
140
- end
141
- end
142
-
143
- context 'with an object that is a subclass' do
144
- let(:subclass) { Class.new(ObjectThing) }
145
- let(:value) { subclass.new }
146
-
147
- it 'does not call the converter' do
148
- allow(subclass).to receive(:converter)
149
- result.value
150
- expect(subclass).to_not have_received(:converter)
151
- end
152
-
153
- it 'returns the correct value' do
154
- expect(result.value).to eql value
155
- end
156
- end
157
-
158
- context 'with a nil value' do
159
- let(:value) { nil }
160
-
161
- include_context 'optional'
162
-
163
- it 'returns nil' do
164
- allow(ObjectThing).to receive(:converter)
165
- result.value
166
- expect(ObjectThing).to_not have_received(:converter)
167
- end
168
-
169
- it 'returns the correct value' do
170
- expect(result.value).to eql value
171
- end
172
- end
173
-
174
- context 'that is invalid' do
175
- before do
176
- options[:converter] = 'invalid converter'
177
- end
178
-
179
- it 'raises an error' do
180
- expect do
181
- result
182
- end.to raise_error ActiveInteraction::InvalidConverterError
183
- end
184
- end
185
-
186
- context 'that throws an error' do
187
- before do
188
- options[:converter] = :converter_with_error
189
- end
190
-
191
- it 'indicates an error' do
192
- error = result.errors.first
193
-
194
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
195
- expect(error.type).to be :invalid_type
196
- end
197
- end
198
-
199
- context 'that returns a nil' do
200
- let(:value) { '' }
201
-
202
- before do
203
- options[:default] = ObjectThing.new
204
- options[:converter] = ->(_) {}
205
- end
206
-
207
- it 'indicates an error' do
208
- error = filter.process(value, nil).errors.first
209
-
210
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
211
- expect(error.type).to be :invalid_type
212
- end
213
- end
214
-
215
- context 'that returns an invalid value' do
216
- let(:value) { '' }
217
-
218
- before do
219
- options[:converter] = ->(_) { 'invalid' }
220
- end
221
-
222
- it 'indicates an error' do
223
- error = filter.process(value, nil).errors.first
224
-
225
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
226
- expect(error.type).to be :invalid_type
227
- end
228
- end
229
- end
230
- end
231
-
232
- describe '#database_column_type' do
233
- it 'returns :string' do
234
- expect(filter.database_column_type).to be :string
235
- end
236
- end
237
- end