active_interaction 1.1.7 → 1.2.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +3 -2
  4. data/lib/active_interaction.rb +7 -1
  5. data/lib/active_interaction/base.rb +61 -13
  6. data/lib/active_interaction/concerns/runnable.rb +2 -18
  7. data/lib/active_interaction/concerns/transactable.rb +72 -0
  8. data/lib/active_interaction/errors.rb +7 -0
  9. data/lib/active_interaction/filter.rb +23 -2
  10. data/lib/active_interaction/filter_column.rb +59 -0
  11. data/lib/active_interaction/filters/abstract_date_time_filter.rb +14 -0
  12. data/lib/active_interaction/filters/abstract_filter.rb +4 -7
  13. data/lib/active_interaction/filters/abstract_numeric_filter.rb +4 -0
  14. data/lib/active_interaction/filters/boolean_filter.rb +4 -0
  15. data/lib/active_interaction/filters/date_time_filter.rb +3 -0
  16. data/lib/active_interaction/filters/decimal_filter.rb +54 -0
  17. data/lib/active_interaction/filters/file_filter.rb +4 -0
  18. data/lib/active_interaction/filters/time_filter.rb +4 -0
  19. data/lib/active_interaction/grouped_input.rb +24 -0
  20. data/lib/active_interaction/locale/en.yml +1 -0
  21. data/lib/active_interaction/modules/input_processor.rb +40 -0
  22. data/lib/active_interaction/version.rb +1 -1
  23. data/spec/active_interaction/base_spec.rb +90 -29
  24. data/spec/active_interaction/concerns/runnable_spec.rb +0 -26
  25. data/spec/active_interaction/concerns/transactable_spec.rb +114 -0
  26. data/spec/active_interaction/filter_column_spec.rb +96 -0
  27. data/spec/active_interaction/filter_spec.rb +15 -11
  28. data/spec/active_interaction/filters/array_filter_spec.rb +13 -5
  29. data/spec/active_interaction/filters/boolean_filter_spec.rb +6 -0
  30. data/spec/active_interaction/filters/date_filter_spec.rb +76 -5
  31. data/spec/active_interaction/filters/date_time_filter_spec.rb +87 -5
  32. data/spec/active_interaction/filters/decimal_filter_spec.rb +70 -0
  33. data/spec/active_interaction/filters/file_filter_spec.rb +11 -3
  34. data/spec/active_interaction/filters/float_filter_spec.rb +12 -4
  35. data/spec/active_interaction/filters/hash_filter_spec.rb +16 -8
  36. data/spec/active_interaction/filters/integer_filter_spec.rb +12 -4
  37. data/spec/active_interaction/filters/model_filter_spec.rb +12 -5
  38. data/spec/active_interaction/filters/string_filter_spec.rb +11 -3
  39. data/spec/active_interaction/filters/symbol_filter_spec.rb +10 -2
  40. data/spec/active_interaction/filters/time_filter_spec.rb +87 -5
  41. data/spec/active_interaction/grouped_input_spec.rb +19 -0
  42. data/spec/active_interaction/modules/input_processor_spec.rb +75 -0
  43. data/spec/support/filters.rb +6 -0
  44. metadata +16 -1
@@ -0,0 +1,70 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ActiveInteraction::DecimalFilter, :filter do
6
+ include_context 'filters'
7
+ it_behaves_like 'a filter'
8
+
9
+ shared_context 'with digits' do
10
+ let(:digits) { 4 }
11
+
12
+ before do
13
+ options.merge!(digits: digits)
14
+ end
15
+ end
16
+
17
+ describe '#cast' do
18
+ let(:result) { filter.cast(value) }
19
+
20
+ context 'with a Float' do
21
+ let(:value) { rand }
22
+
23
+ it 'returns the BigDecimal' do
24
+ expect(result).to eql BigDecimal.new(value, 0)
25
+ end
26
+
27
+ context 'with :digits option' do
28
+ include_context 'with digits'
29
+
30
+ let(:value) { 1.23456789 }
31
+
32
+ it 'returns BigDecimal with given digits' do
33
+ expect(result).to eql BigDecimal.new('1.235')
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'with a Numeric' do
39
+ let(:value) { rand(1 << 16) }
40
+
41
+ it 'returns a BigDecimal' do
42
+ expect(result).to eql BigDecimal.new(value)
43
+ end
44
+ end
45
+
46
+ context 'with a String' do
47
+ let(:value) { rand.to_s }
48
+
49
+ it 'returns a BigDecimal' do
50
+ expect(result).to eql BigDecimal.new(value)
51
+ end
52
+ end
53
+
54
+ context 'with an invalid String' do
55
+ let(:value) { 'invalid' }
56
+
57
+ it 'raises an error' do
58
+ expect do
59
+ result
60
+ end.to raise_error ActiveInteraction::InvalidValueError
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#database_column_type' do
66
+ it 'returns :decimal' do
67
+ expect(filter.database_column_type).to eql :decimal
68
+ end
69
+ end
70
+ end
@@ -7,11 +7,13 @@ describe ActiveInteraction::FileFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
+ let(:result) { filter.cast(value) }
11
+
10
12
  context 'with a File' do
