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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 934dc95c7d8fd79268fcf7e2303257cd72378ef9
4
- data.tar.gz: dd9096d86a6df285b7b97f4cabab540afa72ed0b
3
+ metadata.gz: 1a85ace0a75695ebb65294da839a389e5349b660
4
+ data.tar.gz: 2c8d5150758b6bab5ce1bb8484cdaff11d1fe581
5
5
  SHA512:
6
- metadata.gz: 9095639c91403b8193bfe71a9067da701298a5190f65bdef2ac0ea0aaef130cf819529b2a672e071b48857ce614082402048a9125658b4a6f129d432968239f7
7
- data.tar.gz: ec1343ee430f0e6c6766c6e7a2457d116b7b4de00156f2ffe813989f1f62f96d712218756f750bfb45dc700552ba7999450ae243a3024ed1af3a5671e8a7b817
6
+ metadata.gz: e92ffbfc9ee7b17c58253130ad0e5bdf45857618d04d64d5c8e58b0d3d156deac13d2cc44d3b628f08ec76cdc9bc8634aca2570e987de2cd64e07ffe21fb8d04
7
+ data.tar.gz: 33db1e4a9040ce6d008062683a6eedcce3632b4854290a114795accad964233094d80f324d1b703487f6f14d6b1510e383dfce32bf7a341f9bf372d95fd37363
@@ -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/rom.svg)][gem]
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 => 29)
64
- user.attributes # => { :name => "Piotr", :age => 29 }
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 = '29' # => 29
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.
@@ -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'
@@ -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) if options[:name]
164
- @attribute.extend(Coercible) if options[:coerce]
165
- @attribute.extend(Strict) if options[:strict]
166
- @attribute.extend(LazyDefault) if options[:lazy]
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Virtus
2
- VERSION = '1.0.4'.freeze
2
+ VERSION = '1.0.5'.freeze
3
3
  end
@@ -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
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-01-03 00:00:00.000000000 Z
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.2.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: