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
data/lib/virtus/version.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'I can create a Virtus module' do
|
4
|
+
before do
|
5
|
+
module Examples
|
6
|
+
NoncoercingModule = Virtus.model { |config|
|
7
|
+
config.coerce = false
|
8
|
+
}
|
9
|
+
|
10
|
+
CoercingModule = Virtus.model { |config|
|
11
|
+
config.coerce = true
|
12
|
+
|
13
|
+
config.coercer do |coercer|
|
14
|
+
coercer.string.boolean_map = { 'yup' => true, 'nope' => false }
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
StrictModule = Virtus.model { |config|
|
19
|
+
config.strict = true
|
20
|
+
}
|
21
|
+
|
22
|
+
class NoncoercedUser
|
23
|
+
include NoncoercingModule
|
24
|
+
|
25
|
+
attribute :name, String
|
26
|
+
attribute :happy, String
|
27
|
+
end
|
28
|
+
|
29
|
+
class CoercedUser
|
30
|
+
include CoercingModule
|
31
|
+
|
32
|
+
attribute :name, String
|
33
|
+
attribute :happy, Boolean
|
34
|
+
end
|
35
|
+
|
36
|
+
class StrictModel
|
37
|
+
include StrictModule
|
38
|
+
|
39
|
+
attribute :stuff, Hash
|
40
|
+
attribute :happy, Boolean, :strict => false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
specify 'including a custom module with coercion disabled' do
|
46
|
+
user = Examples::NoncoercedUser.new(:name => :Giorgio, :happy => 'yes')
|
47
|
+
|
48
|
+
expect(user.name).to be(:Giorgio)
|
49
|
+
expect(user.happy).to eql('yes')
|
50
|
+
end
|
51
|
+
|
52
|
+
specify 'including a custom module with coercion enabled' do
|
53
|
+
user = Examples::CoercedUser.new(:name => 'Paul', :happy => 'nope')
|
54
|
+
|
55
|
+
expect(user.name).to eql('Paul')
|
56
|
+
expect(user.happy).to be(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
specify 'including a custom module with strict enabled' do
|
60
|
+
model = Examples::StrictModel.new
|
61
|
+
|
62
|
+
expect { model.stuff = 'foo' }.to raise_error(ArgumentError)
|
63
|
+
|
64
|
+
model.happy = 'foo'
|
65
|
+
|
66
|
+
expect(model.happy).to eql('foo')
|
67
|
+
end
|
68
|
+
end
|
@@ -2,24 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'custom attributes' do
|
4
4
|
|
5
|
-
module Virtus
|
6
|
-
class Coercion
|
7
|
-
class String < Virtus::Coercion::Object
|
8
|
-
def self.to_upcase(value)
|
9
|
-
value.upcase
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
5
|
before do
|
16
6
|
module Examples
|
17
|
-
class
|
18
|
-
|
19
|
-
|
7
|
+
class NoisyString < Virtus::Attribute
|
8
|
+
lazy true
|
9
|
+
|
10
|
+
def coerce(input)
|
11
|
+
input.to_s.upcase
|
12
|
+
end
|
20
13
|
end
|
21
14
|
|
22
|
-
class RegularExpression < Virtus::Attribute
|
15
|
+
class RegularExpression < Virtus::Attribute
|
23
16
|
primitive Regexp
|
24
17
|
end
|
25
18
|
|
@@ -27,7 +20,7 @@ describe 'custom attributes' do
|
|
27
20
|
include Virtus
|
28
21
|
|
29
22
|
attribute :name, String
|
30
|
-
attribute :scream,
|
23
|
+
attribute :scream, NoisyString
|
31
24
|
attribute :expression, RegularExpression
|
32
25
|
end
|
33
26
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'custom collection attributes' do
|
4
|
+
let(:library) { Examples::Library.new }
|
5
|
+
let(:books) { library.books }
|
6
|
+
|
7
|
+
before do
|
8
|
+
module Examples end
|
9
|
+
Examples.const_set 'BookCollection', book_collection_class
|
10
|
+
|
11
|
+
module Examples
|
12
|
+
class Book
|
13
|
+
include Virtus
|
14
|
+
|
15
|
+
attribute :title, String
|
16
|
+
end
|
17
|
+
|
18
|
+
class BookCollectionAttribute < Virtus::Attribute::Collection
|
19
|
+
primitive BookCollection
|
20
|
+
end
|
21
|
+
|
22
|
+
class Library
|
23
|
+
include Virtus
|
24
|
+
|
25
|
+
attribute :books, BookCollection[Book]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
[:BookCollectionAttribute, :BookCollection, :Book, :Library].each do |const|
|
32
|
+
Examples.send(:remove_const, const)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
shared_examples_for 'a collection' do
|
37
|
+
it 'can be used as Virtus attributes' do
|
38
|
+
attribute = Examples::Library.attribute_set[:books]
|
39
|
+
attribute.should be_kind_of(Examples::BookCollectionAttribute)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'defaults to an empty collection' do
|
43
|
+
books_should_be_an_empty_collection
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'coerces nil' do
|
47
|
+
library.books = nil
|
48
|
+
books_should_be_an_empty_collection
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'coerces an empty array' do
|
52
|
+
library.books = []
|
53
|
+
books_should_be_an_empty_collection
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'coerces an array of attribute hashes' do
|
57
|
+
library.books = [{ :title => 'Foo' }]
|
58
|
+
books.should be_kind_of(Examples::BookCollection)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'coerces its members' do
|
62
|
+
library.books = [{ :title => 'Foo' }]
|
63
|
+
books.count.should == 1
|
64
|
+
books.first.should be_kind_of(Examples::Book)
|
65
|
+
end
|
66
|
+
|
67
|
+
def books_should_be_an_empty_collection
|
68
|
+
books.should be_kind_of(Examples::BookCollection)
|
69
|
+
books.count.should == 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with an array subclass' do
|
74
|
+
let(:book_collection_class) { Class.new(Array) }
|
75
|
+
|
76
|
+
it_behaves_like 'a collection'
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with an enumerable' do
|
80
|
+
require 'forwardable'
|
81
|
+
|
82
|
+
let(:book_collection_class) {
|
83
|
+
Class.new do
|
84
|
+
extend Forwardable
|
85
|
+
include Enumerable
|
86
|
+
|
87
|
+
def_delegators :@array, :each, :<<
|
88
|
+
|
89
|
+
def initialize(*args)
|
90
|
+
@array = Array[*args]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.[](*args)
|
94
|
+
new(*args)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
}
|
98
|
+
|
99
|
+
it_behaves_like 'a collection'
|
100
|
+
end
|
101
|
+
end
|
@@ -15,10 +15,10 @@ describe "default values" do
|
|
15
15
|
include Virtus
|
16
16
|
|
17
17
|
attribute :title, String
|
18
|
-
attribute :slug, String, :default => lambda { |post, attribute| post.title.downcase.gsub(' ', '-') }
|
18
|
+
attribute :slug, String, :default => lambda { |post, attribute| post.title.downcase.gsub(' ', '-') }, :lazy => true
|
19
19
|
attribute :view_count, Integer, :default => 0
|
20
20
|
attribute :published, Boolean, :default => false, :accessor => :private
|
21
|
-
attribute :editor_title, String, :default => :default_editor_title
|
21
|
+
attribute :editor_title, String, :default => :default_editor_title, :lazy => true
|
22
22
|
attribute :reference, String, :default => Reference.new
|
23
23
|
attribute :revisions, Array
|
24
24
|
attribute :index, Hash
|
@@ -52,6 +52,13 @@ describe "default values" do
|
|
52
52
|
subject.editor_title.should == 'UNPUBLISHED: Top Secret'
|
53
53
|
end
|
54
54
|
|
55
|
+
specify 'you can reset attribute to its default' do
|
56
|
+
subject.view_count = 10
|
57
|
+
expect do
|
58
|
+
subject.reset_attribute(:view_count)
|
59
|
+
end.to change { subject.view_count }.to(0)
|
60
|
+
end
|
61
|
+
|
55
62
|
context 'a ValueObject' do
|
56
63
|
it 'does not duplicate the ValueObject' do
|
57
64
|
page1 = Examples::Page.new
|
@@ -10,7 +10,7 @@ describe "virtus attribute definitions" do
|
|
10
10
|
attribute :name, String
|
11
11
|
attribute :age, Integer
|
12
12
|
attribute :doctor, Boolean
|
13
|
-
attribute :
|
13
|
+
attribute :salary, Decimal
|
14
14
|
end
|
15
15
|
|
16
16
|
class Manager < Person
|
@@ -39,7 +39,7 @@ describe "virtus attribute definitions" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
context 'with attributes' do
|
42
|
-
let(:attributes) { {:name => 'Jane', :age => 45, :doctor => true, :
|
42
|
+
let(:attributes) { {:name => 'Jane', :age => 45, :doctor => true, :salary => 4500} }
|
43
43
|
subject { Examples::Person.new(attributes) }
|
44
44
|
|
45
45
|
specify "#attributes returns the object's attributes as a hash" do
|
@@ -11,6 +11,7 @@ describe 'I can define attributes within a module' do
|
|
11
11
|
include Common
|
12
12
|
|
13
13
|
attribute :name, String
|
14
|
+
attribute :gamer, Boolean
|
14
15
|
end
|
15
16
|
|
16
17
|
module Age
|
@@ -32,10 +33,11 @@ describe 'I can define attributes within a module' do
|
|
32
33
|
end
|
33
34
|
|
34
35
|
specify 'including a module with attributes into a class' do
|
35
|
-
Examples::User.attribute_set[:name].should be_instance_of(Virtus::Attribute
|
36
|
+
Examples::User.attribute_set[:name].should be_instance_of(Virtus::Attribute)
|
37
|
+
Examples::User.attribute_set[:gamer].should be_instance_of(Virtus::Attribute::Boolean)
|
36
38
|
|
37
|
-
Examples::Admin.attribute_set[:name].should be_instance_of(Virtus::Attribute
|
38
|
-
Examples::Admin.attribute_set[:age].should be_instance_of(Virtus::Attribute
|
39
|
+
Examples::Admin.attribute_set[:name].should be_instance_of(Virtus::Attribute)
|
40
|
+
Examples::Admin.attribute_set[:age].should be_instance_of(Virtus::Attribute)
|
39
41
|
|
40
42
|
user = Examples::Admin.new(:name => 'Piotr', :age => 29)
|
41
43
|
user.name.should eql('Piotr')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
shared_examples_for 'a #freeze method' do
|
2
2
|
let(:sample_exception) do
|
3
3
|
begin
|
4
|
-
object.dup.freeze.instance_variable_set(:@foo
|
4
|
+
object.dup.freeze.instance_variable_set(:@foo, :bar)
|
5
5
|
rescue => exception
|
6
6
|
exception
|
7
7
|
end
|
@@ -26,7 +26,7 @@ shared_examples_for 'a #freeze method' do
|
|
26
26
|
it 'prevents future modifications' do
|
27
27
|
subject
|
28
28
|
expectation = raise_error(expected_exception_class,expected_exception_message)
|
29
|
-
expect { object.instance_variable_set(:@foo
|
29
|
+
expect { object.instance_variable_set(:@foo, :bar) }.to(expectation)
|
30
30
|
end
|
31
31
|
|
32
32
|
its(:frozen?) { should be(true) }
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,33 @@
|
|
1
|
+
if ENV['COVERAGE'] == 'true'
|
2
|
+
require 'simplecov'
|
3
|
+
require 'coveralls'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
Coveralls::SimpleCov::Formatter
|
8
|
+
]
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
command_name 'spec:unit'
|
12
|
+
add_filter 'config/'
|
13
|
+
add_filter 'spec'
|
14
|
+
add_filter '.bundle'
|
15
|
+
minimum_coverage 99
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
1
19
|
require 'rspec'
|
20
|
+
require 'bogus/rspec'
|
2
21
|
require 'virtus'
|
3
22
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
SimpleCov.start
|
23
|
+
module Virtus
|
24
|
+
def self.warn(*)
|
25
|
+
# shut up in tests
|
26
|
+
end
|
9
27
|
end
|
10
28
|
|
29
|
+
ENV['TZ'] = 'UTC'
|
30
|
+
|
11
31
|
# require spec support files and shared behavior
|
12
32
|
Dir[File.expand_path('../shared/**/*.rb', __FILE__)].each { |file| require file }
|
13
33
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Virtus::Attribute::Boolean, '#value_coerced?' do
|
4
|
+
subject { object.value_coerced?(input) }
|
5
|
+
|
6
|
+
let(:object) { described_class.build('Boolean') }
|
7
|
+
|
8
|
+
context 'when input is true' do
|
9
|
+
let(:input) { true }
|
10
|
+
|
11
|
+
it { should be(true) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when input is false' do
|
15
|
+
let(:input) { false }
|
16
|
+
|
17
|
+
it { should be(true) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when input is not coerced' do
|
21
|
+
let(:input) { 1 }
|
22
|
+
|
23
|
+
it { should be(false) }
|
24
|
+
end
|
25
|
+
end
|
@@ -1,47 +1,140 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Virtus::Attribute, '.build' do
|
4
|
-
|
5
|
-
|
6
|
-
let(:
|
4
|
+
subject { described_class.build(type, options.merge(:name => name)) }
|
5
|
+
|
6
|
+
let(:name) { :test }
|
7
|
+
let(:type) { String }
|
8
|
+
let(:options) { {} }
|
9
|
+
|
10
|
+
share_examples_for 'a valid attribute instance' do
|
11
|
+
it { should be_instance_of(Virtus::Attribute) }
|
12
|
+
|
13
|
+
it { should be_frozen }
|
14
|
+
end
|
7
15
|
|
8
16
|
context 'without options' do
|
9
|
-
|
17
|
+
it_behaves_like 'a valid attribute instance'
|
18
|
+
|
19
|
+
it { should be_coercible }
|
20
|
+
it { should be_public_reader }
|
21
|
+
it { should be_public_writer }
|
22
|
+
it { should_not be_lazy }
|
23
|
+
|
24
|
+
it 'sets up a coercer' do
|
25
|
+
expect(subject.options[:coerce]).to be(true)
|
26
|
+
expect(subject.coercer).to be_instance_of(Virtus::Attribute::Coercer)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when name is passed as a string' do
|
31
|
+
let(:name) { 'something' }
|
32
|
+
|
33
|
+
its(:name) { should be(:something) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when coercion is turned off in options' do
|
37
|
+
let(:options) { { :coerce => false } }
|
38
|
+
|
39
|
+
it_behaves_like 'a valid attribute instance'
|
40
|
+
|
41
|
+
it { should_not be_coercible }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when options specify reader visibility' do
|
45
|
+
let(:options) { { :reader => :private } }
|
46
|
+
|
47
|
+
it_behaves_like 'a valid attribute instance'
|
48
|
+
|
49
|
+
it { should_not be_public_reader }
|
50
|
+
it { should be_public_writer }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when options specify writer visibility' do
|
54
|
+
let(:options) { { :writer => :private } }
|
10
55
|
|
11
|
-
|
56
|
+
it_behaves_like 'a valid attribute instance'
|
12
57
|
|
13
|
-
|
58
|
+
it { should be_public_reader }
|
59
|
+
it { should_not be_public_writer }
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when options specify lazy accessor' do
|
63
|
+
let(:options) { { :lazy => true } }
|
64
|
+
|
65
|
+
it_behaves_like 'a valid attribute instance'
|
14
66
|
|
15
|
-
|
67
|
+
it { should be_lazy }
|
16
68
|
end
|
17
69
|
|
18
|
-
context '
|
19
|
-
|
70
|
+
context 'when options specify strict mode' do
|
71
|
+
let(:options) { { :strict => true } }
|
20
72
|
|
21
|
-
|
73
|
+
it_behaves_like 'a valid attribute instance'
|
74
|
+
|
75
|
+
it { should be_strict }
|
76
|
+
end
|
22
77
|
|
23
|
-
|
78
|
+
context 'when type is a string' do
|
79
|
+
let(:type) { 'Integer' }
|
24
80
|
|
25
|
-
|
81
|
+
it_behaves_like 'a valid attribute instance'
|
26
82
|
|
27
|
-
its(:
|
83
|
+
its(:type) { should be(Axiom::Types::Integer) }
|
28
84
|
end
|
29
85
|
|
30
|
-
context '
|
31
|
-
|
86
|
+
context 'when type is a symbol of an existing class constant' do
|
87
|
+
let(:type) { :String }
|
32
88
|
|
33
|
-
|
89
|
+
it_behaves_like 'a valid attribute instance'
|
34
90
|
|
35
|
-
its(:
|
91
|
+
its(:type) { should be(Axiom::Types::String) }
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when type is an axiom type' do
|
95
|
+
let(:type) { Axiom::Types::Integer }
|
96
|
+
|
97
|
+
it_behaves_like 'a valid attribute instance'
|
36
98
|
|
37
|
-
its(:
|
99
|
+
its(:type) { should be(type) }
|
38
100
|
end
|
39
101
|
|
40
|
-
context '
|
41
|
-
|
102
|
+
context 'when custom attribute class exists for a given primitive' do
|
103
|
+
let(:type) { Class.new }
|
104
|
+
let(:attribute) { Class.new(Virtus::Attribute) }
|
105
|
+
|
106
|
+
before do
|
107
|
+
attribute.primitive(type)
|
108
|
+
end
|
109
|
+
|
110
|
+
it { should be_instance_of(attribute) }
|
111
|
+
|
112
|
+
its(:type) { should be(Axiom::Types::Object) }
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when custom attribute class exists for a given array with member coercion defined' do
|
116
|
+
let(:type) { Class.new(Array)[String] }
|
117
|
+
let(:attribute) { Class.new(Virtus::Attribute) }
|
118
|
+
|
119
|
+
before do
|
120
|
+
attribute.primitive(type.class)
|
121
|
+
end
|
122
|
+
|
123
|
+
it { should be_instance_of(attribute) }
|
124
|
+
|
125
|
+
its(:type) { should be < Axiom::Types::Collection }
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when custom collection-like attribute class exists for a given enumerable primitive' do
|
129
|
+
let(:type) { Class.new { include Enumerable } }
|
130
|
+
let(:attribute) { Class.new(Virtus::Attribute::Collection) }
|
131
|
+
|
132
|
+
before do
|
133
|
+
attribute.primitive(type)
|
134
|
+
end
|
42
135
|
|
43
|
-
|
136
|
+
it { should be_instance_of(attribute) }
|
44
137
|
|
45
|
-
|
138
|
+
its(:type) { should be < Axiom::Types::Collection }
|
46
139
|
end
|
47
140
|
end
|