virtus 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +33 -7
- data/.travis.yml +4 -74
- data/Changelog.md +11 -2
- data/Gemfile +10 -9
- data/README.md +85 -1
- data/TODO +18 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/roodi.yml +3 -3
- data/config/site.reek +8 -3
- data/lib/virtus.rb +5 -0
- data/lib/virtus/attribute.rb +137 -30
- data/lib/virtus/attribute/array.rb +17 -1
- data/lib/virtus/attribute/boolean.rb +8 -13
- data/lib/virtus/attribute/collection.rb +96 -0
- data/lib/virtus/attribute/default_value.rb +11 -7
- data/lib/virtus/attribute/embedded_value.rb +70 -0
- data/lib/virtus/attribute/set.rb +25 -0
- data/lib/virtus/attribute_set.rb +18 -16
- data/lib/virtus/attributes_accessor.rb +66 -0
- data/lib/virtus/class_methods.rb +50 -28
- data/lib/virtus/coercion/array.rb +23 -0
- data/lib/virtus/coercion/string.rb +10 -4
- data/lib/virtus/instance_methods.rb +38 -31
- data/lib/virtus/support/options.rb +6 -8
- data/lib/virtus/support/type_lookup.rb +4 -11
- data/lib/virtus/version.rb +1 -1
- data/spec/integration/collection_member_coercion_spec.rb +75 -0
- data/spec/integration/custom_attributes_spec.rb +49 -0
- data/spec/integration/default_values_spec.rb +32 -0
- data/spec/integration/defining_attributes_spec.rb +79 -0
- data/spec/integration/embedded_value_spec.rb +50 -0
- data/spec/integration/overriding_virtus_spec.rb +46 -0
- data/spec/integration/virtus/instance_level_attributes_spec.rb +23 -0
- data/spec/rcov.opts +1 -0
- data/spec/shared/constants_helpers.rb +9 -0
- data/spec/shared/options_class_method.rb +19 -0
- data/spec/spec_helper.rb +20 -7
- data/spec/unit/virtus/attribute/array/coerce_spec.rb +13 -0
- data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +85 -0
- data/spec/unit/virtus/attribute/boolean/define_reader_method_spec.rb +15 -0
- data/spec/unit/virtus/attribute/boolean/value_coerced_spec.rb +97 -0
- data/spec/unit/virtus/attribute/boolean_spec.rb +2 -81
- data/spec/unit/virtus/attribute/class/coerce_spec.rb +13 -0
- data/spec/unit/virtus/attribute/class_methods/accessor_spec.rb +12 -0
- data/spec/unit/virtus/attribute/class_methods/build_spec.rb +37 -0
- data/spec/unit/virtus/attribute/class_methods/coercion_method_spec.rb +9 -0
- data/spec/unit/virtus/attribute/class_methods/default_spec.rb +9 -0
- data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +31 -1
- data/spec/unit/virtus/attribute/class_methods/merge_options_spec.rb +11 -0
- data/spec/unit/virtus/attribute/class_methods/primitive_spec.rb +9 -0
- data/spec/unit/virtus/attribute/class_methods/reader_spec.rb +9 -0
- data/spec/unit/virtus/attribute/class_methods/writer_spec.rb +9 -0
- data/spec/unit/virtus/attribute/coerce_spec.rb +30 -0
- data/spec/unit/virtus/attribute/coercion_method_spec.rb +12 -0
- data/spec/unit/virtus/attribute/collection/class_methods/merge_options_spec.rb +40 -0
- data/spec/unit/virtus/attribute/collection/coerce_spec.rb +26 -0
- data/spec/unit/virtus/attribute/date/coerce_spec.rb +47 -0
- data/spec/unit/virtus/attribute/date/value_coerced_spec.rb +46 -0
- data/spec/unit/virtus/attribute/date_time/coerce_spec.rb +68 -0
- data/spec/unit/virtus/attribute/decimal/coerce_spec.rb +117 -0
- data/spec/unit/virtus/attribute/default_spec.rb +32 -0
- data/spec/unit/virtus/attribute/default_value/attribute_spec.rb +11 -0
- data/spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb +4 -2
- data/spec/unit/virtus/attribute/default_value/evaluate_spec.rb +51 -0
- data/spec/unit/virtus/attribute/default_value/instance_methods/evaluate_spec.rb +9 -6
- data/spec/unit/virtus/attribute/default_value/value_spec.rb +11 -0
- data/spec/unit/virtus/attribute/define_accessor_methods_spec.rb +26 -0
- data/spec/unit/virtus/attribute/define_reader_method_spec.rb +24 -0
- data/spec/unit/virtus/attribute/define_writer_method_spec.rb +24 -0
- data/spec/unit/virtus/attribute/embedded_value/class_methods/merge_options_spec.rb +17 -0
- data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +50 -0
- data/spec/unit/virtus/attribute/float/coerce_spec.rb +117 -0
- data/spec/unit/virtus/attribute/get_spec.rb +80 -0
- data/spec/unit/virtus/attribute/inspect_spec.rb +27 -0
- data/spec/unit/virtus/attribute/instance_variable_name_spec.rb +12 -0
- data/spec/unit/virtus/attribute/integer/coerce_spec.rb +105 -0
- data/spec/unit/virtus/attribute/name_spec.rb +12 -0
- data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +1 -1
- data/spec/unit/virtus/attribute/numeric/class_methods/max_spec.rb +9 -0
- data/spec/unit/virtus/attribute/numeric/class_methods/min_spec.rb +9 -0
- data/spec/unit/virtus/attribute/object/class_methods/descendants_spec.rb +9 -7
- data/spec/unit/virtus/attribute/options_spec.rb +14 -0
- data/spec/unit/virtus/attribute/public_reader_spec.rb +24 -0
- data/spec/unit/virtus/attribute/public_writer_spec.rb +24 -0
- data/spec/unit/virtus/attribute/reader_visibility_spec.rb +24 -0
- data/spec/unit/virtus/attribute/set/coerce_spec.rb +13 -0
- data/spec/unit/virtus/attribute/set_spec.rb +49 -0
- data/spec/unit/virtus/attribute/string/coerce_spec.rb +11 -0
- data/spec/unit/virtus/attribute/time/coerce_spec.rb +67 -0
- data/spec/unit/virtus/attribute/value_coerced_spec.rb +19 -0
- data/spec/unit/virtus/attribute/writer_visibility_spec.rb +24 -0
- data/spec/unit/virtus/attribute_set/append_spec.rb +12 -0
- data/spec/unit/virtus/attribute_set/element_reference_spec.rb +4 -0
- data/spec/unit/virtus/attribute_set/element_set_spec.rb +29 -9
- data/spec/unit/virtus/attributes_accessor/inspect_spec.rb +9 -0
- data/spec/unit/virtus/class_methods/attribute_spec.rb +23 -5
- data/spec/unit/virtus/class_methods/attributes_spec.rb +3 -5
- data/spec/unit/virtus/class_methods/const_missing_spec.rb +27 -0
- data/spec/unit/virtus/class_methods/inherited_spec.rb +21 -0
- data/spec/unit/virtus/coercion/array/to_set_spec.rb +12 -0
- data/spec/unit/virtus/coercion/date/class_methods/to_date_spec.rb +10 -0
- data/spec/unit/virtus/coercion/date_time/class_methods/to_datetime_spec.rb +10 -0
- data/spec/unit/virtus/coercion/hash/class_methods/to_date_spec.rb +10 -3
- data/spec/unit/virtus/coercion/hash/class_methods/to_datetime_spec.rb +10 -3
- data/spec/unit/virtus/coercion/hash/class_methods/to_time_spec.rb +10 -3
- data/spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb +8 -8
- data/spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb +2 -2
- data/spec/unit/virtus/coercion/string/class_methods/to_constant_spec.rb +1 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb +1 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb +13 -13
- data/spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb +25 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_float_spec.rb +25 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_integer_spec.rb +30 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_time_spec.rb +13 -13
- data/spec/unit/virtus/coercion/time/class_methods/to_time_spec.rb +10 -0
- data/spec/unit/virtus/coercion/true_class/class_methods/to_string_spec.rb +1 -1
- data/spec/unit/virtus/instance_methods/attributes_spec.rb +77 -20
- data/spec/unit/virtus/instance_methods/element_reference_spec.rb +1 -1
- data/spec/unit/virtus/instance_methods/element_set_spec.rb +2 -2
- data/spec/unit/virtus/instance_methods/to_hash_spec.rb +23 -0
- data/spec/unit/virtus/options/accept_options_spec.rb +10 -11
- data/spec/unit/virtus/options/accepted_options_spec.rb +1 -1
- data/spec/unit/virtus/options/options_spec.rb +27 -4
- data/tasks/metrics/ci.rake +2 -1
- data/tasks/metrics/heckle.rake +207 -0
- data/tasks/spec.rake +14 -7
- data/virtus.gemspec +1 -1
- metadata +111 -97
- data/VERSION +0 -1
- data/examples/custom_coercion_spec.rb +0 -50
- data/examples/default_values_spec.rb +0 -21
- data/examples/override_attribute_methods_spec.rb +0 -40
- data/spec/integration/virtus/attributes/attribute/set_spec.rb +0 -36
- data/spec/integration/virtus/class_methods/attribute_spec.rb +0 -82
- data/spec/integration/virtus/class_methods/attributes_spec.rb +0 -22
- data/spec/integration/virtus/class_methods/const_missing_spec.rb +0 -44
- data/spec/unit/shared/attribute.rb +0 -7
- data/spec/unit/shared/attribute/accept_options.rb +0 -37
- data/spec/unit/shared/attribute/accepted_options.rb +0 -5
- data/spec/unit/shared/attribute/get.rb +0 -44
- data/spec/unit/shared/attribute/inspect.rb +0 -7
- data/spec/unit/shared/attribute/set.rb +0 -37
- data/spec/unit/virtus/attribute/array_spec.rb +0 -24
- data/spec/unit/virtus/attribute/class_spec.rb +0 -24
- data/spec/unit/virtus/attribute/date_spec.rb +0 -59
- data/spec/unit/virtus/attribute/date_time_spec.rb +0 -87
- data/spec/unit/virtus/attribute/decimal_spec.rb +0 -109
- data/spec/unit/virtus/attribute/float_spec.rb +0 -109
- data/spec/unit/virtus/attribute/hash_spec.rb +0 -11
- data/spec/unit/virtus/attribute/integer_spec.rb +0 -99
- data/spec/unit/virtus/attribute/string_spec.rb +0 -21
- data/spec/unit/virtus/attribute/time_spec.rb +0 -82
- data/spec/unit/virtus/class_methods/new_spec.rb +0 -41
data/.gitignore
CHANGED
@@ -1,11 +1,37 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## Rubinius
|
17
|
+
*.rbc
|
18
|
+
.rbx
|
19
|
+
|
20
|
+
## PROJECT::GENERAL
|
21
|
+
*.gem
|
22
|
+
coverage
|
23
|
+
profiling
|
24
|
+
turbulence
|
25
|
+
rdoc
|
26
|
+
pkg
|
27
|
+
tmp
|
1
28
|
doc
|
29
|
+
log
|
2
30
|
.yardoc
|
3
|
-
|
31
|
+
measurements
|
32
|
+
|
33
|
+
## BUNDLER
|
4
34
|
.bundle
|
5
35
|
Gemfile.lock
|
6
|
-
|
7
|
-
|
8
|
-
tmp/
|
9
|
-
profiling/
|
10
|
-
development
|
11
|
-
.rbx/
|
36
|
+
|
37
|
+
## PROJECT::SPECIFIC
|
data/.travis.yml
CHANGED
@@ -6,80 +6,10 @@ rvm:
|
|
6
6
|
- 1.9.3
|
7
7
|
- ruby-head
|
8
8
|
- ree
|
9
|
-
- jruby
|
10
|
-
-
|
11
|
-
|
12
|
-
-
|
13
|
-
- JRUBY_OPTS="--1.8"
|
14
|
-
- JRUBY_OPTS="--1.9"
|
15
|
-
- RBXOPT="-X18"
|
16
|
-
matrix:
|
17
|
-
exclude:
|
18
|
-
# exclude 1.8.7
|
19
|
-
- rvm: 1.8.7
|
20
|
-
env: JRUBY_OPTS="--1.8"
|
21
|
-
- rvm: 1.8.7
|
22
|
-
env: JRUBY_OPTS="--1.9"
|
23
|
-
- rvm: 1.8.7
|
24
|
-
env: RBXOPT="-X18"
|
25
|
-
- rvm: 1.8.7
|
26
|
-
env: RBXOPT="-X19"
|
27
|
-
|
28
|
-
# exclude 1.9.2
|
29
|
-
- rvm: 1.9.2
|
30
|
-
env: JRUBY_OPTS="--1.8"
|
31
|
-
- rvm: 1.9.2
|
32
|
-
env: JRUBY_OPTS="--1.9"
|
33
|
-
- rvm: 1.9.2
|
34
|
-
env: RBXOPT="-X18"
|
35
|
-
- rvm: 1.9.2
|
36
|
-
env: RBXOPT="-X19"
|
37
|
-
|
38
|
-
# exclude 1.9.3
|
39
|
-
- rvm: 1.9.3
|
40
|
-
env: JRUBY_OPTS="--1.8"
|
41
|
-
- rvm: 1.9.3
|
42
|
-
env: JRUBY_OPTS="--1.9"
|
43
|
-
- rvm: 1.9.3
|
44
|
-
env: RBXOPT="-X18"
|
45
|
-
- rvm: 1.9.3
|
46
|
-
env: RBXOPT="-X19"
|
47
|
-
|
48
|
-
# exclude ruby-head
|
49
|
-
- rvm: ruby-head
|
50
|
-
env: JRUBY_OPTS="--1.8"
|
51
|
-
- rvm: ruby-head
|
52
|
-
env: JRUBY_OPTS="--1.9"
|
53
|
-
- rvm: ruby-head
|
54
|
-
env: RBXOPT="-X18"
|
55
|
-
- rvm: ruby-head
|
56
|
-
env: RBXOPT="-X19"
|
57
|
-
|
58
|
-
# exclude ree
|
59
|
-
- rvm: ree
|
60
|
-
env: JRUBY_OPTS="--1.8"
|
61
|
-
- rvm: ree
|
62
|
-
env: JRUBY_OPTS="--1.9"
|
63
|
-
- rvm: ree
|
64
|
-
env: RBXOPT="-X18"
|
65
|
-
- rvm: ree
|
66
|
-
env: RBXOPT="-X19"
|
67
|
-
|
68
|
-
# exclude jruby
|
69
|
-
- rvm: jruby
|
70
|
-
env:
|
71
|
-
- rvm: jruby
|
72
|
-
env: RBXOPT="-X18"
|
73
|
-
- rvm: jruby
|
74
|
-
env: RBXOPT="-X19"
|
75
|
-
|
76
|
-
# exclude rbx
|
77
|
-
- rvm: rbx
|
78
|
-
env:
|
79
|
-
- rvm: rbx
|
80
|
-
env: JRUBY_OPTS="--1.8"
|
81
|
-
- rvm: rbx
|
82
|
-
env: JRUBY_OPTS="--1.9"
|
9
|
+
- jruby-18mode
|
10
|
+
- jruby-19mode
|
11
|
+
- rbx-18mode
|
12
|
+
# - rbx-19mode # FIXME: uncomment when rbx 1.9 is more stable
|
83
13
|
notifications:
|
84
14
|
email:
|
85
15
|
- piotr.solnica@gmail.com
|
data/Changelog.md
CHANGED
@@ -1,9 +1,18 @@
|
|
1
|
-
# v0.0
|
1
|
+
# v0.1.0 to-be-released
|
2
|
+
|
3
|
+
[Compare v0.0.10..master](https://github.com/solnic/virtus/compare/v0.0.10...master)
|
4
|
+
|
5
|
+
* [feature] New EmbeddedValue attribute (solnic)
|
6
|
+
* [feature] Support for scientific notation handling in string => integer coercion (dkubb)
|
7
|
+
* [feature] Handling of string => numeric coercion with a leading + sign (dkubb)
|
8
|
+
|
9
|
+
|
10
|
+
# v0.0.10 2011-11-21
|
2
11
|
|
3
12
|
* [fixed] Default values are now duped on evaluate (rclosner)
|
4
13
|
* [fixed] Allow to override attribute mutator methods (senny)
|
5
14
|
|
6
|
-
[Compare v0.0.9..
|
15
|
+
[Compare v0.0.9..v0.0.10](https://github.com/solnic/virtus/compare/v0.0.9...v0.0.10)
|
7
16
|
|
8
17
|
# v0.0.9 2011-10-11
|
9
18
|
|
data/Gemfile
CHANGED
@@ -3,17 +3,18 @@ source :rubygems
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :metrics do
|
6
|
-
gem '
|
7
|
-
gem '
|
8
|
-
gem '
|
9
|
-
gem '
|
10
|
-
gem '
|
11
|
-
gem '
|
12
|
-
gem '
|
13
|
-
gem '
|
6
|
+
gem 'fattr', '~> 2.2.0'
|
7
|
+
gem 'arrayfields', '~> 4.7.4'
|
8
|
+
gem 'flay', '~> 1.4.2'
|
9
|
+
gem 'flog', '~> 2.5.1'
|
10
|
+
gem 'map', '~> 5.2.0'
|
11
|
+
gem 'reek', '~> 1.2.8', :git => 'git://github.com/dkubb/reek.git'
|
12
|
+
gem 'roodi', '~> 2.1.0'
|
13
|
+
gem 'yardstick', '~> 0.4.0'
|
14
14
|
|
15
15
|
platforms :mri_18 do
|
16
|
-
gem '
|
16
|
+
gem 'heckle', '~> 1.4.3'
|
17
|
+
gem 'json', '~> 1.6.4'
|
17
18
|
gem 'metric_fu', '~> 2.1.1'
|
18
19
|
gem 'mspec', '~> 1.5.17'
|
19
20
|
gem 'rcov', '~> 0.9.9'
|
data/README.md
CHANGED
@@ -23,9 +23,11 @@ or
|
|
23
23
|
``` ruby
|
24
24
|
# ./Gemfile
|
25
25
|
|
26
|
-
gem 'virtus'
|
26
|
+
gem 'virtus'
|
27
27
|
```
|
28
28
|
|
29
|
+
*IMPORTANT*: If you are still using Ruby 1.8.7 then you also have to install backports gem!
|
30
|
+
|
29
31
|
Examples
|
30
32
|
--------
|
31
33
|
|
@@ -78,6 +80,86 @@ page.views
|
|
78
80
|
# => 0
|
79
81
|
```
|
80
82
|
|
83
|
+
**Embedded Value**
|
84
|
+
|
85
|
+
``` ruby
|
86
|
+
class City
|
87
|
+
include Virtus
|
88
|
+
|
89
|
+
attribute :name, String
|
90
|
+
end
|
91
|
+
|
92
|
+
class Address
|
93
|
+
include Virtus
|
94
|
+
|
95
|
+
attribute :street, String
|
96
|
+
attribute :zipcode, String
|
97
|
+
attribute :city, City
|
98
|
+
end
|
99
|
+
|
100
|
+
class User
|
101
|
+
include Virtus
|
102
|
+
|
103
|
+
attribute :name, String
|
104
|
+
attribute :address, Address
|
105
|
+
end
|
106
|
+
|
107
|
+
user = User.new(:address => {
|
108
|
+
:street => 'Street 1/2', :zipcode => '12345', :city => { :name => 'NYC' } })
|
109
|
+
|
110
|
+
user.address.street # => "Street 1/2"
|
111
|
+
user.address.city.name # => "NYC"
|
112
|
+
```
|
113
|
+
|
114
|
+
**Collection Member Coercions**
|
115
|
+
|
116
|
+
``` ruby
|
117
|
+
# Support "primitive" classes
|
118
|
+
|
119
|
+
class Book
|
120
|
+
include Virtus
|
121
|
+
|
122
|
+
attribute :page_numbers, Array[Integer]
|
123
|
+
end
|
124
|
+
|
125
|
+
book = Book.new(:page_numbers => %w[1 2 3])
|
126
|
+
book.page_numbers # => [1, 2, 3]
|
127
|
+
|
128
|
+
# Support EmbeddedValues, too!
|
129
|
+
class Address
|
130
|
+
include Virtus
|
131
|
+
|
132
|
+
attribute :address, String
|
133
|
+
attribute :locality, String
|
134
|
+
attribute :region, String
|
135
|
+
attribute :postal_code, String
|
136
|
+
end
|
137
|
+
|
138
|
+
class PhoneNumber
|
139
|
+
include Virtus
|
140
|
+
|
141
|
+
attribute :number, String
|
142
|
+
end
|
143
|
+
|
144
|
+
class User
|
145
|
+
include Virtus
|
146
|
+
|
147
|
+
attribute :phone_numbers, Array[PhoneNumber]
|
148
|
+
attribute :addresses, Set[Address]
|
149
|
+
end
|
150
|
+
|
151
|
+
user = User.new(
|
152
|
+
:phone_numbers => [
|
153
|
+
{ :number => '212-555-1212' },
|
154
|
+
{ :number => '919-444-3265' } ],
|
155
|
+
:addresses => [
|
156
|
+
{ :address => '1234 Any St.', :locality => 'Anytown', :region => "DC", :postal_code => "21234" } ])
|
157
|
+
|
158
|
+
user.phone_numbers # => [#<PhoneNumber:0x007fdb2d3bef88 @number="212-555-1212">, #<PhoneNumber:0x007fdb2d3beb00 @number="919-444-3265">]
|
159
|
+
|
160
|
+
user.addresses # => #<Set: {#<Address:0x007fdb2d3be448 @address="1234 Any St.", @locality="Anytown", @region="DC", @postal_code="21234">}>
|
161
|
+
```
|
162
|
+
|
81
163
|
**Adding Coercions**
|
82
164
|
|
83
165
|
Virtus comes with a builtin coercion library.
|
@@ -160,6 +242,8 @@ Credits
|
|
160
242
|
* Dan Kubb ([dkubb](https://github.com/dkubb))
|
161
243
|
* Chris Corbyn ([d11wtq](https://github.com/d11wtq))
|
162
244
|
* Emmanuel Gomez ([emmanuel](https://github.com/emmanuel))
|
245
|
+
* Ryan Closner ([rclosner](https://github.com/rclosner))
|
246
|
+
* Yves Senn ([senny](https://github.com/senny))
|
163
247
|
|
164
248
|
|
165
249
|
Contributing
|
data/TODO
CHANGED
@@ -1,2 +1,20 @@
|
|
1
|
+
* Add missing specs:
|
2
|
+
* Add spec file spec/unit/virtus/coercion/time_coercions/to_date_spec.rb for Virtus::Coercion::TimeCoercions#to_date
|
3
|
+
* Add spec file spec/unit/virtus/coercion/time_coercions/to_time_spec.rb for Virtus::Coercion::TimeCoercions#to_time
|
4
|
+
* Add spec file spec/unit/virtus/coercion/time_coercions/to_string_spec.rb for Virtus::Coercion::TimeCoercions#to_string
|
5
|
+
* Add spec file spec/unit/virtus/coercion/time_coercions/to_datetime_spec.rb for Virtus::Coercion::TimeCoercions#to_datetime
|
6
|
+
* Add spec file spec/unit/virtus/coercion/decimal/class_methods/to_decimal_spec.rb for Virtus::Coercion::Decimal.to_decimal
|
7
|
+
* Add spec file spec/unit/virtus/coercion/float/class_methods/to_float_spec.rb for Virtus::Coercion::Float.to_float
|
8
|
+
* Add spec file spec/unit/virtus/coercion/integer/class_methods/to_integer_spec.rb for Virtus::Coercion::Integer.to_integer
|
9
|
+
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_float_spec.rb for Virtus::Coercion::Numeric.to_float
|
10
|
+
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_integer_spec.rb for Virtus::Coercion::Numeric.to_integer
|
11
|
+
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_string_spec.rb for Virtus::Coercion::Numeric.to_string
|
12
|
+
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_decimal_spec.rb for Virtus::Coercion::Numeric.to_decimal
|
13
|
+
* Add spec file spec/unit/virtus/coercion/class_methods/element_reference_spec.rb for Virtus::Coercion.[]
|
14
|
+
* Add spec file spec/unit/virtus/coercion/class_methods/primitive_spec.rb for Virtus::Coercion.primitive
|
15
|
+
* Add spec file spec/unit/virtus/attributes_accessor/define_writer_method_spec.rb for Virtus::AttributesAccessor#define_writer_method
|
16
|
+
* Add spec file spec/unit/virtus/attributes_accessor/inspect_spec.rb for Virtus::AttributesAccessor#inspect
|
17
|
+
* Add spec file spec/unit/virtus/attributes_accessor/define_reader_method_spec.rb for Virtus::AttributesAccessor#define_reader_method
|
18
|
+
|
1
19
|
* Make #to_time #to_date and #to_datetime work on Ruby 1.8.7 instead of typecasting to string and parsing the value
|
2
20
|
* Add support for defining attributes on Modules
|
data/config/flay.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
3
|
-
total_score:
|
2
|
+
threshold: 19
|
3
|
+
total_score: 322
|
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 16.8
|
data/config/roodi.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
---
|
2
|
-
AbcMetricMethodCheck: { score:
|
2
|
+
AbcMetricMethodCheck: { score: 12.1 }
|
3
3
|
AssignmentInConditionalCheck: { }
|
4
4
|
CaseMissingElseCheck: { }
|
5
|
-
ClassLineCountCheck: { line_count:
|
5
|
+
ClassLineCountCheck: { line_count: 319 }
|
6
6
|
ClassNameCheck: { pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ }
|
7
7
|
ClassVariableCheck: { }
|
8
8
|
CyclomaticComplexityBlockCheck: { complexity: 4 }
|
@@ -11,7 +11,7 @@ EmptyRescueBodyCheck: { }
|
|
11
11
|
ForLoopCheck: { }
|
12
12
|
MethodLineCountCheck: { line_count: 9 }
|
13
13
|
MethodNameCheck: { pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/ }
|
14
|
-
ModuleLineCountCheck: { line_count:
|
14
|
+
ModuleLineCountCheck: { line_count: 325 }
|
15
15
|
ModuleNameCheck: { pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ }
|
16
16
|
# TODO: decrease parameter_count to 2 or less
|
17
17
|
ParameterNumberCheck: { parameter_count: 3 }
|
data/config/site.reek
CHANGED
@@ -8,10 +8,10 @@ UncommunicativeParameterName:
|
|
8
8
|
- !ruby/regexp /[0-9]$/
|
9
9
|
- !ruby/regexp /[A-Z]/
|
10
10
|
LargeClass:
|
11
|
-
max_methods:
|
11
|
+
max_methods: 14
|
12
12
|
exclude: []
|
13
13
|
enabled: true
|
14
|
-
max_instance_variables:
|
14
|
+
max_instance_variables: 8
|
15
15
|
UncommunicativeMethodName:
|
16
16
|
accept: []
|
17
17
|
exclude: []
|
@@ -27,6 +27,8 @@ LongParameterList:
|
|
27
27
|
overrides: {}
|
28
28
|
FeatureEnvy:
|
29
29
|
exclude: [
|
30
|
+
Virtus::Attribute::Boolean#value_coerced?,
|
31
|
+
Virtus::ClassMethods#build_attribute,
|
30
32
|
Virtus::Coercion::TimeCoercions#to_string,
|
31
33
|
Virtus::Coercion::TimeCoercions#coerce_with_method,
|
32
34
|
Virtus::TypeLookup#determine_type_from_primitive
|
@@ -66,7 +68,10 @@ Duplication:
|
|
66
68
|
max_calls: 1
|
67
69
|
UtilityFunction:
|
68
70
|
max_helper_calls: 1
|
69
|
-
exclude: [
|
71
|
+
exclude: [
|
72
|
+
Virtus::Attribute::Boolean#value_coerced?,
|
73
|
+
Virtus::ClassMethods#build_attribute
|
74
|
+
]
|
70
75
|
enabled: true
|
71
76
|
Attribute:
|
72
77
|
exclude: []
|
data/lib/virtus.rb
CHANGED
@@ -31,6 +31,7 @@ require 'virtus/support/descendants_tracker'
|
|
31
31
|
require 'virtus/support/type_lookup'
|
32
32
|
require 'virtus/support/options'
|
33
33
|
|
34
|
+
require 'virtus/attributes_accessor'
|
34
35
|
require 'virtus/class_methods'
|
35
36
|
require 'virtus/instance_methods'
|
36
37
|
|
@@ -45,6 +46,7 @@ require 'virtus/coercion/decimal'
|
|
45
46
|
require 'virtus/coercion/false_class'
|
46
47
|
require 'virtus/coercion/true_class'
|
47
48
|
require 'virtus/coercion/hash'
|
49
|
+
require 'virtus/coercion/array'
|
48
50
|
require 'virtus/coercion/time_coercions'
|
49
51
|
require 'virtus/coercion/date'
|
50
52
|
require 'virtus/coercion/date_time'
|
@@ -56,7 +58,9 @@ require 'virtus/attribute/default_value'
|
|
56
58
|
require 'virtus/attribute'
|
57
59
|
require 'virtus/attribute/object'
|
58
60
|
require 'virtus/attribute/class'
|
61
|
+
require 'virtus/attribute/collection'
|
59
62
|
require 'virtus/attribute/array'
|
63
|
+
require 'virtus/attribute/set'
|
60
64
|
require 'virtus/attribute/boolean'
|
61
65
|
require 'virtus/attribute/date'
|
62
66
|
require 'virtus/attribute/date_time'
|
@@ -67,3 +71,4 @@ require 'virtus/attribute/hash'
|
|
67
71
|
require 'virtus/attribute/integer'
|
68
72
|
require 'virtus/attribute/string'
|
69
73
|
require 'virtus/attribute/time'
|
74
|
+
require 'virtus/attribute/embedded_value'
|
data/lib/virtus/attribute.rb
CHANGED
@@ -8,6 +8,11 @@ module Virtus
|
|
8
8
|
extend TypeLookup
|
9
9
|
extend Options
|
10
10
|
|
11
|
+
accept_options :primitive, :accessor, :reader,
|
12
|
+
:writer, :coercion_method, :default
|
13
|
+
|
14
|
+
accessor :public
|
15
|
+
|
11
16
|
# Returns name of the attribute
|
12
17
|
#
|
13
18
|
# @example
|
@@ -27,7 +32,7 @@ module Virtus
|
|
27
32
|
|
28
33
|
# Returns instance variable name of the attribute
|
29
34
|
#
|
30
|
-
# @return [
|
35
|
+
# @return [Symbol]
|
31
36
|
#
|
32
37
|
# @api private
|
33
38
|
attr_reader :instance_variable_name
|
@@ -60,16 +65,75 @@ module Virtus
|
|
60
65
|
# @api private
|
61
66
|
attr_reader :default
|
62
67
|
|
63
|
-
|
68
|
+
# Builds an attribute instance
|
69
|
+
#
|
70
|
+
# @param [Symbol] name
|
71
|
+
# the name of an attribute
|
72
|
+
#
|
73
|
+
# @param [Class] type
|
74
|
+
# the type class of an attribute
|
75
|
+
#
|
76
|
+
# @param [#to_hash] options
|
77
|
+
# the extra options hash
|
78
|
+
#
|
79
|
+
# @return [Attribute]
|
80
|
+
#
|
81
|
+
# @api private
|
82
|
+
def self.build(name, type, options = {})
|
83
|
+
attribute_class = determine_type(type) or
|
84
|
+
raise ArgumentError, "#{type.inspect} does not map to an attribute type"
|
85
|
+
attribute_options = attribute_class.merge_options(type, options)
|
86
|
+
attribute_class.new(name, attribute_options)
|
87
|
+
end
|
64
88
|
|
65
|
-
|
66
|
-
|
89
|
+
# Determine attribute type based on class or name
|
90
|
+
#
|
91
|
+
# Returns Attribute::EmbeddedValue if a virtus class is passed
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# address_class = Class.new { include Virtus }
|
95
|
+
# Virtus::Attribute.determine_type(address_class) # => Virtus::Attribute::EmbeddedValue
|
96
|
+
#
|
97
|
+
# @see Virtus::Support::TypeLookup.determine_type
|
98
|
+
#
|
99
|
+
# @return [Class]
|
100
|
+
#
|
101
|
+
# @api public
|
102
|
+
def self.determine_type(class_or_name)
|
103
|
+
case class_or_name
|
104
|
+
when ::Class
|
105
|
+
if class_or_name <= Virtus
|
106
|
+
Attribute::EmbeddedValue
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
when ::Array, ::Set
|
111
|
+
super(class_or_name.class)
|
112
|
+
else
|
113
|
+
super
|
114
|
+
end
|
115
|
+
end
|
67
116
|
|
68
|
-
|
117
|
+
# A hook for Attributes to update options based on the type from the caller
|
118
|
+
#
|
119
|
+
# @param [Object] type
|
120
|
+
# The raw type, typically given by the caller of ClassMethods#attribute
|
121
|
+
# @param [Hash] options
|
122
|
+
# Attribute configuration options
|
123
|
+
#
|
124
|
+
# @return [Hash]
|
125
|
+
# New Hash instance, potentially updated with information from the args
|
126
|
+
#
|
127
|
+
# @api private
|
128
|
+
#
|
129
|
+
# @todo add type arg to Attribute#initialize signature and handle there?
|
130
|
+
def self.merge_options(type, options)
|
131
|
+
options
|
132
|
+
end
|
69
133
|
|
70
134
|
# Initializes an attribute instance
|
71
135
|
#
|
72
|
-
# @param [
|
136
|
+
# @param [#to_sym] name
|
73
137
|
# the name of an attribute
|
74
138
|
#
|
75
139
|
# @param [#to_hash] options
|
@@ -79,14 +143,13 @@ module Virtus
|
|
79
143
|
#
|
80
144
|
# @api private
|
81
145
|
def initialize(name, options = {})
|
82
|
-
@name
|
83
|
-
@options
|
84
|
-
|
85
|
-
@
|
146
|
+
@name = name.to_sym
|
147
|
+
@options = self.class.options.merge(options).freeze
|
148
|
+
@instance_variable_name = "@#{@name}".to_sym
|
149
|
+
@primitive = @options.fetch(:primitive)
|
86
150
|
@coercion_method = @options.fetch(:coercion_method)
|
87
151
|
@default = DefaultValue.new(self, @options[:default])
|
88
|
-
|
89
|
-
set_visibility
|
152
|
+
initialize_visibility
|
90
153
|
end
|
91
154
|
|
92
155
|
# Returns a concise string representation of the attribute instance
|
@@ -99,7 +162,7 @@ module Virtus
|
|
99
162
|
#
|
100
163
|
# @api public
|
101
164
|
def inspect
|
102
|
-
"#<#{self.class.
|
165
|
+
"#<#{self.class.inspect} @name=#{name.inspect}>"
|
103
166
|
end
|
104
167
|
|
105
168
|
# Returns value of an attribute for the given instance
|
@@ -118,7 +181,9 @@ module Virtus
|
|
118
181
|
if instance.instance_variable_defined?(instance_variable_name)
|
119
182
|
get!(instance)
|
120
183
|
else
|
121
|
-
|
184
|
+
value = default.evaluate(instance)
|
185
|
+
set!(instance, value)
|
186
|
+
value
|
122
187
|
end
|
123
188
|
end
|
124
189
|
|
@@ -157,6 +222,7 @@ module Virtus
|
|
157
222
|
# @api public
|
158
223
|
def set!(instance, value)
|
159
224
|
instance.instance_variable_set(instance_variable_name, value)
|
225
|
+
self
|
160
226
|
end
|
161
227
|
|
162
228
|
# Converts the given value to the primitive type
|
@@ -175,6 +241,39 @@ module Virtus
|
|
175
241
|
Coercion[value.class].send(coercion_method, value)
|
176
242
|
end
|
177
243
|
|
244
|
+
# Is the given value coerced into the target type for this attribute?
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# string_attribute = Virtus::Attribute::String.new(:str)
|
248
|
+
# string_attribute.value_coerced?('foo') # => true
|
249
|
+
# string_attribute.value_coerced?(:foo) # => false
|
250
|
+
# integer_attribute = Virtus::Attribute::Integer.new(:integer)
|
251
|
+
# integer_attribute.value_coerced?(5) # => true
|
252
|
+
# integer_attribute.value_coerced?('5') # => false
|
253
|
+
# date_attribute = Virtus::Attribute::Date.new(:date)
|
254
|
+
# date_attribute.value_coerced?('2011-12-31') # => false
|
255
|
+
# date_attribute.value_coerced?(Date.today) # => true
|
256
|
+
#
|
257
|
+
# @return [Boolean]
|
258
|
+
#
|
259
|
+
# @api private
|
260
|
+
def value_coerced?(value)
|
261
|
+
@primitive === value
|
262
|
+
end
|
263
|
+
|
264
|
+
# Define reader and writer methods for an Attribute
|
265
|
+
#
|
266
|
+
# @param [Attribute] attribute
|
267
|
+
#
|
268
|
+
# @return [self]
|
269
|
+
#
|
270
|
+
# @api private
|
271
|
+
def define_accessor_methods(mod)
|
272
|
+
define_reader_method(mod)
|
273
|
+
define_writer_method(mod)
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
178
277
|
# Creates an attribute reader method
|
179
278
|
#
|
180
279
|
# @param [Module] mod
|
@@ -183,12 +282,7 @@ module Virtus
|
|
183
282
|
#
|
184
283
|
# @api private
|
185
284
|
def define_reader_method(mod)
|
186
|
-
|
187
|
-
attribute = self
|
188
|
-
|
189
|
-
mod.send(:define_method, reader_method_name) { attribute.get(self) }
|
190
|
-
mod.send(reader_visibility, reader_method_name)
|
191
|
-
|
285
|
+
mod.define_reader_method(self, name, reader_visibility)
|
192
286
|
self
|
193
287
|
end
|
194
288
|
|
@@ -200,26 +294,39 @@ module Virtus
|
|
200
294
|
#
|
201
295
|
# @api private
|
202
296
|
def define_writer_method(mod)
|
203
|
-
|
204
|
-
|
297
|
+
mod.define_writer_method(self, "#{name}=".to_sym, writer_visibility)
|
298
|
+
self
|
299
|
+
end
|
205
300
|
|
206
|
-
|
207
|
-
|
301
|
+
# Returns a Boolean indicating whether the reader method is public
|
302
|
+
#
|
303
|
+
# @return [Boolean]
|
304
|
+
#
|
305
|
+
# @api private
|
306
|
+
def public_reader?
|
307
|
+
reader_visibility == :public
|
308
|
+
end
|
208
309
|
|
209
|
-
|
310
|
+
# Returns a Boolean indicating whether the writer method is public
|
311
|
+
#
|
312
|
+
# @return [Boolean]
|
313
|
+
#
|
314
|
+
# @api private
|
315
|
+
def public_writer?
|
316
|
+
writer_visibility == :public
|
210
317
|
end
|
211
318
|
|
212
319
|
private
|
213
320
|
|
214
|
-
#
|
321
|
+
# Initialize visibility of reader/write methods based on the options hash
|
215
322
|
#
|
216
323
|
# @return [undefined]
|
217
324
|
#
|
218
325
|
# @api private
|
219
|
-
def
|
220
|
-
default_accessor
|
221
|
-
@reader_visibility = @options.fetch(:reader,
|
222
|
-
@writer_visibility = @options.fetch(:writer,
|
326
|
+
def initialize_visibility
|
327
|
+
default_accessor = @options.fetch(:accessor)
|
328
|
+
@reader_visibility = @options.fetch(:reader, default_accessor)
|
329
|
+
@writer_visibility = @options.fetch(:writer, default_accessor)
|
223
330
|
end
|
224
331
|
|
225
332
|
end # class Attribute
|