11
13
  let(:value) { File.new(__FILE__) }
12
14
 
13
15
  it 'returns the File' do
14
- expect(filter.cast(value)).to eql value
16
+ expect(result).to eql value
15
17
  end
16
18
  end
17
19
 
@@ -19,7 +21,7 @@ describe ActiveInteraction::FileFilter, :filter do
19
21
  let(:value) { Tempfile.new(SecureRandom.hex) }
20
22
 
21
23
  it 'returns the Tempfile' do
22
- expect(filter.cast(value)).to eq value
24
+ expect(result).to eq value
23
25
  end
24
26
  end
25
27
 
@@ -27,8 +29,14 @@ describe ActiveInteraction::FileFilter, :filter do
27
29
  let(:value) { double(tempfile: Tempfile.new(SecureRandom.hex)) }
28
30
 
29
31
  it 'returns the Tempfile' do
30
- expect(filter.cast(value)).to eq value.tempfile
32
+ expect(result).to eq value.tempfile
31
33
  end
32
34
  end
33
35
  end
36
+
37
+ describe '#database_column_type' do
38
+ it 'returns :file' do
39
+ expect(filter.database_column_type).to eql :file
40
+ end
41
+ end
34
42
  end
@@ -7,11 +7,13 @@ describe ActiveInteraction::FloatFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
+ let(:result) { filter.cast(value) }
11
+
10
12
  context 'with a Float' do
11
13
  let(:value) { rand }
12
14
 
13
15
  it 'returns the Float' do
14
- expect(filter.cast(value)).to eql value
16
+ expect(result).to eql value
15
17
  end
16
18
  end
17
19
 
@@ -19,7 +21,7 @@ describe ActiveInteraction::FloatFilter, :filter do
19
21
  let(:value) { rand(1 << 16) }
20
22
 
21
23
  it 'returns a Float' do
22
- expect(filter.cast(value)).to eql value.to_f
24
+ expect(result).to eql value.to_f
23
25
  end
24
26
  end
25
27
 
@@ -27,7 +29,7 @@ describe ActiveInteraction::FloatFilter, :filter do
27
29
  let(:value) { rand.to_s }
28
30
 
29
31
  it 'returns a Float' do
30
- expect(filter.cast(value)).to eql Float(value)
32
+ expect(result).to eql Float(value)
31
33
  end
32
34
  end
33
35
 
@@ -36,9 +38,15 @@ describe ActiveInteraction::FloatFilter, :filter do
36
38
 
37
39
  it 'raises an error' do
38
40
  expect do
39
- filter.cast(value)
41
+ result
40
42
  end.to raise_error ActiveInteraction::InvalidValueError
41
43
  end
42
44
  end
43
45
  end
46
+
47
+ describe '#database_column_type' do
48
+ it 'returns :float' do
49
+ expect(filter.database_column_type).to eql :float
50
+ end
51
+ end
44
52
  end
@@ -15,11 +15,13 @@ describe ActiveInteraction::HashFilter, :filter do
15
15
  end
16
16
 
17
17
  describe '#cast' do
18
+ let(:result) { filter.cast(value) }
19
+
18
20
  context 'with a Hash' do
19
21
  let(:value) { {} }
20
22
 
21
23
  it 'returns the Hash' do
22
- expect(filter.cast(value)).to eql value
24
+ expect(result).to eql value
23
25
  end
