virtus 1.0.3 → 1.0.4

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -5
  3. data/Changelog.md +7 -1
  4. data/Gemfile +14 -5
  5. data/README.md +40 -19
  6. data/Rakefile +13 -3
  7. data/lib/virtus/configuration.rb +10 -5
  8. data/lib/virtus/version.rb +1 -1
  9. data/spec/integration/collection_member_coercion_spec.rb +34 -13
  10. data/spec/integration/hash_attributes_coercion_spec.rb +5 -5
  11. data/spec/shared/freeze_method_behavior.rb +5 -2
  12. data/spec/shared/idempotent_method_behaviour.rb +1 -1
  13. data/spec/shared/options_class_method.rb +3 -3
  14. data/spec/spec_helper.rb +3 -18
  15. data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +3 -3
  16. data/spec/unit/virtus/attribute/boolean/value_coerced_predicate_spec.rb +3 -3
  17. data/spec/unit/virtus/attribute/class_methods/build_spec.rb +48 -24
  18. data/spec/unit/virtus/attribute/class_methods/coerce_spec.rb +2 -2
  19. data/spec/unit/virtus/attribute/coerce_spec.rb +9 -9
  20. data/spec/unit/virtus/attribute/coercible_predicate_spec.rb +2 -2
  21. data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +2 -2
  22. data/spec/unit/virtus/attribute/collection/coerce_spec.rb +5 -5
  23. data/spec/unit/virtus/attribute/custom_collection_spec.rb +8 -2
  24. data/spec/unit/virtus/attribute/defined_spec.rb +2 -2
  25. data/spec/unit/virtus/attribute/embedded_value/class_methods/build_spec.rb +30 -15
  26. data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +25 -11
  27. data/spec/unit/virtus/attribute/get_spec.rb +2 -2
  28. data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +7 -7
  29. data/spec/unit/virtus/attribute/hash/coerce_spec.rb +9 -9
  30. data/spec/unit/virtus/attribute/lazy_predicate_spec.rb +2 -2
  31. data/spec/unit/virtus/attribute/rename_spec.rb +6 -3
  32. data/spec/unit/virtus/attribute/required_predicate_spec.rb +2 -2
  33. data/spec/unit/virtus/attribute/set_default_value_spec.rb +43 -10
  34. data/spec/unit/virtus/attribute/set_spec.rb +1 -1
  35. data/spec/unit/virtus/attribute/value_coerced_predicate_spec.rb +2 -2
  36. data/spec/unit/virtus/attribute_set/append_spec.rb +2 -2
  37. data/spec/unit/virtus/attribute_set/define_reader_method_spec.rb +12 -11
  38. data/spec/unit/virtus/attribute_set/define_writer_method_spec.rb +13 -12
  39. data/spec/unit/virtus/attribute_set/each_spec.rb +3 -3
  40. data/spec/unit/virtus/attribute_set/element_reference_spec.rb +1 -1
  41. data/spec/unit/virtus/attribute_set/element_set_spec.rb +2 -2
  42. data/spec/unit/virtus/attribute_set/merge_spec.rb +2 -2
  43. data/spec/unit/virtus/attribute_set/reset_spec.rb +17 -8
  44. data/spec/unit/virtus/attribute_spec.rb +4 -4
  45. data/spec/unit/virtus/element_reader_spec.rb +1 -1
  46. data/spec/unit/virtus/freeze_spec.rb +10 -3
  47. data/spec/unit/virtus/model_spec.rb +35 -4
  48. data/spec/unit/virtus/set_default_attributes_spec.rb +10 -3
  49. data/spec/unit/virtus/value_object_spec.rb +13 -3
  50. data/virtus.gemspec +6 -4
  51. metadata +16 -8
  52. data/Gemfile.devtools +0 -71
  53. data/config/flay.yml +0 -3
  54. data/config/flog.yml +0 -2
  55. data/config/mutant.yml +0 -15
  56. data/config/reek.yml +0 -146
  57. data/config/yardstick.yml +0 -2
