virtus 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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 Version](https://badge.fury.io/rb/
|
13
|
+
[![Gem Version](https://badge.fury.io/rb/virtus.svg)][gem]
|
14
14
|
[![Build Status](https://travis-ci.org/solnic/virtus.svg?branch=master)][travis]
|
15
15
|
[![Dependency Status](https://gemnasium.com/solnic/virtus.png)][gemnasium]
|
16
16
|
[![Code Climate](https://codeclimate.com/github/solnic/virtus/badges/gpa.svg)][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:
|