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