virtus 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +10 -2
- data/Guardfile +9 -0
- data/README.md +12 -8
- data/TODO +0 -35
- data/config/flay.yml +1 -1
- data/config/site.reek +3 -1
- data/lib/virtus.rb +1 -0
- data/lib/virtus/attribute.rb +1 -1
- data/lib/virtus/attribute/collection.rb +2 -2
- data/lib/virtus/attribute/default_value/from_symbol.rb +2 -2
- data/lib/virtus/attribute_set.rb +4 -17
- data/lib/virtus/attributes_accessor.rb +22 -20
- data/lib/virtus/class_methods.rb +1 -1
- data/lib/virtus/coercion/hash.rb +1 -1
- data/lib/virtus/coercion/object.rb +1 -1
- data/lib/virtus/coercion/string.rb +20 -7
- data/lib/virtus/coercion/time_coercions.rb +5 -1
- data/lib/virtus/instance_methods.rb +8 -8
- data/lib/virtus/support/type_lookup.rb +24 -8
- data/lib/virtus/value_object/equalizer.rb +3 -2
- data/lib/virtus/version.rb +1 -1
- data/spec/shared/options_class_method.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +1 -7
- data/spec/unit/virtus/attribute/coerce_spec.rb +2 -2
- data/spec/unit/virtus/attribute/collection/coerce_and_append_member_spec.rb +16 -0
- data/spec/unit/virtus/attribute/collection/coerce_spec.rb +20 -7
- data/spec/unit/virtus/attribute/collection/member_coercion/coerce_and_append_member_spec.rb +18 -0
- data/spec/unit/virtus/attribute/collection/member_type_spec.rb +17 -0
- data/spec/unit/virtus/attribute/collection/new_collection_spec.rb +9 -0
- data/spec/unit/virtus/attribute/default_value/class_methods/build_spec.rb +25 -0
- data/spec/unit/virtus/attribute/default_value/evaluate_spec.rb +0 -43
- data/spec/unit/virtus/attribute/default_value/from_callable/class_methods/handle_spec.rb +20 -0
- data/spec/unit/virtus/attribute/default_value/from_callable/evaluate_spec.rb +21 -0
- data/spec/unit/virtus/attribute/default_value/from_clonable/class_methods/handle_spec.rb +20 -0
- data/spec/unit/virtus/attribute/default_value/from_clonable/evaluate_spec.rb +22 -0
- data/spec/unit/virtus/attribute/default_value/from_symbol/class_methods/handle_spec.rb +20 -0
- data/spec/unit/virtus/attribute/default_value/from_symbol/evaluate_spec.rb +18 -0
- data/spec/unit/virtus/attribute_set/element_set_spec.rb +5 -4
- data/spec/unit/virtus/attributes_accessor/define_reader_method_spec.rb +36 -0
- data/spec/unit/virtus/attributes_accessor/define_writer_method_spec.rb +36 -0
- data/spec/unit/virtus/coercion/array/{to_set_spec.rb → class_methods/to_set_spec.rb} +0 -0
- data/spec/unit/virtus/coercion/{class_name_reference_spec.rb → class_methods/element_reference_spec.rb} +0 -0
- data/spec/unit/virtus/coercion/class_methods/primitive_spec.rb +13 -0
- data/spec/unit/virtus/coercion/decimal/class_methods/to_decimal_spec.rb +10 -0
- data/spec/unit/virtus/coercion/float/class_methods/to_float_spec.rb +10 -0
- data/spec/unit/virtus/coercion/integer/class_methods/to_integer_spec.rb +10 -0
- data/spec/unit/virtus/coercion/numeric/class_methods/to_decimal_spec.rb +0 -0
- data/spec/unit/virtus/coercion/numeric/class_methods/to_float_spec.rb +0 -0
- data/spec/unit/virtus/coercion/numeric/class_methods/to_integer_spec.rb +0 -0
- data/spec/unit/virtus/coercion/numeric/class_methods/to_string_spec.rb +0 -0
- data/spec/unit/virtus/coercion/object/class_methods/to_string_spec.rb +1 -1
- data/spec/unit/virtus/coercion/string/class_methods/to_symbol_spec.rb +10 -0
- data/spec/unit/virtus/coercion/time/class_methods/to_integer_spec.rb +11 -0
- data/spec/unit/virtus/instance_methods/attributes_spec.rb +25 -0
- data/spec/unit/virtus/instance_methods/initialize_spec.rb +42 -0
- data/spec/unit/virtus/type_lookup/class_methods/extended_spec.rb +10 -0
- data/spec/unit/virtus/value_object/class_methods/attribute_spec.rb +16 -0
- data/spec/unit/virtus/value_object/equalizer/append_spec.rb +61 -0
- data/virtus.gemspec +4 -3
- metadata +80 -75
- data/spec/unit/virtus/attribute_set/parent_spec.rb +0 -11
data/Changelog.md
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
# v0.
|
1
|
+
# v0.4.0 2012-03-22
|
2
|
+
|
3
|
+
* [improvement] Add a caching mechanism for type lookups (solnic)
|
4
|
+
* [fixed] Fix attributes mass-assignment when nil is passed (fgrehm)
|
5
|
+
* [changed] Replace usage of #to_hash with Hash.try_convert (dkubb)
|
6
|
+
|
7
|
+
[Compare v0.3.0..v0.4.0](https://github.com/solnic/virtus/compare/v0.3.0...master)
|
8
|
+
|
9
|
+
# v0.3.0 2012-02-25
|
2
10
|
|
3
11
|
* [feature] Support for default values from a symbol (which can be a method name) (solnic)
|
4
12
|
* [feature] Support for mass-assignment via custom setters not generated with attribute (fgrehm)
|
@@ -13,7 +21,7 @@
|
|
13
21
|
* [BREAKING CHANGE] Removed Attribute#instance_variable_name - this is a private ivar (solnic)
|
14
22
|
* [BREAKING CHANGE] Removed Equalizer#host_name and Equalizer#keys (solnic)
|
15
23
|
|
16
|
-
[Compare v0.2.0..
|
24
|
+
[Compare v0.2.0..v0.3.0](https://github.com/solnic/virtus/compare/v0.2.0...v0.3.0)
|
17
25
|
|
18
26
|
# v0.2.0 2012-02-08
|
19
27
|
|
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -61,13 +61,16 @@ class Page
|
|
61
61
|
include Virtus
|
62
62
|
|
63
63
|
attribute :title, String
|
64
|
-
|
64
|
+
|
65
65
|
# default from a singleton value (integer in this case)
|
66
66
|
attribute :views, Integer, :default => 0
|
67
|
-
|
67
|
+
|
68
|
+
# default from a singleton value (boolean in this case)
|
69
|
+
attribute :published, Boolean, :default => false
|
70
|
+
|
68
71
|
# default from a callable object (proc in this case)
|
69
72
|
attribute :slug, String, :default => lambda { |page, attribute| page.title.downcase.gsub(' ', '-') }
|
70
|
-
|
73
|
+
|
71
74
|
# default from a method name as symbol
|
72
75
|
attribute :editor_title, String, :default => :default_editor_title
|
73
76
|
|
@@ -76,10 +79,11 @@ class Page
|
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
79
|
-
page = Page.new(:title => 'Virtus
|
80
|
-
page.slug
|
81
|
-
page.views
|
82
|
-
page.
|
82
|
+
page = Page.new(:title => 'Virtus README')
|
83
|
+
page.slug # => 'virtus-readme'
|
84
|
+
page.views # => 0
|
85
|
+
page.published # => false
|
86
|
+
page.editor_title # => "UNPUBLISHED: Virtus README"
|
83
87
|
```
|
84
88
|
|
85
89
|
**Embedded Value**
|
@@ -238,7 +242,7 @@ user.password # => '3858f62230ac3c915f300c664312c63f'
|
|
238
242
|
``` ruby
|
239
243
|
require 'json'
|
240
244
|
|
241
|
-
module
|
245
|
+
module MyApp
|
242
246
|
|
243
247
|
# Defining the custom attribute(s)
|
244
248
|
module Attributes
|
data/TODO
CHANGED
@@ -1,36 +1 @@
|
|
1
|
-
* Add missing specs:
|
2
|
-
* Add spec file spec/unit/virtus/attribute/collection/member_coercion/coerce_and_append_member_spec.rb for Virtus::Attribute::Collection::MemberCoercion#coerce_and_append_member
|
3
|
-
* Add spec file spec/unit/virtus/attribute/collection/member_type_spec.rb for Virtus::Attribute::Collection#member_type
|
4
|
-
* Add spec file spec/unit/virtus/attribute/collection/new_collection_spec.rb for Virtus::Attribute::Collection#new_collection
|
5
|
-
* Add spec file spec/unit/virtus/attribute/collection/coerce_and_append_member_spec.rb for Virtus::Attribute::Collection#coerce_and_append_member
|
6
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_symbol/class_methods/handle_spec.rb for Virtus::Attribute::DefaultValue::FromSymbol.handle?
|
7
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_symbol/evaluate_spec.rb for Virtus::Attribute::DefaultValue::FromSymbol#evaluate
|
8
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_callable/class_methods/handle_spec.rb for Virtus::Attribute::DefaultValue::FromCallable.handle?
|
9
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_callable/evaluate_spec.rb for Virtus::Attribute::DefaultValue::FromCallable#evaluate
|
10
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_clonable/class_methods/handle_spec.rb for Virtus::Attribute::DefaultValue::FromClonable.handle?
|
11
|
-
* Add spec file spec/unit/virtus/attribute/default_value/from_clonable/evaluate_spec.rb for Virtus::Attribute::DefaultValue::FromClonable#evaluate
|
12
|
-
* Add spec file spec/unit/virtus/attribute/default_value/class_methods/build_spec.rb for Virtus::Attribute::DefaultValue.build
|
13
|
-
* Add spec file spec/unit/virtus/coercion/string/class_methods/to_symbol_spec.rb for Virtus::Coercion::String.to_symbol
|
14
|
-
* Add spec file spec/unit/virtus/coercion/time/class_methods/to_integer_spec.rb for Virtus::Coercion::Time.to_integer
|
15
|
-
* Add spec file spec/unit/virtus/coercion/time_coercions/to_datetime_spec.rb for Virtus::Coercion::TimeCoercions#to_datetime
|
16
|
-
* Add spec file spec/unit/virtus/coercion/time_coercions/to_time_spec.rb for Virtus::Coercion::TimeCoercions#to_time
|
17
|
-
* Add spec file spec/unit/virtus/coercion/time_coercions/to_date_spec.rb for Virtus::Coercion::TimeCoercions#to_date
|
18
|
-
* Add spec file spec/unit/virtus/coercion/time_coercions/to_string_spec.rb for Virtus::Coercion::TimeCoercions#to_string
|
19
|
-
* Add spec file spec/unit/virtus/coercion/array/class_methods/to_set_spec.rb for Virtus::Coercion::Array.to_set
|
20
|
-
* Add spec file spec/unit/virtus/coercion/decimal/class_methods/to_decimal_spec.rb for Virtus::Coercion::Decimal.to_decimal
|
21
|
-
* Add spec file spec/unit/virtus/coercion/float/class_methods/to_float_spec.rb for Virtus::Coercion::Float.to_float
|
22
|
-
* Add spec file spec/unit/virtus/coercion/integer/class_methods/to_integer_spec.rb for Virtus::Coercion::Integer.to_integer
|
23
|
-
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_decimal_spec.rb for Virtus::Coercion::Numeric.to_decimal
|
24
|
-
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_float_spec.rb for Virtus::Coercion::Numeric.to_float
|
25
|
-
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_integer_spec.rb for Virtus::Coercion::Numeric.to_integer
|
26
|
-
* Add spec file spec/unit/virtus/coercion/numeric/class_methods/to_string_spec.rb for Virtus::Coercion::Numeric.to_string
|
27
|
-
* Add spec file spec/unit/virtus/coercion/class_methods/element_reference_spec.rb for Virtus::Coercion.[]
|
28
|
-
* Add spec file spec/unit/virtus/coercion/class_methods/primitive_spec.rb for Virtus::Coercion.primitive
|
29
|
-
* Add spec file spec/unit/virtus/value_object/class_methods/attribute_spec.rb for Virtus::ValueObject::ClassMethods#attribute
|
30
|
-
* Add spec file spec/unit/virtus/value_object/instance_methods/with_spec.rb for Virtus::ValueObject::InstanceMethods#with
|
31
|
-
* Add spec file spec/unit/virtus/value_object/equalizer/append_spec.rb for Virtus::ValueObject::Equalizer#<<
|
32
|
-
* Add spec file spec/unit/virtus/value_object/equalizer/compile_spec.rb for Virtus::ValueObject::Equalizer#compile
|
33
|
-
* Add spec file spec/unit/virtus/attributes_accessor/define_reader_method_spec.rb for Virtus::AttributesAccessor#define_reader_method
|
34
|
-
* Add spec file spec/unit/virtus/attributes_accessor/define_writer_method_spec.rb for Virtus::AttributesAccessor#define_writer_method
|
35
|
-
|
36
1
|
* Make #to_time #to_date and #to_datetime work on Ruby 1.8.7 instead of typecasting to string and parsing the value
|
data/config/flay.yml
CHANGED
data/config/site.reek
CHANGED
data/lib/virtus.rb
CHANGED
data/lib/virtus/attribute.rb
CHANGED
@@ -217,7 +217,7 @@ module Virtus
|
|
217
217
|
#
|
218
218
|
# @api public
|
219
219
|
def coerce(value)
|
220
|
-
Coercion[value.class].
|
220
|
+
Coercion[value.class].public_send(coercion_method, value)
|
221
221
|
end
|
222
222
|
|
223
223
|
# Is the given value coerced into the target type for this attribute?
|
@@ -63,8 +63,8 @@ module Virtus
|
|
63
63
|
def coerce(value)
|
64
64
|
coerced = super
|
65
65
|
return coerced unless coerced.respond_to?(:inject)
|
66
|
-
coerced.inject(new_collection) do |
|
67
|
-
coerce_and_append_member(
|
66
|
+
coerced.inject(new_collection) do |*args|
|
67
|
+
coerce_and_append_member(*args)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -16,7 +16,7 @@ module Virtus
|
|
16
16
|
value.is_a?(::Symbol)
|
17
17
|
end
|
18
18
|
|
19
|
-
# Evaluates the value via instance#
|
19
|
+
# Evaluates the value via instance#public_send(value)
|
20
20
|
#
|
21
21
|
# Symbol value is returned if the instance doesn't respond to value
|
22
22
|
#
|
@@ -26,7 +26,7 @@ module Virtus
|
|
26
26
|
#
|
27
27
|
# @api private
|
28
28
|
def evaluate(instance)
|
29
|
-
instance.respond_to?(@value) ? instance.
|
29
|
+
instance.respond_to?(@value) ? instance.public_send(@value) : @value
|
30
30
|
end
|
31
31
|
|
32
32
|
end # class FromSymbol
|
data/lib/virtus/attribute_set.rb
CHANGED
@@ -4,17 +4,6 @@ module Virtus
|
|
4
4
|
class AttributeSet
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
-
# Return the parent attributes
|
8
|
-
#
|
9
|
-
# @return [AttributeSet]
|
10
|
-
# the parent attributes
|
11
|
-
#
|
12
|
-
# @return [nil]
|
13
|
-
# nil if there are no parent attributes
|
14
|
-
#
|
15
|
-
# @api private
|
16
|
-
attr_reader :parent
|
17
|
-
|
18
7
|
# Initialize an AttributeSet
|
19
8
|
#
|
20
9
|
# @param [AttributeSet] parent
|
@@ -27,7 +16,6 @@ module Virtus
|
|
27
16
|
@parent = parent
|
28
17
|
@attributes = attributes.dup
|
29
18
|
@index = {}
|
30
|
-
@string_index = {}
|
31
19
|
reset
|
32
20
|
end
|
33
21
|
|
@@ -47,7 +35,7 @@ module Virtus
|
|
47
35
|
# @api public
|
48
36
|
def each
|
49
37
|
return to_enum unless block_given?
|
50
|
-
@index.
|
38
|
+
@index.values.uniq.each { |attribute| yield attribute }
|
51
39
|
self
|
52
40
|
end
|
53
41
|
|
@@ -92,7 +80,7 @@ module Virtus
|
|
92
80
|
#
|
93
81
|
# @api public
|
94
82
|
def [](name)
|
95
|
-
@index
|
83
|
+
@index[name]
|
96
84
|
end
|
97
85
|
|
98
86
|
# Set an attribute by name
|
@@ -117,8 +105,7 @@ module Virtus
|
|
117
105
|
#
|
118
106
|
# @api private
|
119
107
|
def reset
|
120
|
-
parent
|
121
|
-
merge_attributes(parent) if parent
|
108
|
+
merge_attributes(@parent) if @parent
|
122
109
|
merge_attributes(@attributes)
|
123
110
|
self
|
124
111
|
end
|
@@ -146,7 +133,7 @@ module Virtus
|
|
146
133
|
#
|
147
134
|
# @api private
|
148
135
|
def update_index(name, attribute)
|
149
|
-
@index[name] = @
|
136
|
+
@index[name] = @index[name.to_s.freeze] = attribute
|
150
137
|
end
|
151
138
|
|
152
139
|
end # class AttributeSet
|
@@ -3,25 +3,6 @@ module Virtus
|
|
3
3
|
# Host attribute accessor methods
|
4
4
|
class AttributesAccessor < Module
|
5
5
|
|
6
|
-
# The inspect value of this Module
|
7
|
-
#
|
8
|
-
# This provides meaningful output when inspecting the ancestors
|
9
|
-
# of a class/module that includes this module
|
10
|
-
#
|
11
|
-
# @example
|
12
|
-
#
|
13
|
-
# class ClassWithAttributes
|
14
|
-
# include Virtus
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# mod = ClassWithAttributes.send(:virtus_setup_attributes_accessor_module)
|
18
|
-
# mod.inspect
|
19
|
-
#
|
20
|
-
# @return [String]
|
21
|
-
#
|
22
|
-
# @api public
|
23
|
-
attr_reader :inspect
|
24
|
-
|
25
6
|
# Initialize a module for hosting Attribute access methods
|
26
7
|
#
|
27
8
|
# @param [Symbol, String] name
|
@@ -29,7 +10,7 @@ module Virtus
|
|
29
10
|
# @api private
|
30
11
|
def initialize(name)
|
31
12
|
super()
|
32
|
-
@
|
13
|
+
@name = name
|
33
14
|
end
|
34
15
|
|
35
16
|
# Defines an attribute reader method
|
@@ -62,5 +43,26 @@ module Virtus
|
|
62
43
|
self
|
63
44
|
end
|
64
45
|
|
46
|
+
# The inspect value of this Module
|
47
|
+
#
|
48
|
+
# This provides meaningful output when inspecting the ancestors
|
49
|
+
# of a class/module that includes this module
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
#
|
53
|
+
# class ClassWithAttributes
|
54
|
+
# include Virtus
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# mod = ClassWithAttributes.send(:virtus_setup_attributes_accessor_module)
|
58
|
+
# mod.inspect
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
#
|
62
|
+
# @api public
|
63
|
+
def inspect
|
64
|
+
"#{@name}::AttributesAccessor"
|
65
|
+
end
|
66
|
+
|
65
67
|
end
|
66
68
|
end
|
data/lib/virtus/class_methods.rb
CHANGED
@@ -76,7 +76,7 @@ module Virtus
|
|
76
76
|
return @attributes if defined?(@attributes)
|
77
77
|
superclass = self.superclass
|
78
78
|
method = __method__
|
79
|
-
parent = superclass.
|
79
|
+
parent = superclass.public_send(method) if superclass.respond_to?(method)
|
80
80
|
@attributes = AttributeSet.new(parent)
|
81
81
|
end
|
82
82
|
|
data/lib/virtus/coercion/hash.rb
CHANGED
@@ -115,7 +115,7 @@ module Virtus
|
|
115
115
|
#
|
116
116
|
# @api private
|
117
117
|
def self.coerce_with_method(value, method)
|
118
|
-
value.respond_to?(method) ? value.
|
118
|
+
value.respond_to?(method) ? value.public_send(method) : value
|
119
119
|
end
|
120
120
|
|
121
121
|
private_class_method :coerce_with_method
|
@@ -27,15 +27,28 @@ module Virtus
|
|
27
27
|
def self.to_constant(value)
|
28
28
|
names = value.split('::')
|
29
29
|
names.shift if names.first.empty?
|
30
|
-
names.inject(::Object)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
names.inject(::Object) { |*args| constant_lookup(*args) }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Lookup a constant within a module
|
34
|
+
#
|
35
|
+
# @param [Module] mod
|
36
|
+
#
|
37
|
+
# @param [String] name
|
38
|
+
#
|
39
|
+
# @return [Object]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
def self.constant_lookup(mod, name)
|
43
|
+
if mod.const_defined?(name, *EXTRA_CONST_ARGS)
|
44
|
+
mod.const_get(name, *EXTRA_CONST_ARGS)
|
45
|
+
else
|
46
|
+
mod.const_missing(name)
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
50
|
+
private_class_method :constant_lookup
|
51
|
+
|
39
52
|
# Coerce give value to a symbol
|
40
53
|
#
|
41
54
|
# @example
|
@@ -167,7 +180,7 @@ module Virtus
|
|
167
180
|
# @api private
|
168
181
|
def self.to_numeric(value, method)
|
169
182
|
if value =~ NUMERIC_REGEXP
|
170
|
-
$1.
|
183
|
+
$1.public_send(method)
|
171
184
|
else
|
172
185
|
value
|
173
186
|
end
|
@@ -74,7 +74,11 @@ module Virtus
|
|
74
74
|
# @api private
|
75
75
|
def coerce_with_method(value, method)
|
76
76
|
coerced = super
|
77
|
-
coerced.equal?(value)
|
77
|
+
if coerced.equal?(value)
|
78
|
+
String.public_send(method, to_string(value))
|
79
|
+
else
|
80
|
+
coerced
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
end # module TimeCoercions
|
@@ -11,8 +11,8 @@ module Virtus
|
|
11
11
|
# @return [undefined]
|
12
12
|
#
|
13
13
|
# @api private
|
14
|
-
def initialize(
|
15
|
-
self.attributes =
|
14
|
+
def initialize(attributes = nil)
|
15
|
+
self.attributes = attributes if attributes
|
16
16
|
end
|
17
17
|
|
18
18
|
# Returns a value of the attribute with the given name
|
@@ -87,7 +87,7 @@ module Virtus
|
|
87
87
|
|
88
88
|
# Mass-assign attribute values
|
89
89
|
#
|
90
|
-
# Keys in the +
|
90
|
+
# Keys in the +attributes+ param can be symbols or strings.
|
91
91
|
# All referenced Attribute writer methods *will* be called.
|
92
92
|
# Non-attribute setter methods on the receiver *will* be called.
|
93
93
|
#
|
@@ -102,14 +102,14 @@ module Virtus
|
|
102
102
|
# user = User.new
|
103
103
|
# user.attributes = { :name => 'John', 'age' => 28 }
|
104
104
|
#
|
105
|
-
# @param [#to_hash]
|
105
|
+
# @param [#to_hash] attributes
|
106
106
|
# a hash of attribute names and values to set on the receiver
|
107
107
|
#
|
108
108
|
# @return [Hash]
|
109
109
|
#
|
110
110
|
# @api public
|
111
|
-
def attributes=(
|
112
|
-
set_attributes(
|
111
|
+
def attributes=(attributes)
|
112
|
+
set_attributes(attributes)
|
113
113
|
end
|
114
114
|
|
115
115
|
# Returns a hash of all publicly accessible attributes
|
@@ -153,8 +153,8 @@ module Virtus
|
|
153
153
|
# @return [Hash]
|
154
154
|
#
|
155
155
|
# @api private
|
156
|
-
def set_attributes(
|
157
|
-
|
156
|
+
def set_attributes(attributes)
|
157
|
+
::Hash.try_convert(attributes).each do |name, value|
|
158
158
|
set_attribute(name, value) if self.class.allowed_writer_methods.include?("#{name}=")
|
159
159
|
end
|
160
160
|
end
|
@@ -5,6 +5,17 @@ module Virtus
|
|
5
5
|
|
6
6
|
TYPE_FORMAT = /\A[A-Z]\w*\z/.freeze
|
7
7
|
|
8
|
+
# Set cache ivar on the model
|
9
|
+
#
|
10
|
+
# @param [Class] model
|
11
|
+
#
|
12
|
+
# @return [undefined]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def self.extended(model)
|
16
|
+
model.instance_variable_set('@type_lookup_cache', {})
|
17
|
+
end
|
18
|
+
|
8
19
|
# Returns a descendant based on a name or class
|
9
20
|
#
|
10
21
|
# @example
|
@@ -21,14 +32,7 @@ module Virtus
|
|
21
32
|
#
|
22
33
|
# @api public
|
23
34
|
def determine_type(class_or_name)
|
24
|
-
|
25
|
-
when singleton_class
|
26
|
-
determine_type_from_descendant(class_or_name)
|
27
|
-
when Class
|
28
|
-
determine_type_from_primitive(class_or_name)
|
29
|
-
else
|
30
|
-
determine_type_from_string(class_or_name.to_s)
|
31
|
-
end
|
35
|
+
@type_lookup_cache[class_or_name] ||= determine_type_and_cache(class_or_name)
|
32
36
|
end
|
33
37
|
|
34
38
|
# Return the default primitive supported
|
@@ -42,6 +46,18 @@ module Virtus
|
|
42
46
|
|
43
47
|
private
|
44
48
|
|
49
|
+
# @api private
|
50
|
+
def determine_type_and_cache(class_or_name)
|
51
|
+
type = case class_or_name
|
52
|
+
when singleton_class
|
53
|
+
determine_type_from_descendant(class_or_name)
|
54
|
+
when Class
|
55
|
+
determine_type_from_primitive(class_or_name)
|
56
|
+
else
|
57
|
+
determine_type_from_string(class_or_name.to_s)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
45
61
|
# Return the class given a descendant
|
46
62
|
#
|
47
63
|
# @param [Class] descendant
|