@@ -8,18 +8,18 @@ describe Virtus::Attribute, '.build' do
8
8
  let(:options) { {} }
9
9
 
10
10
  shared_examples_for 'a valid attribute instance' do
11
- it { should be_instance_of(Virtus::Attribute) }
11
+ it { is_expected.to be_instance_of(Virtus::Attribute) }
12
12
 
13
- it { should be_frozen }
13
+ it { is_expected.to be_frozen }
14
14
  end
15
15
 
16
16
  context 'without options' do
17
17
  it_behaves_like 'a valid attribute instance'
18
18
 
19
- it { should be_coercible }
20
- it { should be_public_reader }
21
- it { should be_public_writer }
22
- it { should_not be_lazy }
19
+ it { is_expected.to be_coercible }
20
+ it { is_expected.to be_public_reader }
21
+ it { is_expected.to be_public_writer }
22
+ it { is_expected.not_to be_lazy }
23
23
 
24
24
  it 'sets up a coercer' do
25
25
  expect(subject.options[:coerce]).to be(true)
@@ -30,7 +30,10 @@ describe Virtus::Attribute, '.build' do
30
30
  context 'when name is passed as a string' do
31
31
  let(:name) { 'something' }
32
32
 
33
- its(:name) { should be(:something) }
33
+ describe '#name' do
34
+ subject { super().name }
35
+ it { is_expected.to be(:something) }
36
+ end
34
37
  end
35
38
 
36
39
  context 'when coercion is turned off in options' do
@@ -38,7 +41,7 @@ describe Virtus::Attribute, '.build' do
38
41
 
39
42
  it_behaves_like 'a valid attribute instance'
40
43
 
41
- it { should_not be_coercible }
44
+ it { is_expected.not_to be_coercible }
42
45
  end
43
46
 
44
47
  context 'when options specify reader visibility' do
@@ -46,8 +49,8 @@ describe Virtus::Attribute, '.build' do
46
49
 
47
50
  it_behaves_like 'a valid attribute instance'
48
51
 
49
- it { should_not be_public_reader }
50
- it { should be_public_writer }
52
+ it { is_expected.not_to be_public_reader }
53
+ it { is_expected.to be_public_writer }
51
54
  end
52
55
 
53
56
  context 'when options specify writer visibility' do
@@ -55,8 +58,8 @@ describe Virtus::Attribute, '.build' do
55
58
 
56
59
  it_behaves_like 'a valid attribute instance'
57
60
 
58
- it { should be_public_reader }
59
- it { should_not be_public_writer }
61
+ it { is_expected.to be_public_reader }
62
+ it { is_expected.not_to be_public_writer }
60
63
  end
61
64
 
62
65
  context 'when options specify lazy accessor' do
@@ -64,7 +67,7 @@ describe Virtus::Attribute, '.build' do
64
67
 
65
68
  it_behaves_like 'a valid attribute instance'
66
69
 
67
- it { should be_lazy }
70
+ it { is_expected.to be_lazy }
68
71
  end
69
72
 
70
73
  context 'when options specify strict mode' do
@@ -72,7 +75,7 @@ describe Virtus::Attribute, '.build' do
72
75
 
73
76
  it_behaves_like 'a valid attribute instance'
74
77
 
75
- it { should be_strict }
78
+ it { is_expected.to be_strict }
76
79
  end
77
80
 
78
81
  context 'when type is a string' do
@@ -80,7 +83,10 @@ describe Virtus::Attribute, '.build' do
80
83
 
81
84
  it_behaves_like 'a valid attribute instance'
82
85
 
83
- its(:type) { should be(Axiom::Types::Integer) }
86
+ describe '#type' do
87
+ subject { super().type }
88
+ it { is_expected.to be(Axiom::Types::Integer) }
89
+ end
84
90
  end
85
91
 
86
92
  context 'when type is a range' do
@@ -88,7 +94,10 @@ describe Virtus::Attribute, '.build' do
88
94
 
