virtus 0.5.5 → 1.0.0.beta3
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/.rspec +1 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -8
- data/Gemfile +8 -2
- data/Gemfile.devtools +24 -30
- data/Guardfile +17 -6
- data/README.md +215 -77
- data/TODO.md +6 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/mutant.yml +12 -1
- data/config/reek.yml +57 -66
- data/lib/virtus.rb +126 -42
- data/lib/virtus/attribute.rb +52 -240
- data/lib/virtus/attribute/accessor.rb +91 -0
- data/lib/virtus/attribute/boolean.rb +11 -8
- data/lib/virtus/attribute/builder.rb +120 -0
- data/lib/virtus/attribute/coercer.rb +51 -0
- data/lib/virtus/attribute/coercible.rb +14 -0
- data/lib/virtus/attribute/collection.rb +44 -90
- data/lib/virtus/attribute/default_value/from_callable.rb +1 -1
- data/lib/virtus/attribute/default_value/from_clonable.rb +1 -6
- data/lib/virtus/attribute/default_value/from_symbol.rb +3 -3
- data/lib/virtus/attribute/embedded_value.rb +37 -28
- data/lib/virtus/attribute/hash.rb +69 -71
- data/lib/virtus/attribute/lazy_default.rb +18 -0
- data/lib/virtus/attribute/strict.rb +16 -0
- data/lib/virtus/attribute_set.rb +81 -9
- data/lib/virtus/class_inclusions.rb +24 -17
- data/lib/virtus/class_methods.rb +13 -31
- data/lib/virtus/configuration.rb +77 -0
- data/lib/virtus/const_missing_extensions.rb +16 -0
- data/lib/virtus/extensions.rb +86 -61
- data/lib/virtus/instance_methods.rb +107 -128
- data/lib/virtus/model.rb +68 -0
- data/lib/virtus/module_builder.rb +184 -0
- data/lib/virtus/module_extensions.rb +27 -15
- data/lib/virtus/support/equalizer.rb +2 -3
- data/lib/virtus/support/type_lookup.rb +1 -1
- data/lib/virtus/value_object.rb +24 -31
- data/lib/virtus/version.rb +1 -1
- data/spec/integration/building_module_spec.rb +68 -0
- data/spec/integration/custom_attributes_spec.rb +8 -15
- data/spec/integration/custom_collection_attributes_spec.rb +101 -0
- data/spec/integration/default_values_spec.rb +9 -2
- data/spec/integration/defining_attributes_spec.rb +2 -2
- data/spec/integration/using_modules_spec.rb +5 -3
- data/spec/shared/freeze_method_behavior.rb +2 -2
- data/spec/shared/options_class_method.rb +1 -1
- data/spec/spec_helper.rb +25 -5
- data/spec/unit/virtus/attribute/boolean/value_coerced_predicate_spec.rb +25 -0
- data/spec/unit/virtus/attribute/class_methods/build_spec.rb +115 -22
- data/spec/unit/virtus/attribute/class_methods/coerce_spec.rb +32 -0
- data/spec/unit/virtus/attribute/coerce_spec.rb +38 -21
- data/spec/unit/virtus/attribute/coercible_predicate_spec.rb +20 -0
- data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +84 -0
- data/spec/unit/virtus/attribute/collection/coerce_spec.rb +37 -24
- data/spec/unit/virtus/attribute/custom_collection_spec.rb +23 -0
- data/spec/unit/virtus/attribute/embedded_value/class_methods/build_spec.rb +37 -0
- data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +46 -10
- data/spec/unit/virtus/attribute/get_spec.rb +15 -63
- data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +80 -0
- data/spec/unit/virtus/attribute/hash/coerce_spec.rb +75 -13
- data/spec/unit/virtus/attribute/lazy_predicate_spec.rb +20 -0
- data/spec/unit/virtus/attribute/set_default_value_spec.rb +74 -0
- data/spec/unit/virtus/attribute/set_spec.rb +16 -36
- data/spec/unit/virtus/attribute/value_coerced_predicate_spec.rb +19 -0
- data/spec/unit/virtus/attribute_set/append_spec.rb +3 -5
- data/spec/unit/virtus/attribute_set/define_reader_method_spec.rb +1 -1
- data/spec/unit/virtus/attribute_set/define_writer_method_spec.rb +1 -1
- data/spec/unit/virtus/attribute_set/each_spec.rb +3 -3
- data/spec/unit/virtus/attribute_set/element_reference_spec.rb +1 -1
- data/spec/unit/virtus/attribute_set/element_set_spec.rb +4 -4
- data/spec/unit/virtus/attribute_set/merge_spec.rb +10 -16
- data/spec/unit/virtus/attribute_set/reset_spec.rb +6 -10
- data/spec/unit/virtus/attribute_spec.rb +222 -0
- data/spec/unit/virtus/attributes_reader_spec.rb +41 -0
- data/spec/unit/virtus/attributes_writer_spec.rb +51 -0
- data/spec/unit/virtus/class_methods/new_spec.rb +39 -0
- data/spec/unit/virtus/config_spec.rb +13 -0
- data/spec/unit/virtus/element_reader_spec.rb +21 -0
- data/spec/unit/virtus/element_writer_spec.rb +19 -0
- data/spec/unit/virtus/freeze_spec.rb +21 -0
- data/spec/unit/virtus/model_spec.rb +134 -0
- data/spec/unit/virtus/module_spec.rb +76 -0
- data/spec/unit/virtus/set_default_attributes_spec.rb +25 -0
- data/spec/unit/virtus/value_object_spec.rb +105 -0
- data/virtus.gemspec +4 -2
- metadata +82 -191
- data/.rvmrc +0 -1
- data/TODO +0 -1
- data/config/roodi.yml +0 -17
- data/lib/virtus/attribute/array.rb +0 -24
- data/lib/virtus/attribute/class.rb +0 -21
- data/lib/virtus/attribute/date.rb +0 -34
- data/lib/virtus/attribute/date_time.rb +0 -36
- data/lib/virtus/attribute/decimal.rb +0 -21
- data/lib/virtus/attribute/embedded_value/from_open_struct.rb +0 -19
- data/lib/virtus/attribute/embedded_value/from_struct.rb +0 -19
- data/lib/virtus/attribute/float.rb +0 -30
- data/lib/virtus/attribute/integer.rb +0 -27
- data/lib/virtus/attribute/numeric.rb +0 -11
- data/lib/virtus/attribute/object.rb +0 -11
- data/lib/virtus/attribute/set.rb +0 -24
- data/lib/virtus/attribute/string.rb +0 -24
- data/lib/virtus/attribute/symbol.rb +0 -21
- data/lib/virtus/attribute/time.rb +0 -36
- data/lib/virtus/coercion.rb +0 -32
- data/lib/virtus/coercion/array.rb +0 -23
- data/lib/virtus/coercion/date.rb +0 -26
- data/lib/virtus/coercion/date_time.rb +0 -26
- data/lib/virtus/coercion/decimal.rb +0 -40
- data/lib/virtus/coercion/false_class.rb +0 -24
- data/lib/virtus/coercion/float.rb +0 -39
- data/lib/virtus/coercion/hash.rb +0 -71
- data/lib/virtus/coercion/integer.rb +0 -83
- data/lib/virtus/coercion/numeric.rb +0 -66
- data/lib/virtus/coercion/object.rb +0 -125
- data/lib/virtus/coercion/string.rb +0 -218
- data/lib/virtus/coercion/symbol.rb +0 -24
- data/lib/virtus/coercion/time.rb +0 -40
- data/lib/virtus/coercion/time_coercions.rb +0 -86
- data/lib/virtus/coercion/true_class.rb +0 -24
- data/spec/unit/virtus/attribute/array/coerce_spec.rb +0 -13
- data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +0 -85
- data/spec/unit/virtus/attribute/boolean/define_reader_method_spec.rb +0 -15
- data/spec/unit/virtus/attribute/boolean/value_coerced_spec.rb +0 -97
- data/spec/unit/virtus/attribute/boolean_spec.rb +0 -19
- data/spec/unit/virtus/attribute/class/coerce_spec.rb +0 -13
- data/spec/unit/virtus/attribute/class_methods/accessor_spec.rb +0 -12
- data/spec/unit/virtus/attribute/class_methods/coercion_method_spec.rb +0 -9
- data/spec/unit/virtus/attribute/class_methods/default_spec.rb +0 -9
- data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +0 -117
- data/spec/unit/virtus/attribute/class_methods/merge_options_spec.rb +0 -11
- data/spec/unit/virtus/attribute/class_methods/primitive_spec.rb +0 -9
- data/spec/unit/virtus/attribute/class_methods/reader_spec.rb +0 -9
- data/spec/unit/virtus/attribute/class_methods/writer_spec.rb +0 -9
- data/spec/unit/virtus/attribute/coercion_method_spec.rb +0 -12
- data/spec/unit/virtus/attribute/collection/class_methods/merge_options_spec.rb +0 -40
- data/spec/unit/virtus/attribute/collection/coerce_and_append_member_spec.rb +0 -16
- data/spec/unit/virtus/attribute/collection/member_coercion/coerce_and_append_member_spec.rb +0 -18
- data/spec/unit/virtus/attribute/collection/member_type_spec.rb +0 -17
- data/spec/unit/virtus/attribute/collection/new_collection_spec.rb +0 -9
- data/spec/unit/virtus/attribute/date/coerce_spec.rb +0 -47
- data/spec/unit/virtus/attribute/date/value_coerced_spec.rb +0 -46
- data/spec/unit/virtus/attribute/date_time/coerce_spec.rb +0 -80
- data/spec/unit/virtus/attribute/decimal/coerce_spec.rb +0 -123
- data/spec/unit/virtus/attribute/default_spec.rb +0 -28
- data/spec/unit/virtus/attribute/default_value/call_spec.rb +0 -21
- data/spec/unit/virtus/attribute/default_value/class_methods/build_spec.rb +0 -23
- data/spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb +0 -21
- data/spec/unit/virtus/attribute/default_value/from_callable/call_spec.rb +0 -19
- data/spec/unit/virtus/attribute/default_value/from_callable/class_methods/handle_spec.rb +0 -17
- data/spec/unit/virtus/attribute/default_value/from_clonable/call_spec.rb +0 -20
- data/spec/unit/virtus/attribute/default_value/from_clonable/class_methods/handle_spec.rb +0 -19
- data/spec/unit/virtus/attribute/default_value/from_symbol/call_spec.rb +0 -17
- data/spec/unit/virtus/attribute/default_value/from_symbol/class_methods/handle_spec.rb +0 -17
- data/spec/unit/virtus/attribute/default_value/value_spec.rb +0 -10
- data/spec/unit/virtus/attribute/define_accessor_methods_spec.rb +0 -26
- data/spec/unit/virtus/attribute/define_reader_method_spec.rb +0 -24
- data/spec/unit/virtus/attribute/define_writer_method_spec.rb +0 -24
- data/spec/unit/virtus/attribute/embedded_value/class_methods/determine_type_spec.rb +0 -23
- data/spec/unit/virtus/attribute/embedded_value/class_methods/merge_options_spec.rb +0 -17
- data/spec/unit/virtus/attribute/embedded_value/from_open_struct/coerce_spec.rb +0 -34
- data/spec/unit/virtus/attribute/embedded_value/from_struct/coerce_spec.rb +0 -34
- data/spec/unit/virtus/attribute/float/coerce_spec.rb +0 -123
- data/spec/unit/virtus/attribute/hash/class_methods/merge_options_spec.rb +0 -33
- data/spec/unit/virtus/attribute/hash/key_type_spec.rb +0 -10
- data/spec/unit/virtus/attribute/hash/value_type_spec.rb +0 -10
- data/spec/unit/virtus/attribute/inspect_spec.rb +0 -27
- data/spec/unit/virtus/attribute/integer/coerce_spec.rb +0 -117
- data/spec/unit/virtus/attribute/name_spec.rb +0 -12
- data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +0 -15
- data/spec/unit/virtus/attribute/numeric/class_methods/max_spec.rb +0 -9
- data/spec/unit/virtus/attribute/numeric/class_methods/min_spec.rb +0 -9
- data/spec/unit/virtus/attribute/options_spec.rb +0 -14
- data/spec/unit/virtus/attribute/public_reader_spec.rb +0 -24
- data/spec/unit/virtus/attribute/public_writer_spec.rb +0 -24
- data/spec/unit/virtus/attribute/set/coerce_spec.rb +0 -13
- data/spec/unit/virtus/attribute/string/coerce_spec.rb +0 -11
- data/spec/unit/virtus/attribute/symbol/coerce_spec.rb +0 -13
- data/spec/unit/virtus/attribute/time/coerce_spec.rb +0 -67
- data/spec/unit/virtus/attribute/value_coerced_spec.rb +0 -19
- data/spec/unit/virtus/class_methods/attribute_set_spec.rb +0 -9
- data/spec/unit/virtus/class_methods/attribute_spec.rb +0 -30
- data/spec/unit/virtus/class_methods/attributes_spec.rb +0 -22
- data/spec/unit/virtus/class_methods/const_missing_spec.rb +0 -27
- data/spec/unit/virtus/class_methods/inherited_spec.rb +0 -21
- data/spec/unit/virtus/coercion/array/class_methods/to_set_spec.rb +0 -12
- data/spec/unit/virtus/coercion/class_methods/element_reference_spec.rb +0 -17
- data/spec/unit/virtus/coercion/class_methods/primitive_spec.rb +0 -13
- data/spec/unit/virtus/coercion/date/class_methods/to_date_spec.rb +0 -10
- data/spec/unit/virtus/coercion/date/class_methods/to_datetime_spec.rb +0 -30
- data/spec/unit/virtus/coercion/date/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/date/class_methods/to_time_spec.rb +0 -12
- data/spec/unit/virtus/coercion/date_time/class_methods/to_date_spec.rb +0 -30
- data/spec/unit/virtus/coercion/date_time/class_methods/to_datetime_spec.rb +0 -10
- data/spec/unit/virtus/coercion/date_time/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/date_time/class_methods/to_time_spec.rb +0 -30
- data/spec/unit/virtus/coercion/decimal/class_methods/to_decimal_spec.rb +0 -9
- data/spec/unit/virtus/coercion/decimal/class_methods/to_float_spec.rb +0 -12
- data/spec/unit/virtus/coercion/decimal/class_methods/to_integer_spec.rb +0 -12
- data/spec/unit/virtus/coercion/decimal/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/false_class/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/float/class_methods/to_decimal_spec.rb +0 -12
- data/spec/unit/virtus/coercion/float/class_methods/to_float_spec.rb +0 -9
- data/spec/unit/virtus/coercion/float/class_methods/to_integer_spec.rb +0 -12
- data/spec/unit/virtus/coercion/float/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/hash/class_methods/to_date_spec.rb +0 -38
- data/spec/unit/virtus/coercion/hash/class_methods/to_datetime_spec.rb +0 -38
- data/spec/unit/virtus/coercion/hash/class_methods/to_time_spec.rb +0 -38
- data/spec/unit/virtus/coercion/integer/class_methods/to_boolean_spec.rb +0 -25
- data/spec/unit/virtus/coercion/integer/class_methods/to_decimal_spec.rb +0 -12
- data/spec/unit/virtus/coercion/integer/class_methods/to_float_spec.rb +0 -12
- data/spec/unit/virtus/coercion/integer/class_methods/to_integer_spec.rb +0 -9
- data/spec/unit/virtus/coercion/integer/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/numeric/class_methods/to_decimal_spec.rb +0 -10
- data/spec/unit/virtus/coercion/numeric/class_methods/to_float_spec.rb +0 -10
- data/spec/unit/virtus/coercion/numeric/class_methods/to_integer_spec.rb +0 -10
- data/spec/unit/virtus/coercion/numeric/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb +0 -33
- data/spec/unit/virtus/coercion/object/class_methods/to_array_spec.rb +0 -51
- data/spec/unit/virtus/coercion/object/class_methods/to_hash_spec.rb +0 -22
- data/spec/unit/virtus/coercion/object/class_methods/to_integer_spec.rb +0 -22
- data/spec/unit/virtus/coercion/object/class_methods/to_string_spec.rb +0 -22
- data/spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb +0 -29
- data/spec/unit/virtus/coercion/string/class_methods/to_constant_spec.rb +0 -49
- data/spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb +0 -23
- data/spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb +0 -50
- data/spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb +0 -47
- data/spec/unit/virtus/coercion/string/class_methods/to_float_spec.rb +0 -57
- data/spec/unit/virtus/coercion/string/class_methods/to_integer_spec.rb +0 -68
- data/spec/unit/virtus/coercion/string/class_methods/to_symbol_spec.rb +0 -9
- data/spec/unit/virtus/coercion/string/class_methods/to_time_spec.rb +0 -50
- data/spec/unit/virtus/coercion/symbol/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/coercion/time/class_methods/to_integer_spec.rb +0 -10
- data/spec/unit/virtus/coercion/time/class_methods/to_time_spec.rb +0 -10
- data/spec/unit/virtus/coercion/time_coercions/to_date_spec.rb +0 -33
- data/spec/unit/virtus/coercion/time_coercions/to_datetime_spec.rb +0 -33
- data/spec/unit/virtus/coercion/time_coercions/to_string_spec.rb +0 -18
- data/spec/unit/virtus/coercion/time_coercions/to_time_spec.rb +0 -33
- data/spec/unit/virtus/coercion/true_class/class_methods/to_string_spec.rb +0 -12
- data/spec/unit/virtus/equalizer/append_spec.rb +0 -82
- data/spec/unit/virtus/equalizer/class_method/new_spec.rb +0 -111
- data/spec/unit/virtus/equalizer/methods/eql_spec.rb +0 -47
- data/spec/unit/virtus/equalizer/methods/equal_value_spec.rb +0 -57
- data/spec/unit/virtus/extensions/allowed_writer_methods_spec.rb +0 -25
- data/spec/unit/virtus/extensions/attribute_spec.rb +0 -26
- data/spec/unit/virtus/instance_methods/attributes_spec.rb +0 -140
- data/spec/unit/virtus/instance_methods/element_reference_spec.rb +0 -24
- data/spec/unit/virtus/instance_methods/element_set_spec.rb +0 -28
- data/spec/unit/virtus/instance_methods/freeze_spec.rb +0 -64
- data/spec/unit/virtus/instance_methods/initialize_spec.rb +0 -48
- data/spec/unit/virtus/instance_methods/to_hash_spec.rb +0 -23
- data/spec/unit/virtus/module_extensions/attribute_spec.rb +0 -31
- data/spec/unit/virtus/options/accept_options_spec.rb +0 -37
- data/spec/unit/virtus/options/accepted_options_spec.rb +0 -21
- data/spec/unit/virtus/options/options_spec.rb +0 -34
- data/spec/unit/virtus/type_lookup/class_methods/extended_spec.rb +0 -9
- data/spec/unit/virtus/type_lookup/determine_type_spec.rb +0 -81
- data/spec/unit/virtus/type_lookup/primitive_spec.rb +0 -9
- data/spec/unit/virtus/value_object/class_methods/allowed_writer_methods_spec.rb +0 -15
- data/spec/unit/virtus/value_object/class_methods/attribute_spec.rb +0 -50
- data/spec/unit/virtus/value_object/class_methods/equalizer_spec.rb +0 -24
- data/spec/unit/virtus/value_object/initialize_spec.rb +0 -19
- data/spec/unit/virtus/value_object/instance_methods/clone_spec.rb +0 -21
- data/spec/unit/virtus/value_object/instance_methods/with_spec.rb +0 -31
@@ -0,0 +1,91 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
# Accessor extension provides methods to read and write attributes
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# attribute = Virtus::Attribute.build(String, :name => :email)
|
9
|
+
# model = Class.new { attr_reader :email }
|
10
|
+
# object = model.new
|
11
|
+
#
|
12
|
+
# attribute.set(object, 'jane@doe.com')
|
13
|
+
# attribute.get(object) # => 'jane@doe.com'
|
14
|
+
#
|
15
|
+
module Accessor
|
16
|
+
|
17
|
+
# Return name of this accessor attribute
|
18
|
+
#
|
19
|
+
# @return [Symbol]
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
# Return instance_variable_name used by this accessor
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
attr_reader :instance_variable_name
|
28
|
+
|
29
|
+
# Return value of the attribute
|
30
|
+
#
|
31
|
+
# @param [Object] instance
|
32
|
+
#
|
33
|
+
# @return [Object]
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def get(instance)
|
37
|
+
instance.instance_variable_get(instance_variable_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set value of the attribute
|
41
|
+
#
|
42
|
+
# @param [Object] instance
|
43
|
+
# @param [Object] value
|
44
|
+
#
|
45
|
+
# @return [Object] value that was set
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def set(instance, value)
|
49
|
+
instance.instance_variable_set(instance_variable_name, value)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Set default value
|
53
|
+
#
|
54
|
+
# @param [Object] instance
|
55
|
+
#
|
56
|
+
# @return [Object] value that was set
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
def set_default_value(instance)
|
60
|
+
set(instance, default_value.call(instance, self))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a Boolean indicating whether the reader method is public
|
64
|
+
#
|
65
|
+
# @return [Boolean]
|
66
|
+
#
|
67
|
+
# @api private
|
68
|
+
def public_reader?
|
69
|
+
options[:reader] == :public
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns a Boolean indicating whether the writer method is public
|
73
|
+
#
|
74
|
+
# @return [Boolean]
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
def public_writer?
|
78
|
+
options[:writer] == :public
|
79
|
+
end
|
80
|
+
|
81
|
+
# @api private
|
82
|
+
def finalize
|
83
|
+
@name = options.fetch(:name).to_sym
|
84
|
+
@instance_variable_name = "@#{@name}"
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
end # Accessor
|
89
|
+
|
90
|
+
end # Attribute
|
91
|
+
end # Virtus
|
@@ -14,9 +14,13 @@ module Virtus
|
|
14
14
|
# post = Post.new(:published => false)
|
15
15
|
# post.published? # => false
|
16
16
|
#
|
17
|
-
class Boolean <
|
18
|
-
primitive
|
19
|
-
|
17
|
+
class Boolean < Attribute
|
18
|
+
primitive TrueClass
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def self.build_type(*)
|
22
|
+
Axiom::Types::Boolean
|
23
|
+
end
|
20
24
|
|
21
25
|
# Returns if the given value is either true or false
|
22
26
|
#
|
@@ -31,20 +35,19 @@ module Virtus
|
|
31
35
|
#
|
32
36
|
# @api public
|
33
37
|
def value_coerced?(value)
|
34
|
-
value.equal?(true)
|
38
|
+
value.equal?(true) || value.equal?(false)
|
35
39
|
end
|
36
40
|
|
37
41
|
# Creates an attribute reader method as a query
|
38
42
|
#
|
39
43
|
# @param [Module] mod
|
40
44
|
#
|
41
|
-
# @return [
|
45
|
+
# @return [undefined]
|
42
46
|
#
|
43
47
|
# @api private
|
44
|
-
def
|
48
|
+
def define_accessor_methods(attribute_set)
|
45
49
|
super
|
46
|
-
|
47
|
-
self
|
50
|
+
attribute_set.define_reader_method(self, "#{name}?", options[:reader])
|
48
51
|
end
|
49
52
|
|
50
53
|
end # class Boolean
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
# TODO: this is a huge class and it might be a good idea to split it into
|
5
|
+
# smaller chunks. We probably need some option parser with dedicated
|
6
|
+
# sub-classes per attribute type (different one for Hash, Collection, EV)
|
7
|
+
#
|
8
|
+
# @private
|
9
|
+
class Builder
|
10
|
+
attr_reader :attribute
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def self.call(*args)
|
14
|
+
new(*args).attribute
|
15
|
+
end
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
def self.determine_type(klass, default = nil)
|
19
|
+
type = Attribute.determine_type(klass)
|
20
|
+
|
21
|
+
if klass.is_a?(Class)
|
22
|
+
type ||=
|
23
|
+
if klass < Axiom::Types::Type
|
24
|
+
determine_type(klass.primitive)
|
25
|
+
elsif EmbeddedValue.handles?(klass)
|
26
|
+
EmbeddedValue.determine_type(klass)
|
27
|
+
elsif klass < Enumerable
|
28
|
+
Collection
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
type || default
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def initialize(type, options)
|
37
|
+
initialize_primitive(type)
|
38
|
+
initialize_class
|
39
|
+
initialize_type(:type => type, :primitive => @primitive)
|
40
|
+
initialize_options(options)
|
41
|
+
initialize_default_value
|
42
|
+
initialize_coercer
|
43
|
+
initialize_attribute
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
def initialize_attribute
|
50
|
+
@attribute = @klass.new(@type, @options) do |attribute|
|
51
|
+
attribute.extend(Accessor) if @options[:name]
|
52
|
+
attribute.extend(Coercible) if @options[:coerce]
|
53
|
+
attribute.extend(Strict) if @options[:strict]
|
54
|
+
attribute.extend(LazyDefault) if @options[:lazy]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def initialize_default_value
|
60
|
+
@options.update(:default_value => DefaultValue.build(@options[:default]))
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
def initialize_coercer
|
65
|
+
@options.update(:coercer => @options.fetch(:coercer) { build_coercer })
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
def initialize_primitive(type)
|
70
|
+
@primitive =
|
71
|
+
if type.instance_of?(String) || type.instance_of?(Symbol)
|
72
|
+
begin
|
73
|
+
Object.const_get(type)
|
74
|
+
rescue
|
75
|
+
type
|
76
|
+
end
|
77
|
+
elsif not type.is_a?(Class)
|
78
|
+
type.class
|
79
|
+
else
|
80
|
+
type
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
def initialize_class
|
86
|
+
@klass = self.class.determine_type(@primitive, Attribute)
|
87
|
+
end
|
88
|
+
|
89
|
+
# @api private
|
90
|
+
def initialize_type(options)
|
91
|
+
@type = @klass.build_type(options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @api private
|
95
|
+
def initialize_options(options)
|
96
|
+
@options = @klass.options.merge(:coerce => Virtus.coerce).update(options)
|
97
|
+
@klass.merge_options!(@type, @options)
|
98
|
+
determine_visibility!
|
99
|
+
end
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
def determine_visibility!
|
103
|
+
default_accessor = @options.fetch(:accessor)
|
104
|
+
reader_visibility = @options.fetch(:reader, default_accessor)
|
105
|
+
writer_visibility = @options.fetch(:writer, default_accessor)
|
106
|
+
@options.update(:reader => reader_visibility, :writer => writer_visibility)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api private
|
110
|
+
def build_coercer
|
111
|
+
Coercer.new(
|
112
|
+
@options.fetch(:configured_coercer) { Virtus.coercer },
|
113
|
+
@type.coercion_method
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
end # class Builder
|
118
|
+
|
119
|
+
end # class Attribute
|
120
|
+
end # module Virtus
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
# Coercer accessor wrapper
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
class Coercer
|
8
|
+
attr_reader :method
|
9
|
+
|
10
|
+
# Initialize a new coercer object
|
11
|
+
#
|
12
|
+
# @param [Object] coercers accessor
|
13
|
+
# @param [Symbol] coercion method
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
def initialize(coercers, method)
|
19
|
+
@coercers = coercers
|
20
|
+
@method = method
|
21
|
+
end
|
22
|
+
|
23
|
+
# Coerce given value
|
24
|
+
#
|
25
|
+
# @return [Object]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
def call(value)
|
29
|
+
self[value.class].public_send(@method, value)
|
30
|
+
rescue ::Coercible::UnsupportedCoercion
|
31
|
+
value
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api public
|
35
|
+
def success?(primitive, value)
|
36
|
+
self[primitive].coerced?(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return coercer object for the given type
|
40
|
+
#
|
41
|
+
# @return [Object]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
def [](type)
|
45
|
+
@coercers[type]
|
46
|
+
end
|
47
|
+
|
48
|
+
end # class Coercer
|
49
|
+
|
50
|
+
end # class Attribute
|
51
|
+
end # module Virtus
|
@@ -6,111 +6,65 @@ module Virtus
|
|
6
6
|
# Handles coercing members to the designated member type.
|
7
7
|
#
|
8
8
|
# @abstract
|
9
|
-
class Collection <
|
9
|
+
class Collection < Attribute
|
10
|
+
default Proc.new { |_, attribute| attribute.type.primitive.new }
|
10
11
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# class Post
|
16
|
-
# include Virtus
|
17
|
-
#
|
18
|
-
# attribute :tags, Array[String]
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# Post.attributes[:tags].member_type # => Virtus::Attribute::String
|
22
|
-
#
|
23
|
-
# @return [Virtus::Attribute]
|
24
|
-
#
|
25
|
-
# @api public
|
26
|
-
attr_reader :member_type
|
12
|
+
# FIXME: temporary hack, remove when Axiom::Type works with EV as member_type
|
13
|
+
Type = Struct.new(:primitive, :member_type) do
|
14
|
+
def self.infer(type, primitive)
|
15
|
+
return type if type.is_a?(Class) && type < Axiom::Types::Type
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
options
|
40
|
-
elsif type.size > 1
|
41
|
-
raise NotImplementedError, "build SumType from list of types (#{type.inspect})"
|
42
|
-
else
|
43
|
-
options.merge(:member_type => type.first)
|
17
|
+
klass = Axiom::Types.infer(type)
|
18
|
+
member = infer_member_type(type) || Object
|
19
|
+
|
20
|
+
if EmbeddedValue.handles?(member)
|
21
|
+
Type.new(primitive, member)
|
22
|
+
else
|
23
|
+
klass.new {
|
24
|
+
primitive primitive
|
25
|
+
member_type Axiom::Types.infer(member)
|
26
|
+
}
|
27
|
+
end
|
44
28
|
end
|
45
|
-
end
|
46
29
|
|
47
|
-
|
48
|
-
|
49
|
-
# @api private
|
50
|
-
def initialize(*)
|
51
|
-
super
|
52
|
-
@member_type = @options.fetch(:member_type, Virtus::Attribute::Object)
|
53
|
-
@member_type_instance = Attribute.build(@name, @member_type)
|
54
|
-
end
|
30
|
+
def self.infer_member_type(type)
|
31
|
+
return unless type.respond_to?(:count)
|
55
32
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
return coerced unless coerced.respond_to?(:inject)
|
66
|
-
coerced.inject(new_collection) do |*args|
|
67
|
-
coerce_and_append_member(*args)
|
33
|
+
if type.count > 1
|
34
|
+
raise NotImplementedError, "build SumType from list of types (#{type})"
|
35
|
+
else
|
36
|
+
type.first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def coercion_method
|
41
|
+
:to_array
|
68
42
|
end
|
69
43
|
end
|
70
44
|
|
71
|
-
# Return an instance of the collection
|
72
|
-
#
|
73
|
-
# @return [Enumerable]
|
74
|
-
#
|
75
45
|
# @api private
|
76
|
-
def
|
77
|
-
|
46
|
+
def self.build_type(options)
|
47
|
+
Type.infer(options.fetch(:type), options.fetch(:primitive))
|
78
48
|
end
|
79
49
|
|
80
|
-
# Coerce entry and add it to the collection
|
81
|
-
#
|
82
|
-
# @abstract
|
83
|
-
#
|
84
|
-
# @raise NotImplementedError
|
85
|
-
#
|
86
|
-
# @return [undefined]
|
87
|
-
#
|
88
50
|
# @api private
|
89
|
-
def
|
90
|
-
|
91
|
-
|
51
|
+
def self.merge_options!(type, options)
|
52
|
+
unless options.key?(:member_type)
|
53
|
+
options[:member_type] = Attribute.build(type.member_type)
|
54
|
+
end
|
92
55
|
end
|
93
56
|
|
94
|
-
#
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
#
|
99
|
-
# @param [Array, Set] collection
|
100
|
-
# target collection to which the coerced member should be appended
|
101
|
-
#
|
102
|
-
# @param [Object] entry
|
103
|
-
# the member that should be coerced and appended
|
104
|
-
#
|
105
|
-
# @return [Array, Set]
|
106
|
-
# collection with the coerced member appended to it
|
107
|
-
#
|
108
|
-
# @api private
|
109
|
-
def coerce_and_append_member(collection, entry)
|
110
|
-
collection << @member_type_instance.coerce(entry)
|
57
|
+
# @api public
|
58
|
+
def coerce(*)
|
59
|
+
super.each_with_object(primitive.new) do |entry, collection|
|
60
|
+
collection << member_type.coerce(entry)
|
111
61
|
end
|
112
|
-
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def member_type
|
65
|
+
@options[:member_type]
|
66
|
+
end
|
113
67
|
|
114
|
-
end # class
|
68
|
+
end # class Collection
|
115
69
|
end # class Attribute
|
116
70
|
end # module Virtus
|