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,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