active_interaction 5.3.0 → 5.5.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +2 -2
  4. data/lib/active_interaction/errors.rb +1 -1
  5. data/lib/active_interaction/grouped_input.rb +23 -3
  6. data/lib/active_interaction/version.rb +1 -1
  7. metadata +12 -115
  8. data/spec/active_interaction/array_input_spec.rb +0 -164
  9. data/spec/active_interaction/base_spec.rb +0 -536
  10. data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -43
  11. data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -47
  12. data/spec/active_interaction/concerns/hashable_spec.rb +0 -44
  13. data/spec/active_interaction/concerns/missable_spec.rb +0 -97
  14. data/spec/active_interaction/concerns/runnable_spec.rb +0 -395
  15. data/spec/active_interaction/errors_spec.rb +0 -223
  16. data/spec/active_interaction/filter/column_spec.rb +0 -85
  17. data/spec/active_interaction/filter_spec.rb +0 -58
  18. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -11
  19. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -11
  20. data/spec/active_interaction/filters/array_filter_spec.rb +0 -248
  21. data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -85
  22. data/spec/active_interaction/filters/date_filter_spec.rb +0 -176
  23. data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -187
  24. data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -124
  25. data/spec/active_interaction/filters/file_filter_spec.rb +0 -38
  26. data/spec/active_interaction/filters/float_filter_spec.rb +0 -109
  27. data/spec/active_interaction/filters/hash_filter_spec.rb +0 -127
  28. data/spec/active_interaction/filters/integer_filter_spec.rb +0 -102
  29. data/spec/active_interaction/filters/interface_filter_spec.rb +0 -459
  30. data/spec/active_interaction/filters/object_filter_spec.rb +0 -235
  31. data/spec/active_interaction/filters/record_filter_spec.rb +0 -204
  32. data/spec/active_interaction/filters/string_filter_spec.rb +0 -58
  33. data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -44
  34. data/spec/active_interaction/filters/time_filter_spec.rb +0 -249
  35. data/spec/active_interaction/grouped_input_spec.rb +0 -15
  36. data/spec/active_interaction/hash_input_spec.rb +0 -56
  37. data/spec/active_interaction/i18n_spec.rb +0 -111
  38. data/spec/active_interaction/inputs_spec.rb +0 -264
  39. data/spec/active_interaction/integration/array_interaction_spec.rb +0 -87
  40. data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -11
  41. data/spec/active_interaction/integration/date_interaction_spec.rb +0 -3
  42. data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -3
  43. data/spec/active_interaction/integration/file_interaction_spec.rb +0 -17
  44. data/spec/active_interaction/integration/float_interaction_spec.rb +0 -3
  45. data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -106
  46. data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -3
  47. data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -18
  48. data/spec/active_interaction/integration/object_interaction_spec.rb +0 -12
  49. data/spec/active_interaction/integration/record_integration_spec.rb +0 -3
  50. data/spec/active_interaction/integration/string_interaction_spec.rb +0 -3
  51. data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -3
  52. data/spec/active_interaction/integration/time_interaction_spec.rb +0 -86
  53. data/spec/active_interaction/modules/validation_spec.rb +0 -55
  54. data/spec/spec_helper.rb +0 -22
  55. data/spec/support/concerns.rb +0 -13
  56. data/spec/support/filters.rb +0 -227
  57. data/spec/support/interactions.rb +0 -124