89
95
  it_behaves_like 'a valid attribute instance'
90
96
 
91
- its(:type) { should be(Axiom::Types.infer(Range)) }
97
+ describe '#type' do
98
+ subject { super().type }
99
+ it { is_expected.to be(Axiom::Types.infer(Range)) }
100
+ end
92
101
  end
93
102
 
94
103
  context 'when type is a symbol of an existing class constant' do
@@ -96,7 +105,10 @@ describe Virtus::Attribute, '.build' do
96
105
 
97
106
  it_behaves_like 'a valid attribute instance'
98
107
 
99
- its(:type) { should be(Axiom::Types::String) }
108
+ describe '#type' do
109
+ subject { super().type }
110
+ it { is_expected.to be(Axiom::Types::String) }
111
+ end
100
112
  end
101
113
 
102
114
  context 'when type is an axiom type' do
@@ -104,7 +116,10 @@ describe Virtus::Attribute, '.build' do
104
116
 
105
117
  it_behaves_like 'a valid attribute instance'
106
118
 
107
- its(:type) { should be(type) }
119
+ describe '#type' do
120
+ subject { super().type }
121
+ it { is_expected.to be(type) }
122
+ end
108
123
  end
109
124
 
110
125
  context 'when custom attribute class exists for a given primitive' do
@@ -115,9 +130,12 @@ describe Virtus::Attribute, '.build' do
115
130
  attribute.primitive(type)
116
131
  end
117
132
 
118
- it { should be_instance_of(attribute) }
133
+ it { is_expected.to be_instance_of(attribute) }
119
134
 
120
- its(:type) { should be(Axiom::Types::Object) }
135
+ describe '#type' do
136
+ subject { super().type }
137
+ it { is_expected.to be(Axiom::Types::Object) }
138
+ end
121
139
  end
122
140
 
123
141
  context 'when custom attribute class exists for a given array with member coercion defined' do
@@ -128,9 +146,12 @@ describe Virtus::Attribute, '.build' do
128
146
  attribute.primitive(type.class)
129
147
  end
130
148
 
131
- it { should be_instance_of(attribute) }
149
+ it { is_expected.to be_instance_of(attribute) }
132
150
 
133
- its(:type) { should be < Axiom::Types::Collection }
151
+ describe '#type' do
152
+ subject { super().type }
153
+ it { is_expected.to be < Axiom::Types::Collection }
154
+ end
134
155
  end
135
156
 
136
157
  context 'when custom collection-like attribute class exists for a given enumerable primitive' do
@@ -141,8 +162,11 @@ describe Virtus::Attribute, '.build' do
141
162
  attribute.primitive(type)
142
163
  end
143
164
 
144
- it { should be_instance_of(attribute) }
165
+ it { is_expected.to be_instance_of(attribute) }
145
166
 
146
- its(:type) { should be < Axiom::Types::Collection }
167
+ describe '#type' do
168
+ subject { super().type }
169
+ it { is_expected.to be < Axiom::Types::Collection }
170
+ end
147
171
  end
148
172
  end
@@ -19,7 +19,7 @@ describe Virtus::Attribute, '.coerce' do
19
19
  described_class.coerce(true)
20
20
  end
21
21
 
22
- it { should be(true) }
22
+ it { is_expected.to be(true) }
23
23
  end
24
24
 
25
25
  context 'when it is set to false' do
@@ -27,6 +27,6 @@ describe Virtus::Attribute, '.coerce' do
27
27
  described_class.coerce(false)
28
28
  end
29
29
 
30
- it { should be(false) }
30
+ it { is_expected.to be(false) }
31
31
  end
32
32
  end
@@ -18,7 +18,7 @@ describe Virtus::Attribute, '#coerce' do
18
18
  let(:strict) { false }
19
19
 
20
20
  it 'uses coercer to coerce the input value' do
21
- stub(coercer).call(input) { output }
21
+ mock(coercer).call(input) { output }
22
22
 
