active_interaction 3.8.3 → 4.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +157 -0
- data/README.md +93 -107
- data/lib/active_interaction.rb +1 -7
- data/lib/active_interaction/base.rb +23 -26
- data/lib/active_interaction/concerns/active_modelable.rb +1 -3
- data/lib/active_interaction/concerns/active_recordable.rb +1 -6
- data/lib/active_interaction/concerns/hashable.rb +0 -1
- data/lib/active_interaction/concerns/missable.rb +0 -1
- data/lib/active_interaction/concerns/runnable.rb +6 -12
- data/lib/active_interaction/errors.rb +3 -6
- data/lib/active_interaction/filter.rb +51 -37
- data/lib/active_interaction/filter_column.rb +0 -3
- data/lib/active_interaction/filters/abstract_date_time_filter.rb +34 -36
- data/lib/active_interaction/filters/abstract_numeric_filter.rb +27 -17
- data/lib/active_interaction/filters/array_filter.rb +57 -36
- data/lib/active_interaction/filters/boolean_filter.rb +26 -12
- data/lib/active_interaction/filters/date_filter.rb +1 -2
- data/lib/active_interaction/filters/date_time_filter.rb +1 -2
- data/lib/active_interaction/filters/decimal_filter.rb +10 -28
- data/lib/active_interaction/filters/file_filter.rb +6 -5
- data/lib/active_interaction/filters/float_filter.rb +1 -2
- data/lib/active_interaction/filters/hash_filter.rb +37 -27
- data/lib/active_interaction/filters/integer_filter.rb +7 -8
- data/lib/active_interaction/filters/interface_filter.rb +48 -14
- data/lib/active_interaction/filters/object_filter.rb +23 -50
- data/lib/active_interaction/filters/record_filter.rb +10 -35
- data/lib/active_interaction/filters/string_filter.rb +21 -12
- data/lib/active_interaction/filters/symbol_filter.rb +13 -7
- data/lib/active_interaction/filters/time_filter.rb +19 -22
- data/lib/active_interaction/grouped_input.rb +0 -3
- data/lib/active_interaction/inputs.rb +89 -0
- data/lib/active_interaction/modules/input_processor.rb +1 -4
- data/lib/active_interaction/modules/validation.rb +9 -12
- data/lib/active_interaction/version.rb +1 -3
- data/spec/active_interaction/base_spec.rb +13 -41
- data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -2
- data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -2
- data/spec/active_interaction/concerns/hashable_spec.rb +1 -3
- data/spec/active_interaction/concerns/missable_spec.rb +0 -2
- data/spec/active_interaction/concerns/runnable_spec.rb +9 -13
- data/spec/active_interaction/errors_spec.rb +4 -25
- data/spec/active_interaction/filter_column_spec.rb +0 -2
- data/spec/active_interaction/filter_spec.rb +0 -2
- data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/array_filter_spec.rb +41 -15
- data/spec/active_interaction/filters/boolean_filter_spec.rb +58 -4
- data/spec/active_interaction/filters/date_filter_spec.rb +43 -3
- data/spec/active_interaction/filters/date_time_filter_spec.rb +43 -3
- data/spec/active_interaction/filters/decimal_filter_spec.rb +57 -3
- data/spec/active_interaction/filters/file_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/float_filter_spec.rb +60 -4
- data/spec/active_interaction/filters/hash_filter_spec.rb +19 -9
- data/spec/active_interaction/filters/integer_filter_spec.rb +49 -7
- data/spec/active_interaction/filters/interface_filter_spec.rb +397 -24
- data/spec/active_interaction/filters/object_filter_spec.rb +23 -59
- data/spec/active_interaction/filters/record_filter_spec.rb +23 -49
- data/spec/active_interaction/filters/string_filter_spec.rb +15 -3
- data/spec/active_interaction/filters/symbol_filter_spec.rb +15 -3
- data/spec/active_interaction/filters/time_filter_spec.rb +65 -3
- data/spec/active_interaction/grouped_input_spec.rb +0 -2
- data/spec/active_interaction/i18n_spec.rb +3 -7
- data/spec/active_interaction/{modules/input_processor_spec.rb → inputs_spec.rb} +3 -5
- data/spec/active_interaction/integration/array_interaction_spec.rb +18 -22
- data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/date_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/file_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/float_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/interface_interaction_spec.rb +1 -3
- data/spec/active_interaction/integration/object_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/string_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/time_interaction_spec.rb +14 -18
- data/spec/active_interaction/modules/validation_spec.rb +1 -3
- data/spec/spec_helper.rb +2 -6
- data/spec/support/concerns.rb +0 -2
- data/spec/support/filters.rb +13 -9
- data/spec/support/interactions.rb +22 -14
- metadata +77 -52
- data/lib/active_interaction/backports.rb +0 -59
- data/lib/active_interaction/filters/abstract_filter.rb +0 -19
- data/spec/active_interaction/filters/abstract_filter_spec.rb +0 -8
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
require 'active_record'
|
5
3
|
unless defined?(JRUBY_VERSION) # rubocop:disable Style/IfUnlessModifier
|
@@ -28,25 +26,6 @@ describe ActiveInteraction::Errors do
|
|
28
26
|
|
29
27
|
subject(:errors) { described_class.new(klass.new) }
|
30
28
|
|
31
|
-
context 'backports' do
|
32
|
-
describe '#delete' do
|
33
|
-
it 'deletes the detailed error' do
|
34
|
-
errors.add(:attribute)
|
35
|
-
errors.delete(:attribute)
|
36
|
-
expect(errors.details).to_not have_key :attribute
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#initialize_dup' do
|
41
|
-
it 'duplicates the detailed errors' do
|
42
|
-
errors.add(:attribute)
|
43
|
-
other = errors.dup
|
44
|
-
expect(other.details).to eql errors.details
|
45
|
-
expect(other.details).to_not be errors.details
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
29
|
describe '#merge!' do
|
51
30
|
let(:other) { described_class.new(klass.new) }
|
52
31
|
|
@@ -128,7 +107,7 @@ describe ActiveInteraction::Errors do
|
|
128
107
|
klass.name => {
|
129
108
|
attributes: {
|
130
109
|
attribute: {
|
131
|
-
invalid_type: 'is not a valid
|
110
|
+
invalid_type: 'is not a valid %<type>s'
|
132
111
|
}
|
133
112
|
}
|
134
113
|
}
|
@@ -173,12 +152,12 @@ describe ActiveInteraction::Errors do
|
|
173
152
|
end
|
174
153
|
end
|
175
154
|
|
176
|
-
class A < ActiveRecord::Base
|
155
|
+
class A < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
|
177
156
|
has_one :b
|
178
157
|
accepts_nested_attributes_for :b
|
179
158
|
end
|
180
159
|
|
181
|
-
class B < ActiveRecord::Base
|
160
|
+
class B < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
|
182
161
|
belongs_to :a
|
183
162
|
|
184
163
|
validates :name, presence: true
|
@@ -189,7 +168,7 @@ describe ActiveInteraction::Errors do
|
|
189
168
|
|
190
169
|
it 'merges the nested errors' do
|
191
170
|
a.valid?
|
192
|
-
expect(a.errors.messages).to
|
171
|
+
expect(a.errors.messages).to eq('b.name': ["can't be blank"])
|
193
172
|
expect(a.errors.size).to eql 1
|
194
173
|
expect { errors.merge!(a.errors) }.to_not raise_error
|
195
174
|
expect(errors.size).to eql 1
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::AbstractDateTimeFilter, :filter do
|
@@ -9,7 +7,7 @@ describe ActiveInteraction::AbstractDateTimeFilter, :filter do
|
|
9
7
|
let(:value) { nil }
|
10
8
|
|
11
9
|
it 'raises an error' do
|
12
|
-
expect { filter.cast
|
10
|
+
expect { filter.send(:cast, value, nil) }.to raise_error NameError
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::AbstractNumericFilter, :filter do
|
@@ -9,7 +7,7 @@ describe ActiveInteraction::AbstractNumericFilter, :filter do
|
|
9
7
|
let(:value) { nil }
|
10
8
|
|
11
9
|
it 'raises an error' do
|
12
|
-
expect { filter.cast
|
10
|
+
expect { filter.send(:cast, value, nil) }.to raise_error NameError
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::ArrayFilter, :filter do
|
@@ -36,7 +34,7 @@ describe ActiveInteraction::ArrayFilter, :filter do
|
|
36
34
|
end
|
37
35
|
|
38
36
|
describe '#cast' do
|
39
|
-
let(:result) { filter.cast
|
37
|
+
let(:result) { filter.send(:cast, value, nil) }
|
40
38
|
|
41
39
|
context 'with an Array' do
|
42
40
|
let(:value) { [] }
|
@@ -46,6 +44,20 @@ describe ActiveInteraction::ArrayFilter, :filter do
|
|
46
44
|
end
|
47
45
|
end
|
48
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).to eql value.to_ary
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
49
61
|
context 'with a heterogenous Array' do
|
50
62
|
let(:value) { [[], false, 0.0, {}, 0, '', :''] }
|
51
63
|
|
@@ -84,21 +96,35 @@ describe ActiveInteraction::ArrayFilter, :filter do
|
|
84
96
|
end
|
85
97
|
end
|
86
98
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
99
|
+
[
|
100
|
+
%i[object class],
|
101
|
+
%i[record class],
|
102
|
+
%i[interface from]
|
103
|
+
].each do |(type, option)|
|
104
|
+
context "with a nested #{type} filter" do
|
105
|
+
let(:block) { proc { public_send(type) } }
|
106
|
+
let(:name) { :objects }
|
107
|
+
let(:value) { [''] }
|
108
|
+
|
109
|
+
it 'does not raise an error' do
|
110
|
+
expect { result }.to_not raise_error
|
111
|
+
end
|
91
112
|
|
92
|
-
|
93
|
-
|
94
|
-
|
113
|
+
it 'has a filter with the right key' do
|
114
|
+
expect(filter.filters).to have_key(:'0')
|
115
|
+
end
|
95
116
|
|
96
|
-
|
97
|
-
|
98
|
-
|
117
|
+
it 'has a filter with the right option' do
|
118
|
+
expect(filter.filters[:'0'].options).to have_key(option)
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'with a class set' do
|
122
|
+
let(:block) { proc { public_send(type, "#{option}": String) } }
|
99
123
|
|
100
|
-
|
101
|
-
|
124
|
+
it "does not override the #{option}" do
|
125
|
+
expect(filter.filters[:'0'].options[option]).to eql String
|
126
|
+
end
|
127
|
+
end
|
102
128
|
end
|
103
129
|
end
|
104
130
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::BooleanFilter, :filter do
|
@@ -10,7 +8,21 @@ describe ActiveInteraction::BooleanFilter, :filter do
|
|
10
8
|
context 'falsey' do
|
11
9
|
[false, '0', 'false', 'FALSE', 'off', 'OFF'].each do |value|
|
12
10
|
it "returns false for #{value.inspect}" do
|
13
|
-
expect(filter.cast
|
11
|
+
expect(filter.send(:cast, value, nil)).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.send(:cast, value, nil)).to be_falsey
|
14
26
|
end
|
15
27
|
end
|
16
28
|
end
|
@@ -18,7 +30,49 @@ describe ActiveInteraction::BooleanFilter, :filter do
|
|
18
30
|
context 'truthy' do
|
19
31
|
[true, '1', 'true', 'TRUE', 'on', 'ON'].each do |value|
|
20
32
|
it "returns true for #{value.inspect}" do
|
21
|
-
expect(filter.cast
|
33
|
+
expect(filter.send(:cast, value, nil)).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.send(:cast, value, nil)).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.send(:cast, value, nil)).to eql options[:default]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'required' do
|
70
|
+
include_context 'required'
|
71
|
+
|
72
|
+
it 'raises an error' do
|
73
|
+
expect do
|
74
|
+
filter.send(:cast, value, nil)
|
75
|
+
end.to raise_error ActiveInteraction::MissingValueError
|
22
76
|
end
|
23
77
|
end
|
24
78
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::DateFilter, :filter do
|
@@ -15,7 +13,7 @@ describe ActiveInteraction::DateFilter, :filter do
|
|
15
13
|
end
|
16
14
|
|
17
15
|
describe '#cast' do
|
18
|
-
let(:result) { filter.cast
|
16
|
+
let(:result) { filter.send(:cast, value, nil) }
|
19
17
|
|
20
18
|
context 'with a Date' do
|
21
19
|
let(:value) { Date.new }
|
@@ -63,6 +61,48 @@ describe ActiveInteraction::DateFilter, :filter do
|
|
63
61
|
end
|
64
62
|
end
|
65
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).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).to eql options[:default]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'required' do
|
96
|
+
include_context 'required'
|
97
|
+
|
98
|
+
it 'raises an error' do
|
99
|
+
expect do
|
100
|
+
result
|
101
|
+
end.to raise_error ActiveInteraction::MissingValueError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
66
106
|
context 'with a GroupedInput' do
|
67
107
|
let(:year) { 2012 }
|
68
108
|
let(:month) { 1 }
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::DateTimeFilter, :filter do
|
@@ -15,7 +13,7 @@ describe ActiveInteraction::DateTimeFilter, :filter do
|
|
15
13
|
end
|
16
14
|
|
17
15
|
describe '#cast' do
|
18
|
-
let(:result) { filter.cast
|
16
|
+
let(:result) { filter.send(:cast, value, nil) }
|
19
17
|
|
20
18
|
context 'with a Datetime' do
|
21
19
|
let(:value) { DateTime.new }
|
@@ -63,6 +61,48 @@ describe ActiveInteraction::DateTimeFilter, :filter do
|
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
64
|
+
context 'with an implicit String' do
|
65
|
+
let(:value) do
|
66
|
+
Class.new do
|
67
|
+
def to_str
|
68
|
+
'2011-12-13T14:15:16+17:18'
|
69
|
+
end
|
70
|
+
end.new
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns a DateTime' do
|
74
|
+
expect(result).to eql DateTime.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).to eql options[:default]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'required' do
|
96
|
+
include_context 'required'
|
97
|
+
|
98
|
+
it 'raises an error' do
|
99
|
+
expect do
|
100
|
+
result
|
101
|
+
end.to raise_error ActiveInteraction::MissingValueError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
66
106
|
context 'with a GroupedInput' do
|
67
107
|
let(:year) { 2012 }
|
68
108
|
let(:month) { 1 }
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'spec_helper'
|
4
2
|
|
5
3
|
describe ActiveInteraction::DecimalFilter, :filter do
|
@@ -15,7 +13,7 @@ describe ActiveInteraction::DecimalFilter, :filter do
|
|
15
13
|
end
|
16
14
|
|
17
15
|
describe '#cast' do
|
18
|
-
let(:result) { filter.cast
|
16
|
+
let(:result) { filter.send(:cast, value, nil) }
|
19
17
|
|
20
18
|
context 'with a Float' do
|
21
19
|
let(:value) { rand }
|
@@ -35,6 +33,20 @@ describe ActiveInteraction::DecimalFilter, :filter do
|
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
36
|
+
context 'with an implicit Integer' do
|
37
|
+
let(:value) do
|
38
|
+
Class.new do
|
39
|
+
def to_int
|
40
|
+
@to_int ||= rand(1 << 16)
|
41
|
+
end
|
42
|
+
end.new
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns a BigDecimal' do
|
46
|
+
expect(result).to eql BigDecimal(value.to_int)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
38
50
|
context 'with a Numeric' do
|
39
51
|
let(:value) { rand(1 << 16) }
|
40
52
|
|
@@ -60,6 +72,48 @@ describe ActiveInteraction::DecimalFilter, :filter do
|
|
60
72
|
end.to raise_error ActiveInteraction::InvalidValueError
|
61
73
|
end
|
62
74
|
end
|
75
|
+
|
76
|
+
context 'with an implicit String' do
|
77
|
+
let(:value) do
|
78
|
+
Class.new do
|
79
|
+
def to_str
|
80
|
+
'1.1'
|
81
|
+
end
|
82
|
+
end.new
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns a BigDecimal' do
|
86
|
+
expect(result).to eql BigDecimal(value)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with a blank String' do
|
91
|
+
let(:value) do
|
92
|
+
Class.new do
|
93
|
+
def to_str
|
94
|
+
' '
|
95
|
+
end
|
96
|
+
end.new
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'optional' do
|
100
|
+
include_context 'optional'
|
101
|
+
|
102
|
+
it 'returns the default' do
|
103
|
+
expect(result).to eql options[:default]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'required' do
|
108
|
+
include_context 'required'
|
109
|
+
|
110
|
+
it 'raises an error' do
|
111
|
+
expect do
|
112
|
+
result
|
113
|
+
end.to raise_error ActiveInteraction::MissingValueError
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
63
117
|
end
|
64
118
|
|
65
119
|
describe '#database_column_type' do
|