virtus 1.0.4 → 1.0.5
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 +6 -0
- data/README.md +20 -4
- data/lib/virtus.rb +1 -0
- data/lib/virtus/attribute.rb +19 -1
- data/lib/virtus/attribute/builder.rb +5 -4
- data/lib/virtus/attribute/nullify_blank.rb +24 -0
- data/lib/virtus/configuration.rb +5 -0
- data/lib/virtus/version.rb +1 -1
- data/spec/integration/building_module_spec.rb +22 -0
- data/spec/unit/virtus/attribute/class_methods/build_spec.rb +8 -0
- data/spec/unit/virtus/attribute/coerce_spec.rb +49 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a85ace0a75695ebb65294da839a389e5349b660
|
4
|
+
data.tar.gz: 2c8d5150758b6bab5ce1bb8484cdaff11d1fe581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e92ffbfc9ee7b17c58253130ad0e5bdf45857618d04d64d5c8e58b0d3d156deac13d2cc44d3b628f08ec76cdc9bc8634aca2570e987de2cd64e07ffe21fb8d04
|
7
|
+
data.tar.gz: 33db1e4a9040ce6d008062683a6eedcce3632b4854290a114795accad964233094d80f324d1b703487f6f14d6b1510e383dfce32bf7a341f9bf372d95fd37363
|
data/Changelog.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# v1.0.5 2015-03-18
|
2
|
+
|
3
|
+
* [feature] Support for :nullify_blank option when configuring a virtus module (lucasmazza)
|
4
|
+
|
5
|
+
[Compare v1.0.4..v1.0.5](https://github.com/solnic/virtus/compare/v1.0.4...v1.0.5)
|
6
|
+
|
1
7
|
# v1.0.4 2015-01-03
|
2
8
|
|
3
9
|
* [feature] Support for :required option when configuring a virtus module (solnic)
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ Virtus
|
|
10
10
|
|
11
11
|
# Ruby Object Mapper
|
12
12
|
|
13
|
-
[][gem]
|
14
14
|
[][travis]
|
15
15
|
[][gemnasium]
|
16
16
|
[][codeclimate]
|
@@ -60,12 +60,12 @@ class User
|
|
60
60
|
attribute :birthday, DateTime
|
61
61
|
end
|
62
62
|
|
63
|
-
user = User.new(:name => 'Piotr', :age =>
|
64
|
-
user.attributes # => { :name => "Piotr", :age =>
|
63
|
+
user = User.new(:name => 'Piotr', :age => 31)
|
64
|
+
user.attributes # => { :name => "Piotr", :age => 31 }
|
65
65
|
|
66
66
|
user.name # => "Piotr"
|
67
67
|
|
68
|
-
user.age = '
|
68
|
+
user.age = '31' # => 31
|
69
69
|
user.age.class # => Fixnum
|
70
70
|
|
71
71
|
user.birthday = 'November 18th, 1983' # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
|
@@ -508,6 +508,22 @@ end
|
|
508
508
|
User.new :admin => "can't really say if true or false"
|
509
509
|
```
|
510
510
|
|
511
|
+
## Nullify Blank Strings Mode
|
512
|
+
|
513
|
+
If you want to replace empty Strings with `nil` values (since they can't be
|
514
|
+
coerced into the expected type), you can use the `:nullify_blank` option.
|
515
|
+
|
516
|
+
``` ruby
|
517
|
+
class User
|
518
|
+
include Virtus.model(:nullify_blank => true)
|
519
|
+
|
520
|
+
attribute :birthday, Date
|
521
|
+
end
|
522
|
+
|
523
|
+
User.new(:birthday => "").birthday # => nil
|
524
|
+
```
|
525
|
+
|
526
|
+
|
511
527
|
## Building modules with custom configuration
|
512
528
|
|
513
529
|
You can also build Virtus modules that contain their own configuration.
|
data/lib/virtus.rb
CHANGED
@@ -279,6 +279,7 @@ require 'virtus/attribute/accessor'
|
|
279
279
|
require 'virtus/attribute/coercible'
|
280
280
|
require 'virtus/attribute/strict'
|
281
281
|
require 'virtus/attribute/lazy_default'
|
282
|
+
require 'virtus/attribute/nullify_blank'
|
282
283
|
|
283
284
|
require 'virtus/attribute/boolean'
|
284
285
|
require 'virtus/attribute/collection'
|
data/lib/virtus/attribute.rb
CHANGED
@@ -20,12 +20,13 @@ module Virtus
|
|
20
20
|
|
21
21
|
include ::Equalizer.new(:type, :options)
|
22
22
|
|
23
|
-
accept_options :primitive, :accessor, :default, :lazy, :strict, :required, :finalize
|
23
|
+
accept_options :primitive, :accessor, :default, :lazy, :strict, :required, :finalize, :nullify_blank
|
24
24
|
|
25
25
|
strict false
|
26
26
|
required true
|
27
27
|
accessor :public
|
28
28
|
finalize true
|
29
|
+
nullify_blank false
|
29
30
|
|
30
31
|
# @see Virtus.coerce
|
31
32
|
#
|
@@ -176,6 +177,23 @@ module Virtus
|
|
176
177
|
kind_of?(Strict)
|
177
178
|
end
|
178
179
|
|
180
|
+
# Return if the attribute is in the nullify blank coercion mode
|
181
|
+
#
|
182
|
+
# @example
|
183
|
+
#
|
184
|
+
# attr = Virtus::Attribute.build(String, :nullify_blank => true)
|
185
|
+
# attr.nullify_blank? # => true
|
186
|
+
#
|
187
|
+
# attr = Virtus::Attribute.build(String, :nullify_blank => false)
|
188
|
+
# attr.nullify_blank? # => false
|
189
|
+
#
|
190
|
+
# @return [Boolean]
|
191
|
+
#
|
192
|
+
# @api public
|
193
|
+
def nullify_blank?
|
194
|
+
kind_of?(NullifyBlank)
|
195
|
+
end
|
196
|
+
|
179
197
|
# Return if the attribute is accepts nil values as valid coercion output
|
180
198
|
#
|
181
199
|
# @example
|
@@ -160,10 +160,11 @@ module Virtus
|
|
160
160
|
def initialize_attribute
|
161
161
|
@attribute = klass.new(type, options)
|
162
162
|
|
163
|
-
@attribute.extend(Accessor)
|
164
|
-
@attribute.extend(Coercible)
|
165
|
-
@attribute.extend(
|
166
|
-
@attribute.extend(
|
163
|
+
@attribute.extend(Accessor) if options[:name]
|
164
|
+
@attribute.extend(Coercible) if options[:coerce]
|
165
|
+
@attribute.extend(NullifyBlank) if options[:nullify_blank]
|
166
|
+
@attribute.extend(Strict) if options[:strict]
|
167
|
+
@attribute.extend(LazyDefault) if options[:lazy]
|
167
168
|
|
168
169
|
@attribute.finalize if options[:finalize]
|
169
170
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
# Attribute extension which nullifies blank attributes when coercion failed
|
5
|
+
#
|
6
|
+
module NullifyBlank
|
7
|
+
|
8
|
+
# @see [Attribute#coerce]
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
def coerce(input)
|
12
|
+
output = super
|
13
|
+
|
14
|
+
if !value_coerced?(output) && input.to_s.empty?
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
output
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end # NullifyBlank
|
22
|
+
|
23
|
+
end # Attribute
|
24
|
+
end # Virtus
|
data/lib/virtus/configuration.rb
CHANGED
@@ -12,6 +12,9 @@ module Virtus
|
|
12
12
|
# Access the strict setting for this instance
|
13
13
|
attr_accessor :strict
|
14
14
|
|
15
|
+
# Access the nullify_blank setting for this instance
|
16
|
+
attr_accessor :nullify_blank
|
17
|
+
|
15
18
|
# Access the required setting for this instance
|
16
19
|
attr_accessor :required
|
17
20
|
|
@@ -30,6 +33,7 @@ module Virtus
|
|
30
33
|
@finalize = options.fetch(:finalize, true)
|
31
34
|
@coerce = options.fetch(:coerce, true)
|
32
35
|
@strict = options.fetch(:strict, false)
|
36
|
+
@nullify_blank = options.fetch(:nullify_blank, false)
|
33
37
|
@required = options.fetch(:required, true)
|
34
38
|
@constructor = options.fetch(:constructor, true)
|
35
39
|
@mass_assignment = options.fetch(:mass_assignment, true)
|
@@ -59,6 +63,7 @@ module Virtus
|
|
59
63
|
{ :coerce => coerce,
|
60
64
|
:finalize => finalize,
|
61
65
|
:strict => strict,
|
66
|
+
:nullify_blank => nullify_blank,
|
62
67
|
:required => required,
|
63
68
|
:configured_coercer => coercer }.freeze
|
64
69
|
end
|
data/lib/virtus/version.rb
CHANGED
@@ -19,6 +19,10 @@ describe 'I can create a Virtus module' do
|
|
19
19
|
config.strict = true
|
20
20
|
}
|
21
21
|
|
22
|
+
BlankModule = Virtus.model { |config|
|
23
|
+
config.nullify_blank = true
|
24
|
+
}
|
25
|
+
|
22
26
|
class NoncoercedUser
|
23
27
|
include NoncoercingModule
|
24
28
|
|
@@ -39,6 +43,13 @@ describe 'I can create a Virtus module' do
|
|
39
43
|
attribute :stuff, Hash
|
40
44
|
attribute :happy, Boolean, :strict => false
|
41
45
|
end
|
46
|
+
|
47
|
+
class BlankModel
|
48
|
+
include BlankModule
|
49
|
+
|
50
|
+
attribute :stuff, Hash
|
51
|
+
attribute :happy, Boolean, :nullify_blank => false
|
52
|
+
end
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
@@ -65,4 +76,15 @@ describe 'I can create a Virtus module' do
|
|
65
76
|
|
66
77
|
expect(model.happy).to eql('foo')
|
67
78
|
end
|
79
|
+
|
80
|
+
specify 'including a custom module with nullify blank enabled' do
|
81
|
+
model = Examples::BlankModel.new
|
82
|
+
|
83
|
+
model.stuff = ''
|
84
|
+
expect(model.stuff).to be_nil
|
85
|
+
|
86
|
+
model.happy = 'foo'
|
87
|
+
|
88
|
+
expect(model.happy).to eql('foo')
|
89
|
+
end
|
68
90
|
end
|
@@ -78,6 +78,14 @@ describe Virtus::Attribute, '.build' do
|
|
78
78
|
it { is_expected.to be_strict }
|
79
79
|
end
|
80
80
|
|
81
|
+
context 'when options specify nullify blank mode' do
|
82
|
+
let(:options) { { :nullify_blank => true } }
|
83
|
+
|
84
|
+
it_behaves_like 'a valid attribute instance'
|
85
|
+
|
86
|
+
it { is_expected.to be_nullify_blank }
|
87
|
+
end
|
88
|
+
|
81
89
|
context 'when type is a string' do
|
82
90
|
let(:type) { 'Integer' }
|
83
91
|
|
@@ -7,10 +7,11 @@ describe Virtus::Attribute, '#coerce' do
|
|
7
7
|
|
8
8
|
let(:object) {
|
9
9
|
described_class.build(String,
|
10
|
-
:coercer => coercer, :strict => strict, :required => required)
|
10
|
+
:coercer => coercer, :strict => strict, :required => required, :nullify_blank => nullify_blank)
|
11
11
|
}
|
12
12
|
|
13
13
|
let(:required) { true }
|
14
|
+
let(:nullify_blank) { false }
|
14
15
|
let(:input) { 1 }
|
15
16
|
let(:output) { '1' }
|
16
17
|
|
@@ -78,4 +79,51 @@ describe Virtus::Attribute, '#coerce' do
|
|
78
79
|
expect(coercer).to have_received.success?(String, input)
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
context 'when the input is an empty String' do
|
84
|
+
let(:input) { '' }
|
85
|
+
let(:output) { '' }
|
86
|
+
|
87
|
+
context 'when nullify_blank is turned on' do
|
88
|
+
let(:nullify_blank) { true }
|
89
|
+
let(:strict) { false }
|
90
|
+
let(:require) { false }
|
91
|
+
|
92
|
+
it 'returns nil' do
|
93
|
+
mock(coercer).call(input) { input }
|
94
|
+
mock(coercer).success?(String, input) { false }
|
95
|
+
|
96
|
+
expect(subject).to be_nil
|
97
|
+
|
98
|
+
expect(coercer).to have_received.call(input)
|
99
|
+
expect(coercer).to have_received.success?(String, input)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns the ouput if it was coerced' do
|
103
|
+
mock(coercer).call(input) { output }
|
104
|
+
mock(coercer).success?(String, output) { true }
|
105
|
+
|
106
|
+
expect(subject).to be(output)
|
107
|
+
|
108
|
+
expect(coercer).to have_received.call(input)
|
109
|
+
expect(coercer).to have_received.success?(String, output)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when both nullify_blank and strict are turned on' do
|
114
|
+
let(:nullify_blank) { true }
|
115
|
+
let(:strict) { true }
|
116
|
+
|
117
|
+
it 'does not raises an coercion error' do
|
118
|
+
mock(coercer).call(input) { input }
|
119
|
+
mock(coercer).success?(String, input) { false }
|
120
|
+
|
121
|
+
expect { subject }.not_to raise_error
|
122
|
+
expect(subject).to be_nil
|
123
|
+
|
124
|
+
expect(coercer).to have_received.call(input)
|
125
|
+
expect(coercer).to have_received.success?(String, input)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
81
129
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: virtus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: descendants_tracker
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- lib/virtus/attribute/embedded_value.rb
|
133
133
|
- lib/virtus/attribute/hash.rb
|
134
134
|
- lib/virtus/attribute/lazy_default.rb
|
135
|
+
- lib/virtus/attribute/nullify_blank.rb
|
135
136
|
- lib/virtus/attribute/strict.rb
|
136
137
|
- lib/virtus/attribute_set.rb
|
137
138
|
- lib/virtus/builder.rb
|
@@ -237,9 +238,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
238
|
version: '0'
|
238
239
|
requirements: []
|
239
240
|
rubyforge_project:
|
240
|
-
rubygems_version: 2.
|
241
|
+
rubygems_version: 2.4.5
|
241
242
|
signing_key:
|
242
243
|
specification_version: 4
|
243
244
|
summary: Attributes on Steroids for Plain Old Ruby Objects
|
244
245
|
test_files: []
|
245
|
-
has_rdoc:
|