virtus 1.0.0.beta8 → 1.0.0.rc1
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/Changelog.md +28 -1
- data/LICENSE +1 -1
- data/README.md +12 -22
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/mutant.yml +2 -1
- data/config/reek.yml +67 -17
- data/lib/virtus.rb +61 -5
- data/lib/virtus/attribute.rb +107 -26
- data/lib/virtus/attribute/builder.rb +42 -34
- data/lib/virtus/attribute/collection.rb +11 -6
- data/lib/virtus/attribute/embedded_value.rb +12 -7
- data/lib/virtus/attribute/hash.rb +19 -8
- data/lib/virtus/attribute_set.rb +2 -13
- data/lib/virtus/builder.rb +137 -0
- data/lib/virtus/builder/hook_context.rb +51 -0
- data/lib/virtus/class_inclusions.rb +1 -0
- data/lib/virtus/class_methods.rb +1 -5
- data/lib/virtus/configuration.rb +12 -2
- data/lib/virtus/extensions.rb +28 -32
- data/lib/virtus/instance_methods.rb +2 -2
- data/lib/virtus/model.rb +3 -1
- data/lib/virtus/module_extensions.rb +1 -1
- data/lib/virtus/value_object.rb +1 -1
- data/lib/virtus/version.rb +1 -1
- data/spec/integration/inheritance_spec.rb +42 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +10 -0
- data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +14 -0
- data/spec/unit/virtus/class_methods/finalize_spec.rb +10 -4
- data/spec/unit/virtus/model_spec.rb +35 -3
- data/spec/unit/virtus/module_spec.rb +44 -3
- data/spec/unit/virtus/value_object_spec.rb +39 -22
- data/virtus.gemspec +2 -1
- metadata +9 -6
- data/lib/virtus/module_builder.rb +0 -192
data/Changelog.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
# v1.0.0 [to-be-released]
|
2
|
+
|
3
|
+
This release no longer works with Ruby 1.8.7.
|
4
|
+
|
5
|
+
* [BREAKING CHANGE] Integrated with axiom-types, most of the attribute sub-classes are gone (solnic)
|
6
|
+
* [feature] Configurable coercion via coercible integration (solnic)
|
7
|
+
* [feature] Strict mode for coercions via `:strict` option (solnic)
|
8
|
+
* [feature] Lazy-loaded default values via `:lazy` option (solnic)
|
9
|
+
* [feature] Finalizing models solving circular-dependency issue (see #81) (solnic)
|
10
|
+
* [feature] Ability to cherry-pick which extension should be included (solnic)
|
11
|
+
* [feature] Ability to inject a custom coercer object via `:coercer` option (solnic)
|
12
|
+
* [feature] Extension module builder with pre-defined configuration for attributes (elskwid & solnic)
|
13
|
+
* [feature] `Virtus::Attribute` exposes a public API - you can easily build, rename and clone attribute instances and use their coercion power (solnic)
|
14
|
+
* [feature] Ability to reset attributes to their default values (pewniak747)
|
15
|
+
* [changed] A meaningful error will be raised if a reserved name is used as an attribute name (solnic)
|
16
|
+
* [changed] Default value can be set via private and protected methods now (solnic)
|
17
|
+
* [changed] New syntax for value objects (solnic)
|
18
|
+
* [deprecated] `Virtus::Attribute.coerce` in favor of `Virtus.coerce` or a customized configured module (solnic)
|
19
|
+
* [deprecated] `include Virtus` in favor of `include Virtus.model` (for classes) or `Virtus.module` (for modules) (solnic)
|
20
|
+
* [deprecated] `include Virtus::ValueObject` in favor of `include Virtus.value_object` (solnic)
|
21
|
+
* [deprecated] `Virtus#attributes` in favor of `Virtus#attribute_set` (solnic)
|
22
|
+
* [fixed] const missing hook now works correctly in modules too (cored)
|
23
|
+
* [fixed] value object with Hash type works correctly (solnic)
|
24
|
+
* [fixed] issues with value-object subclasses and `#==` method (solnic)
|
25
|
+
|
26
|
+
[Compare v0.5.4..master](https://github.com/solnic/virtus/compare/v0.5.4...master)
|
27
|
+
|
1
28
|
# v0.5.4 2012-12-20
|
2
29
|
|
3
30
|
* [feature] Allow *any* enumerable to be a collection attribute (aptinio)
|
@@ -12,7 +39,7 @@
|
|
12
39
|
* [feature] Added Hash member type coercion [example](https://github.com/solnic/virtus#hash-attributes-coercion) (greyblake)
|
13
40
|
* [fixed] Fixed issues with String=>Integer coercion and e-notation (greyblake)
|
14
41
|
* [changed] Replaced internal DescendantsTracker with the extracted gem (solnic)
|
15
|
-
* [
|
42
|
+
* [internal] Switched to rspec 2 and mutant for mutation testing (mbj)
|
16
43
|
|
17
44
|
[Compare v0.5.2..v0.5.3](https://github.com/solnic/virtus/compare/v0.5.2...v0.5.3)
|
18
45
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -69,46 +69,36 @@ user.age # => 21
|
|
69
69
|
### Cherry-picking extensions
|
70
70
|
|
71
71
|
``` ruby
|
72
|
-
# include
|
72
|
+
# include attribute DSL + constructor + mass-assignment
|
73
73
|
class User
|
74
|
-
include Virtus
|
74
|
+
include Virtus.model
|
75
75
|
|
76
76
|
attribute :name, String
|
77
77
|
end
|
78
78
|
|
79
|
-
user = User.new
|
80
|
-
user.
|
79
|
+
user = User.new(:name => 'Piotr')
|
80
|
+
user.attributes = { :name => 'John' }
|
81
|
+
user.attributes
|
82
|
+
# => {:name => 'John'}
|
81
83
|
|
82
84
|
# include attribute DSL + constructor
|
83
85
|
class User
|
84
|
-
include Virtus
|
85
|
-
include Virtus::Model::Constructor
|
86
|
+
include Virtus.model(:mass_assignment => false)
|
86
87
|
|
87
88
|
attribute :name, String
|
88
89
|
end
|
89
90
|
|
90
91
|
User.new(:name => 'Piotr')
|
91
92
|
|
92
|
-
# include attribute DSL
|
93
|
+
# include just the attribute DSL
|
93
94
|
class User
|
94
|
-
include Virtus
|
95
|
-
include Virtus::Model::Constructor
|
96
|
-
include Virtus::Model::MassAssignment
|
95
|
+
include Virtus.model(:constructor => false, :mass_assignment => false)
|
97
96
|
|
98
97
|
attribute :name, String
|
99
98
|
end
|
100
99
|
|
101
|
-
user = User.new
|
102
|
-
user.
|
103
|
-
user.attributes
|
104
|
-
# => {:name => 'John'}
|
105
|
-
|
106
|
-
# starting from virtus 1.0.0 preferred way to do this is to use module builder
|
107
|
-
MyModel = Virtus.model(:constructor => false, :mass_assignment => false)
|
108
|
-
|
109
|
-
class User
|
110
|
-
include MyModel
|
111
|
-
end
|
100
|
+
user = User.new
|
101
|
+
user.name = 'Piotr'
|
112
102
|
```
|
113
103
|
|
114
104
|
### Using Virtus with Modules
|
@@ -525,7 +515,7 @@ end
|
|
525
515
|
## Attribute Finalization and Circular Dependencies
|
526
516
|
|
527
517
|
If a type references another type which happens to not be available yet you need
|
528
|
-
to use lazy-finalization of attributes and finalize virtus manually after all
|
518
|
+
to use lazy-finalization of attributes and finalize virtus manually after all
|
529
519
|
types have been already loaded:
|
530
520
|
|
531
521
|
``` ruby
|
data/config/flay.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
3
|
-
total_score:
|
2
|
+
threshold: 24
|
3
|
+
total_score: 439
|
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 33
|
data/config/mutant.yml
CHANGED
@@ -3,12 +3,13 @@ name: virtus
|
|
3
3
|
namespace:
|
4
4
|
- 'Virtus::Attribute'
|
5
5
|
- 'Virtus::AttributeSet'
|
6
|
+
- 'Virtus::Builder'
|
6
7
|
- 'Virtus::ClassInclusions'
|
7
8
|
- 'Virtus::ClassMethods'
|
8
9
|
- 'Virtus::Configuration'
|
9
10
|
- 'Virtus::ConstMissingExtensions'
|
10
11
|
- 'Virtus::Extensions'
|
11
12
|
- 'Virtus::InstanceMethods'
|
12
|
-
- 'Virtus::
|
13
|
+
- 'Virtus::Model'
|
13
14
|
- 'Virtus::ModuleExtensions'
|
14
15
|
- 'Virtus::ValueObject'
|
data/config/reek.yml
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
---
|
2
2
|
Attribute:
|
3
|
-
enabled:
|
4
|
-
exclude: []
|
3
|
+
enabled: false
|
5
4
|
BooleanParameter:
|
6
5
|
enabled: true
|
7
6
|
exclude: []
|
@@ -10,23 +9,39 @@ ClassVariable:
|
|
10
9
|
exclude: []
|
11
10
|
ControlParameter:
|
12
11
|
enabled: true
|
13
|
-
exclude:
|
12
|
+
exclude:
|
13
|
+
- 'Virtus::InstanceMethods::Constructor#initialize'
|
14
14
|
DataClump:
|
15
15
|
enabled: true
|
16
|
-
exclude: []
|
17
16
|
max_copies: 2
|
18
17
|
min_clump_size: 2
|
18
|
+
exclude:
|
19
|
+
- 'Virtus::AttributeSet'
|
19
20
|
DuplicateMethodCall:
|
20
21
|
enabled: false
|
21
22
|
FeatureEnvy:
|
22
23
|
enabled: true
|
23
|
-
exclude:
|
24
|
+
exclude:
|
25
|
+
- 'Virtus::Attribute::Boolean#value_coerced?'
|
26
|
+
- 'Virtus::AttributeSet#get'
|
27
|
+
- 'Virtus::AttributeSet#set'
|
28
|
+
- 'Virtus::AttributeSet#skip_default?'
|
29
|
+
- 'Virtus::Builder#add_extended_hook'
|
30
|
+
- 'Virtus::Builder#add_included_hook'
|
31
|
+
- 'Virtus::InstanceMethods#assert_valid_name'
|
32
|
+
- 'Virtus::TypeLookup#determine_type_from_primitive'
|
24
33
|
IrresponsibleModule:
|
25
34
|
enabled: true
|
26
35
|
exclude: []
|
27
36
|
LongParameterList:
|
28
37
|
enabled: true
|
29
|
-
exclude:
|
38
|
+
exclude:
|
39
|
+
- 'Virtus::AttributeSet#define_reader_method'
|
40
|
+
- 'Virtus::AttributeSet#define_writer_method'
|
41
|
+
- 'Virtus::Extensions::Methods#attribute'
|
42
|
+
- 'Virtus::ModuleExtensions#attribute'
|
43
|
+
- 'Virtus::ModuleExtensions#self.setup'
|
44
|
+
- 'Virtus::ValueObject::ClassMethods#attribute'
|
30
45
|
max_params: 2
|
31
46
|
LongYieldList:
|
32
47
|
enabled: true
|
@@ -36,34 +51,65 @@ NestedIterators:
|
|
36
51
|
enabled: true
|
37
52
|
max_allowed_nesting: 1
|
38
53
|
ignore_iterators: []
|
39
|
-
exclude:
|
54
|
+
exclude:
|
55
|
+
- 'Virtus::Builder#add_extended_hook'
|
56
|
+
- 'Virtus::Builder#add_included_hook'
|
57
|
+
- 'Virtus::ModuleBuilder#add_included_hook'
|
58
|
+
- 'Virtus::Equalizer#define_cmp_method'
|
59
|
+
- 'Virtus::Equalizer#define_hash_method'
|
60
|
+
- 'Virtus::Equalizer#define_inspect_method'
|
40
61
|
NilCheck:
|
41
62
|
enabled: true
|
42
|
-
exclude:
|
63
|
+
exclude:
|
64
|
+
- 'Virtus::Attribute::EmbeddedValue::FromOpenStruct#call'
|
65
|
+
- 'Virtus::Attribute::EmbeddedValue::FromStruct#call'
|
66
|
+
- 'Virtus::Attribute::Strict#coerce'
|
67
|
+
- 'Virtus::Options#options'
|
68
|
+
- 'Virtus::TypeLookup#determine_type_from_primitive'
|
43
69
|
RepeatedConditional:
|
44
70
|
enabled: true
|
45
|
-
exclude: []
|
46
71
|
max_ifs: 1
|
72
|
+
exclude:
|
73
|
+
- 'Virtus::AttributeSet'
|
74
|
+
- 'Virtus::Builder'
|
47
75
|
TooManyInstanceVariables:
|
48
76
|
enabled: true
|
49
|
-
exclude: []
|
50
77
|
max_instance_variables: 3
|
78
|
+
exclude:
|
79
|
+
- 'Virtus::Attribute'
|
80
|
+
- 'Virtus::Attribute::Builder'
|
81
|
+
- 'Virtus::Configuration'
|
51
82
|
TooManyMethods:
|
52
83
|
enabled: true
|
53
|
-
|
54
|
-
|
84
|
+
max_methods: 6
|
85
|
+
exclude:
|
86
|
+
- 'Virtus::Equalizer'
|
87
|
+
- 'Virtus::Builder'
|
88
|
+
- 'Virtus::Attribute'
|
89
|
+
- 'Virtus::AttributeSet'
|
55
90
|
TooManyStatements:
|
56
91
|
enabled: true
|
57
|
-
exclude: []
|
58
92
|
max_statements: 4
|
93
|
+
exclude:
|
94
|
+
- 'Virtus#self.included'
|
95
|
+
- 'Virtus::Attribute::Builder#self.determine_type'
|
96
|
+
- 'Virtus::Attribute::Collection#self.infer'
|
97
|
+
- 'Virtus::Attribute::Hash#self.infer'
|
98
|
+
- 'Virtus::Builder#add_extended_hook'
|
99
|
+
- 'Virtus::Builder#add_included_hook'
|
100
|
+
- 'Virtus::ModuleBuilder#add_included_hook'
|
101
|
+
- 'Virtus::ClassInclusions#self.included'
|
102
|
+
- 'Virtus::ClassMethods#self.extended'
|
103
|
+
- 'Virtus::Extensions#self.extended'
|
104
|
+
- 'Virtus::ModuleExtensions#included'
|
105
|
+
- 'Virtus::TypeLookup#determine_type_from_primitive'
|
106
|
+
- 'Virtus::ValueObject#self.included'
|
59
107
|
UncommunicativeMethodName:
|
60
108
|
enabled: true
|
61
|
-
exclude: []
|
62
109
|
reject:
|
63
110
|
- !ruby/regexp /^[a-z]$/
|
64
111
|
- !ruby/regexp /[0-9]$/
|
65
112
|
- !ruby/regexp /[A-Z]/
|
66
|
-
accept: []
|
67
113
|
UncommunicativeModuleName:
|
68
114
|
enabled: true
|
69
115
|
exclude: []
|
@@ -78,7 +124,7 @@ UncommunicativeParameterName:
|
|
78
124
|
- !ruby/regexp /^.$/
|
79
125
|
- !ruby/regexp /[0-9]$/
|
80
126
|
- !ruby/regexp /[A-Z]/
|
81
|
-
accept: []
|
127
|
+
accept: ['_']
|
82
128
|
UncommunicativeVariableName:
|
83
129
|
enabled: true
|
84
130
|
exclude: []
|
@@ -92,5 +138,9 @@ UnusedParameters:
|
|
92
138
|
exclude: []
|
93
139
|
UtilityFunction:
|
94
140
|
enabled: true
|
95
|
-
exclude: []
|
96
141
|
max_helper_calls: 0
|
142
|
+
exclude:
|
143
|
+
- 'Virtus::Attribute::Boolean#value_coerced?'
|
144
|
+
- 'Virtus::AttributeSet#set_default'
|
145
|
+
- 'Virtus::AttributeSet#skip_default?'
|
146
|
+
- 'Virtus::Extensions::Methods#merge_options'
|
data/lib/virtus.rb
CHANGED
@@ -25,6 +25,8 @@ module Virtus
|
|
25
25
|
#
|
26
26
|
# @return [undefined]
|
27
27
|
#
|
28
|
+
# @deprecated
|
29
|
+
#
|
28
30
|
# @api private
|
29
31
|
def self.included(object)
|
30
32
|
super
|
@@ -44,6 +46,8 @@ module Virtus
|
|
44
46
|
#
|
45
47
|
# @return [undefined]
|
46
48
|
#
|
49
|
+
# @deprecated
|
50
|
+
#
|
47
51
|
# @api private
|
48
52
|
def self.extended(object)
|
49
53
|
Virtus.warn("extending with Virtus module is deprecated. Use 'extend(Virtus.model)' instead #{caller.first}")
|
@@ -124,21 +128,53 @@ module Virtus
|
|
124
128
|
#
|
125
129
|
# @api public
|
126
130
|
def self.model(options = {}, &block)
|
127
|
-
|
131
|
+
ModelBuilder.call(options, &block)
|
128
132
|
end
|
129
133
|
|
130
134
|
# Builds a module for...modules
|
131
135
|
#
|
136
|
+
# @example
|
137
|
+
#
|
138
|
+
# module Common
|
139
|
+
# include Virtus.module
|
140
|
+
#
|
141
|
+
# attribute :name, String
|
142
|
+
# attribute :age, Integer
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# class User
|
146
|
+
# include Common
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# class Admin
|
150
|
+
# include Common
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# @return [Module]
|
154
|
+
#
|
132
155
|
# @api public
|
133
156
|
def self.module(options = {}, &block)
|
134
|
-
|
157
|
+
ModuleBuilder.call(options, &block)
|
135
158
|
end
|
136
159
|
|
137
160
|
# Builds a module for value object models
|
138
161
|
#
|
162
|
+
# @example
|
163
|
+
#
|
164
|
+
# class GeoLocation
|
165
|
+
# include Virtus.value_object
|
166
|
+
#
|
167
|
+
# values do
|
168
|
+
# attribute :lat, Float
|
169
|
+
# attribute :lng, Float
|
170
|
+
# end
|
171
|
+
# end
|
172
|
+
#
|
173
|
+
# @return [Module]
|
174
|
+
#
|
139
175
|
# @api public
|
140
176
|
def self.value_object(options = {}, &block)
|
141
|
-
|
177
|
+
ValueObjectBuilder.call(options, &block)
|
142
178
|
end
|
143
179
|
|
144
180
|
# Global configuration instance
|
@@ -150,9 +186,28 @@ module Virtus
|
|
150
186
|
@configuration ||= Configuration.new
|
151
187
|
end
|
152
188
|
|
189
|
+
# Finalize pending attributes
|
190
|
+
#
|
191
|
+
# @example
|
192
|
+
# class User
|
193
|
+
# include Virtus.model(:finalize => false)
|
194
|
+
#
|
195
|
+
# attribute :address, 'Address'
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# class Address
|
199
|
+
# include Virtus.model(:finalize => false)
|
200
|
+
#
|
201
|
+
# attribute :user, 'User'
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# Virtus.finalize # this will resolve constant names
|
205
|
+
#
|
206
|
+
# @return [Array] array of finalized models
|
207
|
+
#
|
153
208
|
# @api public
|
154
209
|
def self.finalize
|
155
|
-
|
210
|
+
Builder.pending.each do |klass|
|
156
211
|
klass.attribute_set.finalize
|
157
212
|
end
|
158
213
|
end
|
@@ -180,7 +235,8 @@ require 'virtus/class_inclusions'
|
|
180
235
|
require 'virtus/module_extensions'
|
181
236
|
|
182
237
|
require 'virtus/configuration'
|
183
|
-
require 'virtus/
|
238
|
+
require 'virtus/builder'
|
239
|
+
require 'virtus/builder/hook_context'
|
184
240
|
|
185
241
|
require 'virtus/class_methods'
|
186
242
|
require 'virtus/instance_methods'
|
data/lib/virtus/attribute.rb
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
module Virtus
|
2
2
|
|
3
|
+
# Attribute objects handle coercion and provide interface to hook into an
|
4
|
+
# attribute set instance that's included into a class or object
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# # non-strict mode
|
9
|
+
# attr = Virtus::Attribute.build(Integer)
|
10
|
+
# attr.coerce('1')
|
11
|
+
# # => 1
|
12
|
+
#
|
13
|
+
# # strict mode
|
14
|
+
# attr = Virtus::Attribute.build(Integer, :strict => true)
|
15
|
+
# attr.coerce('not really coercible')
|
16
|
+
# # => Virtus::CoercionError: Failed to coerce "fsafa" into Integer
|
17
|
+
#
|
3
18
|
class Attribute
|
4
19
|
extend DescendantsTracker, Options, TypeLookup
|
5
20
|
|
@@ -24,22 +39,28 @@ module Virtus
|
|
24
39
|
self
|
25
40
|
end
|
26
41
|
|
27
|
-
|
42
|
+
# Return type of this attribute
|
43
|
+
#
|
44
|
+
# @return [Axiom::Types::Type]
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
attr_reader :type
|
48
|
+
|
49
|
+
# @api private
|
50
|
+
attr_reader :primitive, :options, :default_value, :coercer
|
28
51
|
|
29
52
|
# Builds an attribute instance
|
30
53
|
#
|
31
|
-
# @param [Symbol]
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# @param [Class] type
|
35
|
-
# optional type class of an attribute
|
54
|
+
# @param [Class,Array,Hash,String,Symbol] type
|
55
|
+
# this can be an explicit class or an object from which virtus can infer
|
56
|
+
# the type
|
36
57
|
#
|
37
58
|
# @param [#to_hash] options
|
38
59
|
# optional extra options hash
|
39
60
|
#
|
40
61
|
# @return [Attribute]
|
41
62
|
#
|
42
|
-
# @api
|
63
|
+
# @api public
|
43
64
|
def self.build(type, options = {})
|
44
65
|
Builder.call(type, options)
|
45
66
|
end
|
@@ -52,13 +73,6 @@ module Virtus
|
|
52
73
|
)
|
53
74
|
end
|
54
75
|
|
55
|
-
# @api private
|
56
|
-
def self.new(*args)
|
57
|
-
attribute = super
|
58
|
-
yield(attribute)
|
59
|
-
attribute
|
60
|
-
end
|
61
|
-
|
62
76
|
# @api private
|
63
77
|
def self.build_type(definition)
|
64
78
|
Axiom::Types.infer(definition.primitive)
|
@@ -69,16 +83,6 @@ module Virtus
|
|
69
83
|
# noop
|
70
84
|
end
|
71
85
|
|
72
|
-
# Initializes an attribute instance
|
73
|
-
#
|
74
|
-
# @param [#to_sym] name
|
75
|
-
# the name of an attribute
|
76
|
-
#
|
77
|
-
# @param [#to_hash] options
|
78
|
-
# hash of extra options which overrides defaults set on an attribute class
|
79
|
-
#
|
80
|
-
# @return [undefined]
|
81
|
-
#
|
82
86
|
# @api private
|
83
87
|
def initialize(type, options)
|
84
88
|
@type = type
|
@@ -88,16 +92,37 @@ module Virtus
|
|
88
92
|
@coercer = options.fetch(:coercer)
|
89
93
|
end
|
90
94
|
|
95
|
+
# Coerce the input into the expected type
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
#
|
99
|
+
# attr = Virtus::Attribute.build(String)
|
100
|
+
# attr.coerce(:one) # => 'one'
|
101
|
+
#
|
102
|
+
# @param [Object] input
|
103
|
+
#
|
91
104
|
# @api public
|
92
|
-
def coerce(
|
93
|
-
coercer.call(
|
105
|
+
def coerce(input)
|
106
|
+
coercer.call(input)
|
94
107
|
end
|
95
108
|
|
109
|
+
# Return a new attribute with the new name
|
110
|
+
#
|
111
|
+
# @param [Symbol] name
|
112
|
+
#
|
113
|
+
# @return [Attribute]
|
114
|
+
#
|
96
115
|
# @api public
|
97
116
|
def rename(name)
|
98
117
|
self.class.build(type, options.merge(:name => name))
|
99
118
|
end
|
100
119
|
|
120
|
+
# Return if the given value was coerced
|
121
|
+
#
|
122
|
+
# @param [Object] value
|
123
|
+
#
|
124
|
+
# @return [Boolean]
|
125
|
+
#
|
101
126
|
# @api public
|
102
127
|
def value_coerced?(value)
|
103
128
|
coercer.success?(primitive, value)
|
@@ -105,6 +130,14 @@ module Virtus
|
|
105
130
|
|
106
131
|
# Return if the attribute is coercible
|
107
132
|
#
|
133
|
+
# @example
|
134
|
+
#
|
135
|
+
# attr = Virtus::Attribute.build(String, :coerce => true)
|
136
|
+
# attr.coercible? # => true
|
137
|
+
#
|
138
|
+
# attr = Virtus::Attribute.build(String, :coerce => false)
|
139
|
+
# attr.coercible? # => false
|
140
|
+
#
|
108
141
|
# @return [Boolean]
|
109
142
|
#
|
110
143
|
# @api public
|
@@ -112,21 +145,69 @@ module Virtus
|
|
112
145
|
kind_of?(Coercible)
|
113
146
|
end
|
114
147
|
|
148
|
+
# Return if the attribute has lazy default value evaluation
|
149
|
+
#
|
150
|
+
# @example
|
151
|
+
#
|
152
|
+
# attr = Virtus::Attribute.build(String, :lazy => true)
|
153
|
+
# attr.lazy? # => true
|
154
|
+
#
|
155
|
+
# attr = Virtus::Attribute.build(String, :lazy => false)
|
156
|
+
# attr.lazy? # => false
|
157
|
+
#
|
158
|
+
# @return [Boolean]
|
159
|
+
#
|
115
160
|
# @api public
|
116
161
|
def lazy?
|
117
162
|
kind_of?(LazyDefault)
|
118
163
|
end
|
119
164
|
|
165
|
+
# Return if the attribute is in the strict coercion mode
|
166
|
+
#
|
167
|
+
# @example
|
168
|
+
#
|
169
|
+
# attr = Virtus::Attribute.build(String, :strict => true)
|
170
|
+
# attr.strict? # => true
|
171
|
+
#
|
172
|
+
# attr = Virtus::Attribute.build(String, :strict => false)
|
173
|
+
# attr.strict? # => false
|
174
|
+
#
|
175
|
+
# @return [Boolean]
|
176
|
+
#
|
120
177
|
# @api public
|
121
178
|
def strict?
|
122
179
|
kind_of?(Strict)
|
123
180
|
end
|
124
181
|
|
182
|
+
# Return if the attribute is accepts nil values as valid coercion output
|
183
|
+
#
|
184
|
+
# @example
|
185
|
+
#
|
186
|
+
# attr = Virtus::Attribute.build(String, :required => true)
|
187
|
+
# attr.required? # => true
|
188
|
+
#
|
189
|
+
# attr = Virtus::Attribute.build(String, :required => false)
|
190
|
+
# attr.required? # => false
|
191
|
+
#
|
192
|
+
# @return [Boolean]
|
193
|
+
#
|
125
194
|
# @api public
|
126
195
|
def required?
|
127
196
|
options[:required]
|
128
197
|
end
|
129
198
|
|
199
|
+
# Return if the attribute was already finalized
|
200
|
+
#
|
201
|
+
# @example
|
202
|
+
#
|
203
|
+
# attr = Virtus::Attribute.build(String, :finalize => true)
|
204
|
+
# attr.finalized? # => true
|
205
|
+
#
|
206
|
+
# attr = Virtus::Attribute.build(String, :finalize => false)
|
207
|
+
# attr.finalized? # => false
|
208
|
+
#
|
209
|
+
# @return [Boolean]
|
210
|
+
#
|
130
211
|
# @api public
|
131
212
|
def finalized?
|
132
213
|
frozen?
|