23
23
  expect(subject).to be(output)
24
24
 
@@ -30,8 +30,8 @@ describe Virtus::Attribute, '#coerce' do
30
30
  let(:strict) { true }
31
31
 
32
32
  it 'uses coercer to coerce the input value' do
33
- stub(coercer).call(input) { output }
34
- stub(coercer).success?(String, output) { true }
33
+ mock(coercer).call(input) { output }
34
+ mock(coercer).success?(String, output) { true }
35
35
 
36
36
  expect(subject).to be(output)
37
37
 
@@ -44,8 +44,8 @@ describe Virtus::Attribute, '#coerce' do
44
44
  let(:input) { nil }
45
45
 
46
46
  it 'returns nil' do
47
- stub(coercer).call(input) { input }
48
- stub(coercer).success?(String, input) { false }
47
+ mock(coercer).call(input) { input }
48
+ mock(coercer).success?(String, input) { false }
49
49
 
50
50
  expect(subject).to be(nil)
51
51
 
@@ -58,8 +58,8 @@ describe Virtus::Attribute, '#coerce' do
58
58
  let(:input) { nil }
59
59
 
60
60
  it 'returns raises error' do
61
- stub(coercer).call(input) { input }
62
- stub(coercer).success?(String, input) { false }
61
+ mock(coercer).call(input) { input }
62
+ mock(coercer).success?(String, input) { false }
63
63
 
64
64
  expect { subject }.to raise_error(Virtus::CoercionError)
65
65
 
@@ -69,8 +69,8 @@ describe Virtus::Attribute, '#coerce' do
69
69
  end
70
70
 
71
71
  it 'raises error when input was not coerced' do
72
- stub(coercer).call(input) { input }
73
- stub(coercer).success?(String, input) { false }
72
+ mock(coercer).call(input) { input }
73
+ mock(coercer).success?(String, input) { false }
74
74
 
75
75
  expect { subject }.to raise_error(Virtus::CoercionError)
76
76
 
@@ -9,12 +9,12 @@ describe Virtus::Attribute, '#coercible?' do
9
9
  context 'when :coerce is set to true' do
10
10
  let(:coerce) { true }
11
11
 
12
- it { should be(true) }
12
+ it { is_expected.to be(true) }
13
13
  end
14
14
 
15
15
  context 'when :coerce is set to false' do
16
16
  let(:coerce) { false }
17
17
 
18
- it { should be(false) }
18
+ it { is_expected.to be(false) }
19
19
  end
20
20
  end
@@ -6,9 +6,9 @@ describe Virtus::Attribute, '.build' do
6
6
  let(:options) { {} }
7
7
 
8
8
  shared_examples_for 'a valid collection attribute instance' do
9
- it { should be_instance_of(Virtus::Attribute::Collection) }
9
+ it { is_expected.to be_instance_of(Virtus::Attribute::Collection) }
10
10
 
11
- it { should be_frozen }
11
+ it { is_expected.to be_frozen }
12
12
  end
13
13
 
14
14
  context 'when type is Array' do
@@ -16,10 +16,10 @@ describe Virtus::Attribute::Collection, '#coerce' do
16
16
  }
17
17
 
18
18
  it 'uses coercer to coerce members' do
19
- stub(coercer).call(input) { input }
20
- stub(member_type).finalize { member_type }
21
- stub(member_type).coerce('1') { 1 }
22
- stub(member_type).coerce('2') { 2 }
19
+ mock(coercer).call(input) { input }
20
+ mock(member_type).finalize { member_type }
21
+ mock(member_type).coerce('1') { 1 }
22
+ mock(member_type).coerce('2') { 2 }
23
23
 
24
24
  expect(subject).to eq([1, 2])
25
25
 
@@ -66,7 +66,7 @@ describe Virtus::Attribute::Collection, '#coerce' do
66
66
  }
67
67
 
68
68
  it 'returns nil' do
69
- stub(coercer).call(input) { input }
69
+ mock(coercer).call(input) { input }
70
70
 