24
26
  end
25
27
 
@@ -27,7 +29,7 @@ describe ActiveInteraction::HashFilter, :filter do
27
29
  let(:value) { { a: {} } }
28
30
 
29
31
  it 'returns an empty Hash' do
30
- expect(filter.cast(value)).to eql({})
32
+ expect(result).to eql({})
31
33
  end
32
34
  end
33
35
 
@@ -38,7 +40,7 @@ describe ActiveInteraction::HashFilter, :filter do
38
40
  let(:value) { { a: {} } }
39
41
 
40
42
  it 'returns the Hash' do
41
- expect(filter.cast(value)).to eql value
43
+ expect(result).to eql value
42
44
  end
43
45
 
44
46
  context 'with String keys' do
@@ -47,7 +49,7 @@ describe ActiveInteraction::HashFilter, :filter do
47
49
  end
48
50
 
49
51
  it 'does not raise an error' do
50
- expect { filter.cast(value) }.to_not raise_error
52
+ expect { result }.to_not raise_error
51
53
  end
52
54
  end
53
55
  end
@@ -59,13 +61,13 @@ describe ActiveInteraction::HashFilter, :filter do
59
61
 
60
62
  it 'raises an error' do
61
63
  expect do
62
- filter.cast(value)
64
+ result
63
65
  end.to raise_error ActiveInteraction::InvalidNestedValueError
64
66
  end
65
67
 
66
68
  it 'populates the error' do
67
69
  begin
68
- filter.cast(value)
70
+ result
69
71
  rescue ActiveInteraction::InvalidNestedValueError => e
70
72
  expect(e.filter_name).to eql k
71
73
  expect(e.input_value).to eql v
@@ -82,11 +84,11 @@ describe ActiveInteraction::HashFilter, :filter do
82
84
  end
83
85
 
84
86
  it 'symbolizes String keys' do
85
- expect(filter.cast(value)).to have_key :a
87
+ expect(result).to have_key :a
86
88
  end
87
89
 
88
90
  it 'leaves other keys alone' do
89
- expect(filter.cast(value)).to have_key 1
91
+ expect(result).to have_key 1
90
92
  end
91
93
  end
92
94
  end
@@ -114,4 +116,10 @@ describe ActiveInteraction::HashFilter, :filter do
114
116
  end
115
117
  end
116
118
  end
119
+
120
+ describe '#database_column_type' do
121
+ it 'returns :string' do
122
+ expect(filter.database_column_type).to eql :string
123
+ end
124
+ end
117
125
  end
@@ -7,11 +7,13 @@ describe ActiveInteraction::IntegerFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
+ let(:result) { filter.cast(value) }
11
+
10
12
  context 'with an Integer' do
11
13
  let(:value) { rand(1 << 16) }
12
14
 
13
15
  it 'returns the Integer' do
14
- expect(filter.cast(value)).to eql value
16
+ expect(result).to eql value
15
17
  end
16
18
  end
17
19
 
@@ -19,7 +21,7 @@ describe ActiveInteraction::IntegerFilter, :filter do
19
21
  let(:value) { rand(1 << 16) + rand }
20
22
 
21
23
  it 'returns an Integer' do
22
- expect(filter.cast(value)).to eql value.to_i
24
+ expect(result).to eql value.to_i
23
25
  end
24
26
  end
25
27
 
@@ -27,7 +29,7 @@ describe ActiveInteraction::IntegerFilter, :filter do
27
29
  let(:value) { rand(1 << 16).to_s }
28
30
 
29
31
  it 'returns an Integer' do
30
- expect(filter.cast(value)).to eql Integer(value)
32
+ expect(result).to eql Integer(value)
31
33
  end
32
34
  end
33
35
 
@@ -36,9 +38,15 @@ describe ActiveInteraction::IntegerFilter, :filter do
36
38
 
37
39
  it 'raises an error' do
38
40
  expect do
39
- filter.cast(value)
41
+ result
40
42
  end.to raise_error ActiveInteraction::InvalidValueError
41
43
  end
42
44
  end
43
45
  end
46
+
47
+ describe '#database_column_type' do
48
+ it 'returns :integer' do
49
+ expect(filter.database_column_type).to eql :integer
50
+ end
51
+ end
44
52
  end
