virtus 0.3.0 → 0.4.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/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
|