virtus 0.5.3 → 0.5.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.
@@ -1,4 +1,13 @@
1
- # v0.5.3 2012-09-01 2012-12-13
1
+ # v0.5.4 2012-12-20
2
+
3
+ * [feature] Allow *any* enumerable to be a collection attribute (aptinio)
4
+ * [feature] Add Integer.to_datetime and Float.to_datetime coercion (brutuscat)
5
+ * [fixed] Fixed a regression with Hash attribute introduced by key/member coercion (shingara)
6
+ * [fixed] Change leading non-significant digit type coercion to be coerced (maskact)
7
+
8
+ [Compare v0.5.3..v0.5.4](https://github.com/solnic/virtus/compare/v0.5.3...v0.5.4)
9
+
10
+ # v0.5.3 2012-12-13
2
11
 
3
12
  * [feature] Added Hash member type coercion [example](https://github.com/solnic/virtus#hash-attributes-coercion) (greyblake)
4
13
  * [fixed] Fixed issues with String=>Integer coercion and e-notation (greyblake)
@@ -1,5 +1,5 @@
1
1
  group :development do
2
- gem 'rake', '~> 0.9.2'
2
+ gem 'rake', '~> 10.0'
3
3
  gem 'rspec', '~> 2.12.0'
4
4
  gem 'yard', '~> 0.8.3'
5
5
  end
@@ -27,7 +27,7 @@ group :metrics do
27
27
  gem 'reek', '~> 1.2.8', :git => 'https://github.com/dkubb/reek.git'
28
28
  gem 'roodi', '~> 2.1.0'
29
29
  gem 'yardstick', '~> 0.8.0'
30
- gem 'mutant', '~> 0.2.0'
30
+ gem 'mutant', '~> 0.2.6'
31
31
 
32
32
  platforms :ruby_18, :ruby_19 do
33
33
  # this indirectly depends on ffi which does not build on ruby-head
@@ -83,7 +83,9 @@ module Virtus
83
83
  case class_or_name
84
84
  when ::Class
85
85
  Attribute::EmbeddedValue.determine_type(class_or_name) || super
86
- when ::Array, ::Set, ::Hash
86
+ when ::String
87
+ super
88
+ when ::Enumerable
87
89
  super(class_or_name.class)
88
90
  else
89
91
  super
@@ -75,12 +75,10 @@ module Virtus
75
75
  # @api private
76
76
  def initialize(*)
77
77
  super
78
- if @options.has_key?(:key_type) && @options.has_key?(:value_type)
79
- @key_type = @options[:key_type]
80
- @value_type = @options[:value_type]
81
- @key_type_instance = Attribute.build(@name, @key_type)
82
- @value_type_instance = Attribute.build(@name, @value_type)
83
- end
78
+ @key_type = @options[:key_type] || Object
79
+ @value_type = @options[:value_type] || Object
80
+ @key_type_instance = Attribute.build(@name, @key_type)
81
+ @value_type_instance = Attribute.build(@name, @value_type)
84
82
  end
85
83
 
86
84
  # Coerce a hash with keys and values
@@ -93,10 +91,8 @@ module Virtus
93
91
  def coerce(value)
94
92
  coerced = super
95
93
  return coerced unless coerced.respond_to?(:each_with_object)
96
- coerced.each_with_object({}) do |key_and_value, hash|
97
- key = @key_type_instance.coerce(key_and_value[0])
98
- value = @value_type_instance.coerce(key_and_value[1])
99
- hash[key] = value
94
+ coerced.each_with_object({}) do |(key, value), hash|
95
+ hash[@key_type_instance.coerce(key)] = @value_type_instance.coerce(value)
100
96
  end
101
97
  end
102
98
 
@@ -19,6 +19,21 @@ module Virtus
19
19
  value
20
20
  end
21
21
 
22
+ # Coerce given value to a DateTime
23
+ #
24
+ # @example
25
+ # datetime = Virtus::Coercion::Float.to_datetime(1000000000.999) # => Sun, 09 Sep 2001 01:46:40 +0000
26
+ # datetime.to_f # => 1000000000.999
27
+ #
28
+ # @param [Float] value
29
+ #
30
+ # @return [DateTime]
31
+ #
32
+ # @api public
33
+ def self.to_datetime(value)
34
+ ::DateTime.strptime((value * 10**3).to_s, "%Q")
35
+ end
36
+
22
37
  end # class Float
23
38
  end # class Coercion
24
39
  end # module Virtus
@@ -55,6 +55,29 @@ module Virtus
55
55
  end
56
56
  end
57
57
 
58
+ # Coerce given value to a DateTime
59
+ #
60
+ # @example
61
+ # Virtus::Coercion::Fixnum.to_datetime(0) # => Thu, 01 Jan 1970 00:00:00 +0000
62
+ #
63
+ # @param [Integer] value
64
+ #
65
+ # @return [DateTime]
66
+ #
67
+ # @api public
68
+ def self.to_datetime(value)
69
+ # FIXME: Remove after Rubinius 2.0 is released
70
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
71
+ datetime_format = '%Q'
72
+ value = "#{value * 10**3}"
73
+ else
74
+ datetime_format = '%s'
75
+ value = "#{value}"
76
+ end
77
+
78
+ ::DateTime.strptime(value, datetime_format)
79
+ end
80
+
58
81
  end # class Fixnum
59
82
  end # class Coercion
60
83
  end # module Virtus
@@ -9,7 +9,7 @@ module Virtus
9
9
  FALSE_VALUES = %w[ 0 off f false n no ].freeze
10
10
  BOOLEAN_MAP = ::Hash[ TRUE_VALUES.product([ true ]) + FALSE_VALUES.product([ false ]) ].freeze
11
11
 
12
- INTEGER_REGEXP = /[-+]?(?:0|[1-9]\d*)/.freeze
12
+ INTEGER_REGEXP = /[-+]?(?:[0-9]\d*)/.freeze
13
13
  EXPONENT_REGEXP = /(?:[eE][-+]?\d+)/.freeze
14
14
  FRACTIONAL_REGEXP = /(?:\.\d+)/.freeze
15
15
 
@@ -1,3 +1,3 @@
1
1
  module Virtus
2
- VERSION = '0.5.3'
2
+ VERSION = '0.5.4'
3
3
  end
@@ -72,4 +72,46 @@ describe Virtus::Attribute, '.determine_type' do
72
72
 
73
73
  it { should equal(Virtus::Attribute::Set) }
74
74
  end
75
+
76
+ context 'with an instance of an enumerable' do
77
+ before do
78
+ module Examples
79
+ class EnumerableClass
80
+ include Enumerable
81
+
82
+ def self.[](*args)
83
+ new
84
+ end
85
+ end
86
+
87
+ class EnumerableAttribute < Virtus::Attribute::Collection
88
+ primitive EnumerableClass
89
+ end
90
+ end
91
+ end
92
+
93
+ subject { object.determine_type(primitive) }
94
+
95
+ let(:primitive) { Examples::EnumerableClass[String] }
96
+
97
+ it { should equal(Examples::EnumerableAttribute) }
98
+ end
99
+
100
+ context 'with an instance of an array subclass' do
101
+ before do
102
+ module Examples
103
+ ArraySubclass = Class.new(Array)
104
+
105
+ class ArraySubclassAttribute < Virtus::Attribute::Collection
106
+ primitive ArraySubclass
107
+ end
108
+ end
109
+ end
110
+
111
+ subject { object.determine_type(primitive) }
112
+
113
+ let(:primitive) { Examples::ArraySubclass[String] }
114
+
115
+ it { should equal(Examples::ArraySubclassAttribute) }
116
+ end
75
117
  end
@@ -60,6 +60,18 @@ describe Virtus::Attribute::DateTime, '#coerce' do
60
60
  end
61
61
  end
62
62
 
63
+ context 'with an integer with the seconds since the Unix Epoch' do
64
+ let(:value) { 1302139609 }
65
+
66
+ it_should_behave_like 'a correct date time'
67
+ end
68
+
69
+ context 'with a float with the seconds and milliseconds since the Unix Epoch' do
70
+ let(:value) { 1302139609.664 }
71
+
72
+ it_should_behave_like 'a correct date time'
73
+ end
74
+
63
75
  context 'with a on-date value' do
64
76
  let(:value) { 'non-date' }
65
77
 
@@ -59,6 +59,12 @@ describe Virtus::Attribute::Decimal, '#coerce' do
59
59
  it { should eql(BigDecimal('0.41')) }
60
60
  end
61
61
 
62
+ context 'with a positive string float and leading non-significant digits' do
63
+ let (:value) { '00.0' }
64
+
65
+ it { should eql(BigDecimal('0.0')) }
66
+ end
67
+
62
68
  context 'with a zero integer' do
63
69
  let(:value) { 0 }
64
70
 
@@ -107,7 +113,7 @@ describe Virtus::Attribute::Decimal, '#coerce' do
107
113
  it { should eql(BigDecimal('-24.35')) }
108
114
  end
109
115
 
110
- [ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |non_num_value|
116
+ [ Object.new, true, '0.', '-.0', 'string' ].each do |non_num_value|
111
117
  context 'with a non-numeric value = #{non_num_value.inspect}' do
112
118
  let(:value) { non_num_value }
113
119
 
@@ -59,6 +59,12 @@ describe Virtus::Attribute::Float, '#coerce' do
59
59
  it { should eql(0.41) }
60
60
  end
61
61
 
62
+ context 'with a positive string float and leading non-significant digits' do
63
+ let (:value) { '00.0' }
64
+
65
+ it { should eql(0.0) }
66
+ end
67
+
62
68
  context 'with a zero integer' do
63
69
  let(:value) { 0 }
64
70
 
@@ -107,7 +113,7 @@ describe Virtus::Attribute::Float, '#coerce' do
107
113
  it { should eql(-24.35) }
108
114
  end
109
115
 
110
- [ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |non_num_value|
116
+ [ Object.new, true, '0.', '-.0', 'string' ].each do |non_num_value|
111
117
  context 'does not coerce non-numeric value #{non_num_value.inspect}' do
112
118
  let(:value) { non_num_value }
113
119
 
@@ -17,4 +17,12 @@ describe Virtus::Attribute::Hash, '#coerce' do
17
17
 
18
18
  it { should be(:symbol) }
19
19
  end
20
+
21
+ context "without Hash Coerce type define" do
22
+ let(:options) { { } }
23
+ let(:input_value) { { :one => '1', 'two' => 2 } }
24
+
25
+ it { should eq(:one => '1', 'two' => 2) }
26
+
27
+ end
20
28
  end
@@ -59,6 +59,12 @@ describe Virtus::Attribute::Integer, '#coerce' do
59
59
  it { should eql(0) }
60
60
  end
61
61
 
62
+ context 'with a positive string float and leading non-significant digits' do
63
+ let (:value) { '00.0' }
64
+
65
+ it { should eql(0) }
66
+ end
67
+
62
68
  context 'with a zero float' do
63
69
  let(:value) { 0.0 }
64
70
 
@@ -101,7 +107,7 @@ describe Virtus::Attribute::Integer, '#coerce' do
101
107
  it { should eql(value.to_i) }
102
108
  end
103
109
 
104
- [ Object.new, true, false, '00.0', '0.', '-.0', 'string' ].each do |non_num_value|
110
+ [ Object.new, true, false, '0.', '-.0', 'string' ].each do |non_num_value|
105
111
  context 'does not coerce non-numeric value #{non_num_value.inspect}' do
106
112
  let(:value) { non_num_value }
107
113
 
@@ -18,7 +18,4 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.add_dependency('backports', '~> 2.6.1')
20
20
  gem.add_dependency('descendants_tracker', '~> 0.0.1')
21
-
22
- gem.add_development_dependency('rake', '~> 0.9.2')
23
- gem.add_development_dependency('rspec', '~> 2.12')
24
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-13 00:00:00.000000000 Z
12
+ date: 2012-12-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: backports
@@ -43,38 +43,6 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.0.1
46
- - !ruby/object:Gem::Dependency
47
- name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ~>
52
- - !ruby/object:Gem::Version
53
- version: 0.9.2
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 0.9.2
62
- - !ruby/object:Gem::Dependency
63
- name: rspec
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: '2.12'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: '2.12'
78
46
  description: Attributes on Steroids for Plain Old Ruby Objects
79
47
  email:
80
48
  - piotr.solnica@gmail.com