active_interaction 5.2.0 → 5.4.0

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