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,206 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class RecordThing
4
- def self.find(_)
5
- raise 'error'
6
- end
7
-
8
- def self.finder(_)
9
- @finder ||= new
10
- end
11
-
12
- def self.finds_nil(_)
13
- nil
14
- end
15
-
16
- def self.finds_bad_value(_)
17
- Object.new
18
- end
19
- end
20
-
21
- class RecordThings; end # rubocop:disable Lint/EmptyClass
22
- BackupRecordThing = RecordThing
23
-
24
- describe ActiveInteraction::RecordFilter, :filter do
25
- include_context 'filters'
26
- before do
27
- options[:class] = RecordThing
28
- end
29
-
30
- it_behaves_like 'a filter'
31
-
32
- describe '#process' do
33
- let(:value) { RecordThing.new }
34
- let(:result) { filter.process(value, nil) }
35
-
36
- context 'with an instance of the class' do
37
- it 'returns the instance' do
38
- expect(result.value).to eql value
39
- end
40
-
41
- context 'with an instance that is a subclass' do
42
- let(:subclass) { Class.new(RecordThing) }
43
- let(:value) { subclass.new }
44
-
45
- it 'returns the instance' do
46
- expect(result.value).to eql value
47
- end
48
- end
49
-
50
- it 'handles reconstantizing' do
51
- expect(result.value).to eql value
52
-
53
- Object.send(:remove_const, :RecordThing)
54
- RecordThing = BackupRecordThing # rubocop:disable Lint/ConstantDefinitionInBlock
55
- value = RecordThing.new
56
-
57
- expect(filter.process(value, nil).value).to eql value
58
- end
59
-
60
- it 'handles reconstantizing subclasses' do
61
- filter
62
-
63
- Object.send(:remove_const, :RecordThing)
64
- RecordThing = BackupRecordThing # rubocop:disable Lint/ConstantDefinitionInBlock
65
- class SubRecordThing < RecordThing; end # rubocop:disable Lint/ConstantDefinitionInBlock
66
- value = SubRecordThing.new
67
-
68
- expect(filter.process(value, nil).value).to eql value
69
- end
70
-
71
- context 'without the class available' do
72
- before { Object.send(:remove_const, :RecordThing) }
73
-
74
- after { RecordThing = BackupRecordThing } # rubocop:disable Lint/ConstantDefinitionInBlock
75
-
76
- it 'does not raise an error on initialization' do
77
- expect { filter }.to_not raise_error
78
- end
79
- end
80
- end
81
-
82
- context 'with class as a superclass' do
83
- before do
84
- options[:class] = RecordThing.superclass
85
- end
86
-
87
- it 'returns the instance' do
88
- expect(result.value).to eql value
89
- end
90
- end
91
-
92
- context 'with class as a String' do
93
- before do
94
- options[:class] = RecordThing.name
95
- end
96
-
97
- it 'returns the instance' do
98
- expect(result.value).to eql value
99
- end
100
- end
101
-
102
- context 'with a plural class' do
103
- let(:value) { RecordThings.new }
104
-
105
- before { options[:class] = RecordThings }
106
-
107
- it 'returns the instance' do
108
- expect(result.value).to eql value
109
- end
110
- end
111
-
112
- context 'with class as an invalid String' do
113
- before do
114
- options[:class] = 'invalid'
115
- end
116
-
117
- it 'raises an error' do
118
- expect do
119
- result
120
- end.to raise_error ActiveInteraction::InvalidNameError
121
- end
122
- end
123
-
124
- context 'with a value that does not match the class' do
125
- let(:value) { 1 }
126
-
127
- it 'calls the default finder' do
128
- allow(RecordThing).to receive(:find)
129
- result
130
- expect(RecordThing).to have_received(:find).with(value)
131
- end
132
-
133
- context 'with a custom finder' do
134
- before do
135
- options[:finder] = :finder
136
- end
137
-
138
- it 'calls the custom finder' do
139
- allow(RecordThing).to receive(:finder)
140
- result
141
- expect(RecordThing).to have_received(:finder).with(value)
142
- end
143
- end
144
-
145
- context 'that returns a nil' do
146
- let(:value) { 1 }
147
-
148
- before do
149
- options[:default] = RecordThing.new
150
- options[:finder] = :finds_nil
151
- end
152
-
153
- it 'indicates an error' do
154
- error = filter.process(value, nil).errors.first
155
-
156
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
157
- expect(error.type).to be :invalid_type
158
- end
159
- end
160
-
161
- context 'that returns an invalid value' do
162
- let(:value) { 1 }
163
-
164
- before do
165
- options[:finder] = :finds_bad_value
166
- end
167
-
168
- it 'indicates an error' do
169
- error = filter.process(value, nil).errors.first
170
-
171
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
172
- expect(error.type).to be :invalid_type
173
- end
174
- end
175
- end
176
-
177
- context 'with a blank String' do
178
- let(:value) { ' ' }
179
-
180
- context 'optional' do
181
- include_context 'optional'
182
-
183
- it 'returns the default' do
184
- expect(filter.process(value, nil).value).to eql options[:default]
185
- end
186
- end
187
-
188
- context 'required' do
189
- include_context 'required'
190
-
191
- it 'indicates an error' do
192
- error = filter.process(value, nil).errors.first
193
-
194
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
195
- expect(error.type).to be :missing
196
- end
197
- end
198
- end
199
- end
200
-
201
- describe '#database_column_type' do
202
- it 'returns :string' do
203
- expect(filter.database_column_type).to be :string
204
- end
205
- end
206
- end
@@ -1,60 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveInteraction::StringFilter, :filter do
4
- include_context 'filters'
5
- it_behaves_like 'a filter'
6
-
7
- shared_context 'without strip' do
8
- before do
9
- options[:strip] = false
10
- end
11
- end
12
-
13
- describe '#process' do
14
- let(:result) { filter.process(value, nil) }
15
-
16
- context 'with a String' do
17
- let(:value) { SecureRandom.hex }
18
-
19
- it 'returns the String' do
20
- expect(result.value).to eql value
21
- end
22
- end
23
-
24
- context 'with an implicit String' do
25
- let(:value) do
26
- Class.new do
27
- def to_str
28
- @to_str ||= SecureRandom.hex
29
- end
30
- end.new
31
- end
32
-
33
- it 'returns the String' do
34
- expect(result.value).to eql value.to_str
35
- end
36
- end
37
-
38
- context 'with a strippable String' do
39
- let(:value) { " #{SecureRandom.hex} " }
40
-
41
- it 'returns the stripped string' do
42
- expect(result.value).to eql value.strip
43
- end
44
-
45
- context 'without strip' do
46
- include_context 'without strip'
47
-
48
- it 'returns the String' do
49
- expect(result.value).to eql value
50
- end
51
- end
52
- end
53
- end
54
-
55
- describe '#database_column_type' do
56
- it 'returns :string' do
57
- expect(filter.database_column_type).to be :string
58
- end
59
- end
60
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveInteraction::SymbolFilter, :filter do
4
- include_context 'filters'
5
- it_behaves_like 'a filter'
6
-
7
- describe '#process' do
8
- let(:result) { filter.process(value, nil) }
9
-
10
- context 'with a Symbol' do
11
- let(:value) { SecureRandom.hex.to_sym }
12
-
13
- it 'returns the Symbol' do
14
- expect(result.value).to eql value
15
- end
16
- end
17
-
18
- context 'with an implicit Symbol' do
19
- let(:value) do
20
- Class.new do
21
- def to_sym
22
- :symbol
23
- end
24
- end.new
25
- end
26
-
27
- it 'returns a symbol' do
28
- expect(result.value).to eql value.to_sym
29
- end
30
- end
31
-
32
- context 'with a String' do
33
- let(:value) { SecureRandom.hex }
34
-
35
- it 'returns a Symbol' do
36
- expect(result.value).to eql value.to_sym
37
- end
38
- end
39
- end
40
-
41
- describe '#database_column_type' do
42
- it 'returns :string' do
43
- expect(filter.database_column_type).to be :string
44
- end
45
- end
46
- end
@@ -1,251 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveInteraction::TimeFilter, :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 %H:%M:%S %z' }
9
-
10
- before do
11
- options[:format] = format
12
- end
13
- end
14
-
15
- describe '#initialize' do
16
- context 'with a format' do
17
- before { options[:format] = '%T' }
18
-
19
- context 'with a time zone' do
20
- before do
21
- time_with_zone = double
22
-
23
- time_zone = double
24
- allow(time_zone).to receive(:at).and_return(time_with_zone)
25
-
26
- allow(Time).to receive(:zone).and_return(time_zone)
27
- end
28
-
29
- it 'raises an error' do
30
- expect do
31
- filter
32
- end.to raise_error(ActiveInteraction::InvalidFilterError)
33
- end
34
- end
35
- end
36
- end
37
-
38
- describe '#process' do
39
- let(:result) { filter.process(value, nil) }
40
-
41
- context 'with a Time' do
42
- let(:value) { Time.new }
43
-
44
- it 'returns the Time' do
45
- expect(result.value).to eql value
46
- end
47
- end
48
-
49
- context 'with a String' do
50
- let(:value) { '2011-12-13 14:15:16 +1718' }
51
-
52
- it 'returns a Time' do
53
- expect(result.value).to eql Time.parse(value)
54
- end
55
-
56
- context 'with a time zone' do
57
- before do
58
- klass = double
59
- allow(klass).to receive(:parse).with(value).and_return(nil)
60
-
61
- allow(filter).to receive(:matches?).and_return(false)
62
- allow(filter).to receive(:klass).and_return(klass)
63
- end
64
-
65
- it 'indicates an error the string is not parsable' do
66
- error = result.errors.first
67
-
68
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
69
- expect(error.type).to be :invalid_type
70
- end
71
- end
72
-
73
- context 'with format' do
74
- include_context 'with format'
75
-
76
- let(:value) { '13/12/2011 14:15:16 +1718' }
77
-
78
- it 'returns a Time' do
79
- expect(result.value).to eql Time.strptime(value, format)
80
- end
81
- end
82
- end
83
-
84
- context 'with an invalid String' do
85
- let(:value) { 'invalid' }
86
-
87
- it 'indicates an error' do
88
- error = result.errors.first
89
-
90
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
91
- expect(error.type).to be :invalid_type
92
- end
93
-
94
- context 'with format' do
95
- include_context 'with format'
96
-
97
- it 'indicates an error' do
98
- error = result.errors.first
99
-
100
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
101
- expect(error.type).to be :invalid_type
102
- end
103
- end
104
- end
105
-
106
- context 'with an implicit String' do
107
- let(:value) do
108
- Class.new do
109
- def to_str
110
- '2011-12-13 14:15:16 +1718'
111
- end
112
- end.new
113
- end
114
-
115
- it 'returns a Time' do
116
- expect(result.value).to eql Time.parse(value)
117
- end
118
- end
119
-
120
- context 'with a blank String' do
121
- let(:value) do
122
- Class.new do
123
- def to_str
124
- ' '
125
- end
126
- end.new
127
- end
128
-
129
- context 'optional' do
130
- include_context 'optional'
131
-
132
- it 'returns the default' do
133
- expect(result.value).to eql options[:default]
134
- end
135
- end
136
-
137
- context 'required' do
138
- include_context 'required'
139
-
140
- it 'indicates an error' do
141
- error = result.errors.first
142
-
143
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
144
- expect(error.type).to be :missing
145
- end
146
- end
147
- end
148
-
149
- context 'with an Integer' do
150
- let(:value) { rand(1 << 16) }
151
-
152
- it 'returns the Time' do
153
- expect(result.value).to eql Time.at(value)
154
- end
155
- end
156
-
157
- context 'with an implicit Integer' do
158
- let(:value) do
159
- Class.new do
160
- def to_int
161
- @to_int ||= rand(1 << 16)
162
- end
163
- end.new
164
- end
165
-
166
- it 'returns the Time' do
167
- expect(result.value).to eql Time.at(value)
168
- end
169
- end
170
-
171
- context 'with a GroupedInput' do
172
- let(:year) { 2012 }
173
- let(:month) { 1 }
174
- let(:day) { 2 }
175
- let(:hour) { 3 }
176
- let(:min) { 4 }
177
- let(:sec) { 5 }
178
- let(:value) do
179
- ActiveInteraction::GroupedInput.new(
180
- '1' => year.to_s,
181
- '2' => month.to_s,
182
- '3' => day.to_s,
183
- '4' => hour.to_s,
184
- '5' => min.to_s,
185
- '6' => sec.to_s
186
- )
187
- end
188
-
189
- it 'returns a Time' do
190
- expect(
191
- result.value
192
- ).to eql Time.new(year, month, day, hour, min, sec)
193
- end
194
- end
195
-
196
- context 'with an invalid GroupedInput' do
197
- context 'empty' do
198
- let(:value) { ActiveInteraction::GroupedInput.new }
199
-
200
- it 'indicates an error' do
201
- error = result.errors.first
202
-
203
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
204
- expect(error.type).to be :invalid_type
205
- end
206
- end
207
-
208
- context 'partial inputs' do
209
- let(:value) do
210
- ActiveInteraction::GroupedInput.new(
211
- '2' => '1'
212
- )
213
- end
214
-
215
- it 'indicates an error' do
216
- error = result.errors.first
217
-
218
- expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
219
- expect(error.type).to be :invalid_type
220
- end
221
- end
222
- end
223
- end
224
-
225
- describe '#database_column_type' do
226
- it 'returns :datetime' do
227
- expect(filter.database_column_type).to be :datetime
228
- end
229
- end
230
-
231
- describe '#default' do
232
- context 'with a GroupedInput' do
233
- before do
234
- options[:default] = ActiveInteraction::GroupedInput.new(
235
- '1' => '2012',
236
- '2' => '1',
237
- '3' => '2',
238
- '4' => '3',
239
- '5' => '4',
240
- '6' => '5'
241
- )
242
- end
243
-
244
- it 'raises an error' do
245
- expect do
246
- filter.default(nil)
247
- end.to raise_error ActiveInteraction::InvalidDefaultError
248
- end
249
- end
250
- end
251
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveInteraction::GroupedInput do
4
- subject(:grouped_input) { described_class.new }
5
-
6
- it 'subclasses OpenStruct' do
7
- expect(grouped_input).to be_an OpenStruct
8
- end
9
-
10
- it 'responds to #[]' do
11
- expect { grouped_input[:key] }.to_not raise_error
12
- end
13
-
14
- it 'responds to #[]=' do
15
- expect { grouped_input[:key] = :value }.to_not raise_error
16
- end
17
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveInteraction::HashInput do
4
- subject(:input) do
5
- described_class.new(filter,
6
- value: value,
7
- error: error,
8
- children: children
9
- )
10
- end
11
-
12
- let(:filter) do
13
- ActiveInteraction::HashFilter.new(:h, &block)
14
- end
15
- let(:block) { proc { integer :i } }
16
- let(:value) { nil }
17
- let(:error) { nil }
18
- let(:children) { {} }
19
-
20
- describe '#errors' do
21
- context 'with no errors' do
22
- it 'returns an empty array' do
23
- expect(input.errors).to be_empty
24
- end
25
- end
26
-
27
- context 'with an error on the hash' do
28
- let(:error) { ActiveInteraction::Filter::Error.new(filter, :invalid_type) }
29
-
30
- it 'returns one error in the array' do
31
- expect(input.errors.size).to be 1
32
-
33
- error = input.errors.first
34
- expect(error.name).to be filter.name
35
- expect(error.type).to be :invalid_type
36
- end
37
- end
38
-
39
- context 'with children with errors' do
40
- let(:child_i) do
41
- filter = ActiveInteraction::IntegerFilter.new(:i)
42
- ActiveInteraction::Input.new(filter,
43
- value: nil,
44
- error: ActiveInteraction::Filter::Error.new(filter, :missing)
45
- )
46
- end
47
- let(:children) { { i: child_i } }
48
-
49
- it 'returns the error' do
50
- expect(input.errors.size).to be 1
51
-
52
- error = input.errors.first
53
- expect(error.name).to be :"#{filter.name}.i"
54
- expect(error.type).to be :missing
55
- end
56
- end
57
- end
58
- end