@@ -14,14 +14,15 @@ describe ActiveInteraction::ModelFilter, :filter do
14
14
 
15
15
  describe '#cast' do
16
16
  let(:value) { Model.new }
17
+ let(:result) { filter.cast(value) }
17
18
 
18
19
  context 'with class as a Class' do
19
20
  it 'returns the instance' do
20
- expect(filter.cast(value)).to eql value
21
+ expect(result).to eql value
21
22
  end
22
23
 
23
24
  it 'handles reconstantizing' do
24
- expect(filter.cast(value)).to eql value
25
+ expect(result).to eql value
25
26
 
26
27
  Object.send(:remove_const, :Model)
27
28
  class Model; end
@@ -69,7 +70,7 @@ describe ActiveInteraction::ModelFilter, :filter do
69
70
  end
70
71
 
71
72
  it 'returns the instance' do
72
- expect(filter.cast(value)).to eql value
73
+ expect(result).to eql value
73
74
  end
74
75
  end
75
76
 
@@ -79,7 +80,7 @@ describe ActiveInteraction::ModelFilter, :filter do
79
80
  end
80
81
 
81
82
  it 'returns the instance' do
82
- expect(filter.cast(value)).to eql value
83
+ expect(result).to eql value
83
84
  end
84
85
  end
85
86
 
@@ -90,9 +91,15 @@ describe ActiveInteraction::ModelFilter, :filter do
90
91
 
91
92
  it 'raises an error' do
92
93
  expect do
93
- filter.cast(value)
94
+ result
94
95
  end.to raise_error ActiveInteraction::InvalidClassError
95
96
  end
96
97
  end
97
98
  end
99
+
100
+ describe '#database_column_type' do
101
+ it 'returns :string' do
102
+ expect(filter.database_column_type).to eql :string
103
+ end
104
+ end
98
105
  end
@@ -13,11 +13,13 @@ describe ActiveInteraction::StringFilter, :filter do
13
13
  end
14
14
 
15
15
  describe '#cast' do
16
+ let(:result) { filter.cast(value) }
17
+
16
18
  context 'with a String' do
17
19
  let(:value) { SecureRandom.hex }
18
20
 
19
21
  it 'returns the String' do
20
- expect(filter.cast(value)).to eql value
22
+ expect(result).to eql value
21
23
  end
22
24
  end
23
25
 
@@ -25,16 +27,22 @@ describe ActiveInteraction::StringFilter, :filter do
25
27
  let(:value) { " #{SecureRandom.hex} " }
26
28
 
27
29
  it 'returns the stripped string' do
28
- expect(filter.cast(value)).to eql value.strip
30
+ expect(result).to eql value.strip
29
31
  end
30
32
 
31
33
  context 'without strip' do
32
34
  include_context 'without strip'
33
35
 
34
36
  it 'returns the String' do
35
- expect(filter.cast(value)).to eql value
37
+ expect(result).to eql value
36
38
  end
37
39
  end
38
40
  end
39
41
  end
42
+
43
+ describe '#database_column_type' do
44
+ it 'returns :string' do
45
+ expect(filter.database_column_type).to eql :string
46
+ end
47
+ end
40
48
  end
@@ -7,11 +7,13 @@ describe ActiveInteraction::SymbolFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
+ let(:result) { filter.cast(value) }
11
+
10
12
  context 'with a Symbol' do
11
13
  let(:value) { SecureRandom.hex.to_sym }
12
14
 
13
15
  it 'returns the Symbol' do
14
- expect(filter.cast(value)).to eql value
16
+ expect(result).to eql value
15
17
  end
16
18
  end
17
19
 
@@ -19,8 +21,14 @@ describe ActiveInteraction::SymbolFilter, :filter do
19
21
  let(:value) { SecureRandom.hex }
20
22
 
21
23
  it 'returns a Symbol' do
22
- expect(filter.cast(value)).to eql value.to_sym
24
+ expect(result).to eql value.to_sym
23
25
  end
24
26
  end
25
27
  end
28
+
29
+ describe '#database_column_type' do
30
+ it 'returns :string' do
31
+ expect(filter.database_column_type).to eql :string
32
+ end
33
+ end
26
34
  end
@@ -15,11 +15,13 @@ describe ActiveInteraction::TimeFilter, :filter do
15
15
  end
