virtus 0.0.10 → 0.1.0
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.
- 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
|