71
71
  expect(subject).to be(input)
72
72
  end
@@ -12,12 +12,18 @@ describe Virtus::Attribute::Collection, 'custom subclass' do
12
12
  context 'when primitive is set on the attribute subclass' do
13
13
  let(:attribute_class) { Class.new(described_class).primitive(primitive) }
14
14
 
15
- its(:primitive) { should be(primitive) }
15
+ describe '#primitive' do
16
+ subject { super().primitive }
17
+ it { is_expected.to be(primitive) }
18
+ end
16
19
  end
17
20
 
18
21
  context 'when primitive is not set on the attribute subclass' do
19
22
  let(:attribute_class) { Class.new(described_class) }
20
23
 
21
- its(:primitive) { should be(primitive) }
24
+ describe '#primitive' do
25
+ subject { super().primitive }
26
+ it { is_expected.to be(primitive) }
27
+ end
22
28
  end
23
29
  end
@@ -10,11 +10,11 @@ describe Virtus::Attribute, '#defined?' do
10
10
  let(:instance) { model.new }
11
11
 
12
12
  context 'when the attribute value has not been defined' do
13
- it { should be(false) }
13
+ it { is_expected.to be(false) }
14
14
  end
15
15
 
16
16
  context 'when the attribute value has been defined' do
17
17
  before { instance.test = nil }
18
- it { should be(true) }
18
+ it { is_expected.to be(true) }
19
19
  end
20
20
  end
@@ -6,50 +6,65 @@ describe Virtus::Attribute::EmbeddedValue, '.build' do
6
6
  context 'when type is a Virtus.model' do
7
7
  let(:type) { Class.new { include Virtus.model } }
8
8
 
9
- it { should be_frozen }
9
+ it { is_expected.to be_frozen }
10
10
 
11
- it { should be_instance_of(Virtus::Attribute::EmbeddedValue) }
11
+ it { is_expected.to be_instance_of(Virtus::Attribute::EmbeddedValue) }
12
12
 
13
- its(:coercer) { should be_instance_of(described_class::FromOpenStruct) }
13
+ describe '#coercer' do
14
+ subject { super().coercer }
15
+ it { is_expected.to be_instance_of(described_class::FromOpenStruct) }
16
+ end
14
17
  end
15
18
 
16
19
  context 'when type includes Virtus' do
17
20
  let(:type) { Class.new { include Virtus } }
18
21
 
19
- it { should be_frozen }
22
+ it { is_expected.to be_frozen }
20
23
 
21
- it { should be_instance_of(Virtus::Attribute::EmbeddedValue) }
24
+ it { is_expected.to be_instance_of(Virtus::Attribute::EmbeddedValue) }
22
25
 
23
- its(:coercer) { should be_instance_of(described_class::FromOpenStruct) }
26
+ describe '#coercer' do
27
+ subject { super().coercer }
28
+ it { is_expected.to be_instance_of(described_class::FromOpenStruct) }
29
+ end
24
30
  end
25
31
 
26
32
  context 'when type is an OpenStruct subclass' do
27
33
  let(:type) { Class.new(OpenStruct) }
28
34
 
29
- it { should be_frozen }
35
+ it { is_expected.to be_frozen }
30
36
 
31
- it { should be_instance_of(Virtus::Attribute::EmbeddedValue) }
37
+ it { is_expected.to be_instance_of(Virtus::Attribute::EmbeddedValue) }
32
38
 
33
- its(:coercer) { should be_instance_of(described_class::FromOpenStruct) }
39
+ describe '#coercer' do
40
+ subject { super().coercer }
41
+ it { is_expected.to be_instance_of(described_class::FromOpenStruct) }
42
+ end
34
43
  end
35
44
 
36
45
  context 'when type is OpenStruct' do
37
46
  let(:type) { OpenStruct }
38
47
 
39
- it { should be_frozen }
48
+ it { is_expected.to be_frozen }
40
49
 