16
16
 
17
17
  describe '#cast' do
18
+ let(:result) { filter.cast(value) }
19
+
18
20
  context 'with a Time' do
19
21
  let(:value) { Time.new }
20
22
 
21
23
  it 'returns the Time' do
22
- expect(filter.cast(value)).to eql value
24
+ expect(result).to eql value
23
25
  end
24
26
  end
25
27
 
@@ -27,7 +29,7 @@ describe ActiveInteraction::TimeFilter, :filter do
27
29
  let(:value) { '2011-12-13 14:15:16 +1718' }
28
30
 
29
31
  it 'returns a Time' do
30
- expect(filter.cast(value)).to eql Time.parse(value)
32
+ expect(result).to eql Time.parse(value)
31
33
  end
32
34
 
33
35
  context 'with format' do
@@ -36,7 +38,7 @@ describe ActiveInteraction::TimeFilter, :filter do
36
38
  let(:value) { '13/12/2011 14:15:16 +1718' }
37
39
 
38
40
  it 'returns a Time' do
39
- expect(filter.cast(value)).to eql Time.strptime(value, format)
41
+ expect(result).to eql Time.strptime(value, format)
40
42
  end
41
43
  end
42
44
  end
@@ -46,7 +48,7 @@ describe ActiveInteraction::TimeFilter, :filter do
46
48
 
47
49
  it 'raises an error' do
48
50
  expect do
49
- filter.cast(value)
51
+ result
50
52
  end.to raise_error ActiveInteraction::InvalidValueError
51
53
  end
52
54
 
@@ -55,10 +57,90 @@ describe ActiveInteraction::TimeFilter, :filter do
55
57
 
56
58
  it do
57
59
  expect do
58
- filter.cast(value)
60
+ result
61
+ end.to raise_error ActiveInteraction::InvalidValueError
62
+ end
63
+ end
64
+ end
65
+
66
+ context 'with a GroupedInput' do
67
+ let(:year) { 2012 }
68
+ let(:month) { 1 }
69
+ let(:day) { 2 }
70
+ let(:hour) { 3 }
71
+ let(:min) { 4 }
72
+ let(:sec) { 5 }
73
+ let(:value) do
74
+ ActiveInteraction::GroupedInput.new(
75
+ '1' => year.to_s,
76
+ '2' => month.to_s,
77
+ '3' => day.to_s,
78
+ '4' => hour.to_s,
79
+ '5' => min.to_s,
80
+ '6' => sec.to_s
81
+ )
82
+ end
83
+
84
+ it 'returns a Time' do
85
+ expect(
86
+ result
87
+ ).to eql Time.new(year, month, day, hour, min, sec)
88
+ end
89
+ end
90
+
91
+ context 'with an invalid GroupedInput' do
92
+ context 'empty' do
93
+ let(:value) { ActiveInteraction::GroupedInput.new }
94
+
95
+ it 'raises an error' do
96
+ expect do
97
+ result
98
+ end.to raise_error ActiveInteraction::InvalidValueError
99
+ end
100
+ end
101
+
102
+ context 'partial inputs' do
103
+ let(:value) do
104
+ ActiveInteraction::GroupedInput.new(
105
+ '2' => '1'
106
+ )
107
+ end
108
+
109
+ it 'raises an error' do
110
+ expect do
111
+ result
59
112
  end.to raise_error ActiveInteraction::InvalidValueError
60
113
  end
61
114
  end
62
115
  end
63
116
  end
117
+
118
+ describe '#database_column_type' do
119
+ it 'returns :datetime' do
120
+ expect(filter.database_column_type).to eql :datetime
121
+ end
122
+ end
123
+
124
+ describe '#default' do
125
+ context 'with a GroupedInput' do
126
+ before do
127
+ options.merge!(
128
+ default: ActiveInteraction::GroupedInput.new(
129
+ '1' => '2012',
130
+ '2' => '1',
131
+ '3' => '2',
132
+ '4' => '3',
133
+ '5' => '4',
134
+ '6' => '5'
135
+ )
136
+ )
137
+ end
138
+
139
+ it 'raises an error' do
140
+ expect do
141
+ filter.default
142
+ end.to raise_error ActiveInteraction::InvalidDefaultError
143
+ end
144
+ end
145
+ end
64
146
  end