@@ -1,85 +0,0 @@
1
- RSpec.describe ActiveInteraction::Filter::Column do
2
- subject(:column) { described_class.intern(type) }
3
-
4
- let(:type) { :float }
5
-
6
- describe '.intern(type)' do
7
- it 'returns the same object for each type' do
8
- expect(described_class.intern(type)).to equal column
9
- end
10
-
11
- it 'returns different objects for different types' do
12
- expect(described_class.intern(:integer)).to_not equal column
13
- end
14
- end
15
-
16
- describe '.new(type)' do
17
- it 'is private' do
18
- expect { described_class.new(type) }.to raise_error NoMethodError
19
- end
20
- end
21
-
22
- describe '#limit' do
23
- it 'returns nil' do
24
- expect(column.limit).to be_nil
25
- end
26
- end
27
-
28
- describe '#type' do
29
- it 'returns the type' do
30
- expect(column.type).to eql type
31
- end
32
- end
33
-
34
- describe '#number?' do
35
- let(:number?) { column.number? }
36
-
37
- context 'type is' do
38
- context ':integer' do
39
- let(:type) { :integer }
40
-
41
- it 'returns true' do
42
- expect(number?).to be_truthy
43
- end
44
- end
45
-
46
- context ':float' do
47
- let(:type) { :float }
48
-
49
- it 'returns true' do
50
- expect(number?).to be_truthy
51
- end
52
- end
53
-
54
- context 'anything else' do
55
- let(:type) { :string }
56
-
57
- it 'returns false' do
58
- expect(number?).to be_falsey
59
- end
60
- end
61
- end
62
- end
63
-
64
- describe '#text?' do
65
- let(:text?) { column.text? }
66
-
67
- context 'type is' do
68
- context ':string' do
69
- let(:type) { :string }
70
-
71
- it 'returns true' do
72
- expect(text?).to be_truthy
73
- end
74
- end
75
-
76
- context 'anything else' do
77
- let(:type) { :float }
78
-
79
- it 'returns false' do
80
- expect(text?).to be_falsey
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,58 +0,0 @@
1
- RSpec.describe ActiveInteraction::Filter, :filter do
2
- include_context 'filters'
3
-
4
- describe '#database_column_type' do
5
- it 'returns `:string`' do
6
- expect(filter.database_column_type).to be :string
7
- end
8
- end
9
-
10
- context 'with an unregistered subclass' do
11
- let(:klass) { Class.new(described_class) }
12
-
13
- describe '.slug' do
14
- it 'is nil' do
15
- expect(klass.slug).to be_nil
16
- end
17
- end
18
- end
19
-
20
- context 'with a registered subclass' do
21
- let(:slug) { SecureRandom.hex.to_sym }
22
- let(:described_class) do
23
- s = slug
24
- Class.new(ActiveInteraction::Filter) do
25
- register s
26
- end
27
- end
28
-
29
- it_behaves_like 'a filter'
30
-
31
- describe '.slug' do
32
- it 'returns the registered slug' do
33
- expect(described_class.slug).to eql slug
34
- end
35
- end
36
- end
37
-
38
- describe '#default' do
39
- subject(:filter) { ActiveInteraction::IntegerFilter.new(:test, default: default) }
40
-
41
- context 'when it is a value' do
42
- let(:default) { 1 }
43
-
44
- it 'returns the default' do
45
- expect(filter.default).to be 1
46
- end
47
- end
48
-
49
- context 'when it is a proc' do
50
- let(:default) { -> { i + 1 } }
51
-
52
- it 'returns the default' do
53
- expect(filter.default(double(i: 0))).to be 1 # rubocop:disable RSpec/VerifiedDoubles
54
- expect(filter.default(double(i: 1))).to be 2 # rubocop:disable RSpec/VerifiedDoubles
55
- end
56
- end
57
- end
58
- end
@@ -1,11 +0,0 @@
1
- RSpec.describe ActiveInteraction::AbstractDateTimeFilter, :filter do
2
- include_context 'filters'
3
-
4
- describe '#process' do
5
- let(:value) { nil }
6
-
7
- it 'raises an error' do
8
- expect { filter.process(value, nil) }.to raise_error NameError
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- RSpec.describe ActiveInteraction::AbstractNumericFilter, :filter do
2
- include_context 'filters'
3
-
4
- describe '#process' do
5
- let(:value) { nil }
6
-
7
- it 'raises an error' do
8
- expect { filter.process(value, nil) }.to raise_error NameError
9
- end
10
- end
11
- end
@@ -1,248 +0,0 @@
1
- RSpec.describe ActiveInteraction::ArrayFilter, :filter do
2
- include_context 'filters'
3
- it_behaves_like 'a filter'
4
-
5
- context 'with multiple nested filters' do
6
- let(:block) do
7
- proc do
8
- array
9
- array
10
- end
11
- end
12
-
13
- it 'raises an error' do
14
- expect { filter }.to raise_error ActiveInteraction::InvalidFilterError
15
- end
16
- end
17
-
18
- context 'with a nested name' do
19
- let(:block) { proc { array :a } }
20
-
21
- it 'raises an error' do
22
- expect { filter }.to raise_error ActiveInteraction::InvalidFilterError
23
- end
24
- end
25
-
26
- describe '#process' do
27
- let(:result) { filter.process(value, nil) }
28
-
29
- context 'with an Array' do
30
- let(:value) { [] }
31
-
32
- it 'returns an ArrayInput' do
33
- expect(result).to be_an_instance_of ActiveInteraction::ArrayInput
34
- end
35
-
36
- it 'returns the Array' do
37
- expect(result.value).to eql value
38
- end
39
-
40
- it 'has no children' do
41
- expect(result.children).to eql []
42
- end
43
- end
44
-
45
- context 'with an implicit Array' do
46
- let(:value) do
47
- Class.new do
48
- def to_ary
49
- [1, 2, 3]
50
- end
51
- end.new
52
- end
53
-
54
- it 'returns the Array' do
55
- expect(result.value).to eql value.to_ary
56
- end
57
- end
58
-
59
- context 'with a heterogenous Array' do
60
- let(:value) { [[], false, 0.0, {}, 0, '', :''] }
61
-
62
- it 'returns the Array' do
63
- expect(result.value).to eql value
64
- end
65
- end
66
-
67
- context 'with a nested filter where the value transforms' do
68
- let(:block) { proc { symbol } }
69
- let(:name) { :test }
70
- let(:value) { ['test'] }
71
-
72
- it 'returns the transformed value' do
73
- expect(result.value).to eql [:test]
74
- end
75
-
76
- it 'does not modify the original value' do
77
- expect(result.value.object_id).to_not eql value.object_id
78
- expect(value).to eql ['test']
79
- end
80
- end
81
-
82
- context 'with a nested filter' do
83
- let(:block) { proc { array } }
84
-
85
- context 'with an Array' do
86
- let(:child_value) { [] }
87
- let(:value) { [child_value, child_value] }
88
-
89
- it 'returns the Array' do
90
- expect(result.value).to eql value
91
- end
92
-
93
- it 'has children' do
94
- expect(result.children.size).to be 2
95
- result.children.each do |child|
96
- expect(child).to be_an_instance_of ActiveInteraction::ArrayInput
97
- expect(child.value).to eql child_value
98
- end
99
- end
100
-
101
- context 'given a nil value' do
102
- let(:value) { nil }
103
-
104
- it 'returns an error' do
105
- error = result.errors.first
106
-
107
- expect(result.value).to eql value
108
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
109
- expect(error.type).to be :missing
110
- end
111
- end
112
- end
113
-
114
- context 'with an Array of Arrays' do
115
- let(:value) { [[]] }
116
-
117
- it 'returns the Array' do
118
- expect(result.value).to eql value
119
- end
120
- end
121
-
122
- context 'with a heterogenous Array' do
123
- let(:value) { [[], false, 0.0] }
124
-
125
- it 'indicates an error' do
126
- error = result.errors.first
127
-
128
- expect(result.errors.size).to be 1
129
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
130
- expect(error.name).to be filter.name
131
- expect(error.type).to be :invalid_type
132
- end
133
-
134
- context 'when :index_errors is true' do
135
- before do
136
- options[:index_errors] = true
137
- end
138
-
139
- it 'shows the index of where the error occurred' do
140
- expect(result.errors.size).to be 2
141
-
142
- result.errors.each.with_index(1) do |error, i|
143
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
144
- expect(error.name).to be :"#{filter.name}[#{i}]"
145
- expect(error.type).to be :invalid_type
146
- end
147
- end
148
- end
149
-
150
- context 'when ActiveRecord.index_nested_attribute_errors is true' do
151
- before do
152
- if ActiveRecord.respond_to?(:index_nested_attribute_errors)
153
- allow(ActiveRecord).to receive(:index_nested_attribute_errors).and_return(true)
154
- else
155
- allow(ActiveRecord::Base).to receive(:index_nested_attribute_errors).and_return(true)
156
- end
157
- end
158
-
159
- it 'shows the index of where the error occurred' do
160
- expect(result.errors.size).to be 2
161
-
162
- result.errors.each.with_index(1) do |error, i|
163
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
164
- expect(error.name).to be :"#{filter.name}[#{i}]"
165
- expect(error.type).to be :invalid_type
166
- end
167
- end
168
-
169
- context 'when :index_errors is false' do
170
- before do
171
- options[:index_errors] = false
172
- end
173
-
174
- it 'does not attach the index' do
175
- error = result.errors.first
176
-
177
- expect(result.errors.size).to be 1
178
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
179
- expect(error.name).to be filter.name
180
- expect(error.type).to be :invalid_type
181
- end
182
- end
183
- end
184
- end
185
- end
186
-
187
- [
188
- %i[object class],
189
- %i[record class],
190
- %i[interface from]
191
- ].each do |(type, option)|
192
- context "with a nested #{type} filter" do
193
- let(:block) { proc { public_send(type) } }
194
- let(:name) { :objects }
195
- let(:value) { [''] }
196
-
197
- it 'does not raise an error' do
198
- expect { result }.to_not raise_error
199
- end
200
-
201
- it 'has a filter with the right key' do
202
- expect(filter.filters).to have_key(:'0')
203
- end
204
-
205
- it 'has a filter with the right option' do
206
- expect(filter.filters[:'0'].options).to have_key(option)
207
- end
208
-
209
- context 'with a class set' do
210
- let(:block) { proc { public_send(type, "#{option}": String) } }
211
-
212
- it "does not override the #{option}" do
213
- expect(filter.filters[:'0'].options[option]).to eql String
214
- end
215
- end
216
- end
217
- end
218
-
219
- context 'with a nested interface type' do
220
- context 'with the methods option set' do
221
- let(:block) { proc { public_send(:interface, methods: %i[to_s]) } }
222
-
223
- it 'has a filter with the right option' do
224
- expect(filter.filters[:'0'].options).to have_key(:methods)
225
- expect(filter.filters[:'0'].options[:methods]).to eql %i[to_s]
226
- end
227
- end
228
-
229
- context 'with another option set' do
230
- let(:block) { proc { public_send(:object, converter: :new) } }
231
- let(:name) { :objects }
232
-
233
- it 'has a filter with the right options' do
234
- expect(filter.filters[:'0'].options).to have_key(:class)
235
- expect(filter.filters[:'0'].options[:class]).to be :Object
236
- expect(filter.filters[:'0'].options).to have_key(:converter)
237
- expect(filter.filters[:'0'].options[:converter]).to be :new
238
- end
239
- end
240
- end
241
- end
242
-
243
- describe '#database_column_type' do
244
- it 'returns :string' do
245
- expect(filter.database_column_type).to be :string
246
- end
247
- end
248
- end
@@ -1,85 +0,0 @@
1
- RSpec.describe ActiveInteraction::BooleanFilter, :filter do
2
- include_context 'filters'
3
- it_behaves_like 'a filter'
4
-
5
- describe '#process' do
6
- context 'falsey' do
7
- [false, '0', 'false', 'FALSE', 'off', 'OFF'].each do |value|
8
- it "returns false for #{value.inspect}" do
9
- expect(filter.process(value, nil).value).to be_falsey
10
- end
11
- end
12
-
13
- context 'with an implicit string' do
14
- let(:value) do
15
- Class.new do
16
- def to_str
17
- 'false'
18
- end
19
- end.new
20
- end
21
-
22
- it 'returns false' do
23
- expect(filter.process(value, nil).value).to be_falsey
24
- end
25
- end
26
- end
27
-
28
- context 'truthy' do
29
- [true, '1', 'true', 'TRUE', 'on', 'ON'].each do |value|
30
- it "returns true for #{value.inspect}" do
31
- expect(filter.process(value, nil).value).to be_truthy
32
- end
33
- end
34
-
35
- context 'with an implicit string' do
36
- let(:value) do
37
- Class.new do
38
- def to_str
39
- 'true'
40
- end
41
- end.new
42
- end
43
-
44
- it 'returns true' do
45
- expect(filter.process(value, nil).value).to be_truthy
46
- end
47
- end
48
- end
49
-
50
- context 'with a blank String' do
51
- let(:value) do
52
- Class.new do
53
- def to_str
54
- ' '
55
- end
56
- end.new
57
- end
58
-
59
- context 'optional' do
60
- include_context 'optional'
61
-
62
- it 'returns the default' do
63
- expect(filter.process(value, nil).value).to eql options[:default]
64
- end
65
- end
66
-
67
- context 'required' do
68
- include_context 'required'
69
-
70
- it 'indicates an error' do
71
- error = filter.process(value, nil).errors.first
72
-
73
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
74
- expect(error.type).to be :missing
75
- end
76
- end
77
- end
78
- end
79
-
80
- describe '#database_column_type' do
81
- it 'returns :boolean' do
82
- expect(filter.database_column_type).to be :boolean
83
- end
84
- end
85
- end
@@ -1,176 +0,0 @@
1
- RSpec.describe ActiveInteraction::DateFilter, :filter do
2
- include_context 'filters'
3
- it_behaves_like 'a filter'
4
-
5
- shared_context 'with format' do
6
- let(:format) { '%d/%m/%Y' }
7
-
8
- before do
9
- options[:format] = format
10
- end
11
- end
12
-
13
- describe '#process' do
14
- let(:result) { filter.process(value, nil) }
15
-
16
- context 'with a Date' do
17
- let(:value) { Date.new }
18
-
19
- it 'returns the Date' do
20
- expect(result.value).to eql value
21
- end
22
- end
23
-
24
- context 'with a String' do
25
- let(:value) { '2011-12-13' }
26
-
27
- it 'returns a Date' do
28
- expect(result.value).to eql Date.parse(value)
29
- end
30
-
31
- context 'with format' do
32
- include_context 'with format'
33
-
34
- let(:value) { '13/12/2011' }
35
-
36
- it 'returns a Date' do
37
- expect(result.value).to eql Date.strptime(value, format)
38
- end
39
- end
40
- end
41
-
42
- context 'with an invalid String' do
43
- let(:value) { 'invalid' }
44
-
45
- it 'indicates an error' do
46
- error = result.errors.first
47
-
48
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
49
- expect(error.type).to be :invalid_type
50
- end
51
-
52
- context 'with format' do
53
- include_context 'with format'
54
-
55
- it 'raises an error' do
56
- error = result.errors.first
57
-
58
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
59
- expect(error.type).to be :invalid_type
60
- end
61
- end
62
- end
63
-
64
- context 'with an implicit String' do
65
- let(:value) do
66
- Class.new do
67
- def to_str
68
- '2011-12-13'
69
- end
70
- end.new
71
- end
72
-
73
- it 'returns a Date' do
74
- expect(result.value).to eql Date.parse(value)
75
- end
76
- end
77
-
78
- context 'with a blank String' do
79
- let(:value) do
80
- Class.new do
81
- def to_str
82
- ' '
83
- end
84
- end.new
85
- end
86
-
87
- context 'optional' do
88
- include_context 'optional'
89
-
90
- it 'returns the default' do
91
- expect(result.value).to eql options[:default]
92
- end
93
- end
94
-
95
- context 'required' do
96
- include_context 'required'
97
-
98
- it 'indicates an error' do
99
- error = result.errors.first
100
-
101
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
102
- expect(error.type).to be :missing
103
- end
104
- end
105
- end
106
-
107
- context 'with a GroupedInput' do
108
- let(:year) { 2012 }
109
- let(:month) { 1 }
110
- let(:day) { 2 }
111
- let(:value) do
112
- ActiveInteraction::GroupedInput.new(
113
- '1' => year.to_s,
114
- '2' => month.to_s,
115
- '3' => day.to_s
116
- )
117
- end
118
-
119
- it 'returns a Date' do
120
- expect(result.value).to eql Date.new(year, month, day)
121
- end
122
- end
123
-
124
- context 'with an invalid GroupedInput' do
125
- context 'empty' do
126
- let(:value) { ActiveInteraction::GroupedInput.new }
127
-
128
- it 'indicates an error' do
129
- error = result.errors.first
130
-
131
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
132
- expect(error.type).to be :invalid_type
133
- end
134
- end
135
-
136
- context 'partial inputs' do
137
- let(:value) do
138
- ActiveInteraction::GroupedInput.new(
139
- '2' => '1'
140
- )
141
- end
142
-
143
- it 'raises an error' do
144
- error = result.errors.first
145
-
146
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
147
- expect(error.type).to be :invalid_type
148
- end
149
- end
150
- end
151
- end
152
-
153
- describe '#database_column_type' do
154
- it 'returns :date' do
155
- expect(filter.database_column_type).to be :date
156
- end
157
- end
158
-
159
- describe '#default' do
160
- context 'with a GroupedInput' do
161
- before do
162
- options[:default] = ActiveInteraction::GroupedInput.new(
163
- '1' => '2012',
164
- '2' => '1',
165
- '3' => '2'
166
- )
167
- end
168
-
169
- it 'raises an error' do
170
- expect do
171
- filter.default(nil)
172
- end.to raise_error ActiveInteraction::InvalidDefaultError
173
- end
174
- end
175
- end
176
- end