41
- it { should be_instance_of(Virtus::Attribute::EmbeddedValue) }
50
+ it { is_expected.to be_instance_of(Virtus::Attribute::EmbeddedValue) }
42
51
 
43
- its(:coercer) { should be_instance_of(described_class::FromOpenStruct) }
52
+ describe '#coercer' do
53
+ subject { super().coercer }
54
+ it { is_expected.to be_instance_of(described_class::FromOpenStruct) }
55
+ end
44
56
  end
45
57
 
46
58
  context 'when type is Struct' do
47
59
  let(:type) { Struct.new(:test) }
48
60
 
49
- it { should be_frozen }
61
+ it { is_expected.to be_frozen }
50
62
 
51
- it { should be_instance_of(Virtus::Attribute::EmbeddedValue) }
63
+ it { is_expected.to be_instance_of(Virtus::Attribute::EmbeddedValue) }
52
64
 
53
- its(:coercer) { should be_instance_of(described_class::FromStruct) }
65
+ describe '#coercer' do
66
+ subject { super().coercer }
67
+ it { is_expected.to be_instance_of(described_class::FromStruct) }
68
+ end
54
69
  end
55
70
  end
@@ -12,22 +12,29 @@ describe Virtus::Attribute::EmbeddedValue, '#coerce' do
12
12
  context 'when input is an attribute hash' do
13
13
  let(:input) { Hash[name: 'Piotr', age: 30] }
14
14
 
15
- it { should be_instance_of(model) }
15
+ it { is_expected.to be_instance_of(model) }
16
16
 
17
- its(:name) { should eql('Piotr') }
18
- its(:age) { should eql(30) }
17
+ describe '#name' do
18
+ subject { super().name }
19
+ it { is_expected.to eql('Piotr') }
20
+ end
21
+
22
+ describe '#age' do
23
+ subject { super().age }
24
+ it { is_expected.to eql(30) }
25
+ end
19
26
  end
20
27
 
21
28
  context 'when input is nil' do
22
29
  let(:input) { nil }
23
30
 
24
- it { should be(nil) }
31
+ it { is_expected.to be(nil) }
25
32
  end
26
33
 
27
34
  context 'when input is a model instance' do
28
35
  let(:input) { OpenStruct.new }
29
36
 
30
- it { should be(input) }
37
+ it { is_expected.to be(input) }
31
38
  end
32
39
  end
33
40
 
@@ -37,22 +44,29 @@ describe Virtus::Attribute::EmbeddedValue, '#coerce' do
37
44
  context 'when input is an attribute hash' do
38
45
  let(:input) { ['Piotr', 30] }
39
46
 
40
- it { should be_instance_of(model) }
47
+ it { is_expected.to be_instance_of(model) }
41
48
 
42
- its(:name) { should eql('Piotr') }
43
- its(:age) { should eql(30) }
49
+ describe '#name' do
50
+ subject { super().name }
51
+ it { is_expected.to eql('Piotr') }
52
+ end
53
+
54
+ describe '#age' do
55
+ subject { super().age }
56
+ it { is_expected.to eql(30) }
57
+ end
44
58
  end
45
59
 
46
60
  context 'when input is nil' do
47
61
  let(:input) { nil }
48
62
 
49
- it { should be(nil) }
63
+ it { is_expected.to be(nil) }
50
64
  end
51
65
 
52
66
  context 'when input is a model instance' do
53
67
  let(:input) { model.new('Piotr', 30) }
54
68
 
55
- it { should be(input) }
69
+ it { is_expected.to be(input) }
56
70
  end
57
71
  end
58
72
 
@@ -63,7 +77,7 @@ describe Virtus::Attribute::EmbeddedValue, '#coerce' do
63
77
  context 'when input is coercible' do
64
78
  let(:input) { ['Piotr'] }
65
79
 
66
- it { should eql(model.new('Piotr')) }
80
+ it { is_expected.to eql(model.new('Piotr')) }
67
81
  end
68
82
 
69
83
  context 'when input is not coercible' do