virtus 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/.gitignore +33 -7
  2. data/.travis.yml +4 -74
  3. data/Changelog.md +11 -2
  4. data/Gemfile +10 -9
  5. data/README.md +85 -1
  6. data/TODO +18 -0
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/roodi.yml +3 -3
  10. data/config/site.reek +8 -3
  11. data/lib/virtus.rb +5 -0
  12. data/lib/virtus/attribute.rb +137 -30
  13. data/lib/virtus/attribute/array.rb +17 -1
  14. data/lib/virtus/attribute/boolean.rb +8 -13
  15. data/lib/virtus/attribute/collection.rb +96 -0
  16. data/lib/virtus/attribute/default_value.rb +11 -7
  17. data/lib/virtus/attribute/embedded_value.rb +70 -0
  18. data/lib/virtus/attribute/set.rb +25 -0
  19. data/lib/virtus/attribute_set.rb +18 -16
  20. data/lib/virtus/attributes_accessor.rb +66 -0
  21. data/lib/virtus/class_methods.rb +50 -28
  22. data/lib/virtus/coercion/array.rb +23 -0
  23. data/lib/virtus/coercion/string.rb +10 -4
  24. data/lib/virtus/instance_methods.rb +38 -31
  25. data/lib/virtus/support/options.rb +6 -8
  26. data/lib/virtus/support/type_lookup.rb +4 -11
  27. data/lib/virtus/version.rb +1 -1
  28. data/spec/integration/collection_member_coercion_spec.rb +75 -0
  29. data/spec/integration/custom_attributes_spec.rb +49 -0
  30. data/spec/integration/default_values_spec.rb +32 -0
  31. data/spec/integration/defining_attributes_spec.rb +79 -0
  32. data/spec/integration/embedded_value_spec.rb +50 -0
  33. data/spec/integration/overriding_virtus_spec.rb +46 -0
  34. data/spec/integration/virtus/instance_level_attributes_spec.rb +23 -0
  35. data/spec/rcov.opts +1 -0
  36. data/spec/shared/constants_helpers.rb +9 -0
  37. data/spec/shared/options_class_method.rb +19 -0
  38. data/spec/spec_helper.rb +20 -7
  39. data/spec/unit/virtus/attribute/array/coerce_spec.rb +13 -0
  40. data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +85 -0
  41. data/spec/unit/virtus/attribute/boolean/define_reader_method_spec.rb +15 -0
  42. data/spec/unit/virtus/attribute/boolean/value_coerced_spec.rb +97 -0
  43. data/spec/unit/virtus/attribute/boolean_spec.rb +2 -81
  44. data/spec/unit/virtus/attribute/class/coerce_spec.rb +13 -0
  45. data/spec/unit/virtus/attribute/class_methods/accessor_spec.rb +12 -0
  46. data/spec/unit/virtus/attribute/class_methods/build_spec.rb +37 -0
  47. data/spec/unit/virtus/attribute/class_methods/coercion_method_spec.rb +9 -0
  48. data/spec/unit/virtus/attribute/class_methods/default_spec.rb +9 -0
  49. data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +31 -1
  50. data/spec/unit/virtus/attribute/class_methods/merge_options_spec.rb +11 -0
  51. data/spec/unit/virtus/attribute/class_methods/primitive_spec.rb +9 -0
  52. data/spec/unit/virtus/attribute/class_methods/reader_spec.rb +9 -0
  53. data/spec/unit/virtus/attribute/class_methods/writer_spec.rb +9 -0
  54. data/spec/unit/virtus/attribute/coerce_spec.rb +30 -0
  55. data/spec/unit/virtus/attribute/coercion_method_spec.rb +12 -0
  56. data/spec/unit/virtus/attribute/collection/class_methods/merge_options_spec.rb +40 -0
  57. data/spec/unit/virtus/attribute/collection/coerce_spec.rb +26 -0
  58. data/spec/unit/virtus/attribute/date/coerce_spec.rb +47 -0
  59. data/spec/unit/virtus/attribute/date/value_coerced_spec.rb +46 -0
  60. data/spec/unit/virtus/attribute/date_time/coerce_spec.rb +68 -0
  61. data/spec/unit/virtus/attribute/decimal/coerce_spec.rb +117 -0
  62. data/spec/unit/virtus/attribute/default_spec.rb +32 -0
  63. data/spec/unit/virtus/attribute/default_value/attribute_spec.rb +11 -0
  64. data/spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb +4 -2
  65. data/spec/unit/virtus/attribute/default_value/evaluate_spec.rb +51 -0
  66. data/spec/unit/virtus/attribute/default_value/instance_methods/evaluate_spec.rb +9 -6
  67. data/spec/unit/virtus/attribute/default_value/value_spec.rb +11 -0
  68. data/spec/unit/virtus/attribute/define_accessor_methods_spec.rb +26 -0
  69. data/spec/unit/virtus/attribute/define_reader_method_spec.rb +24 -0
  70. data/spec/unit/virtus/attribute/define_writer_method_spec.rb +24 -0
  71. data/spec/unit/virtus/attribute/embedded_value/class_methods/merge_options_spec.rb +17 -0
  72. data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +50 -0
  73. data/spec/unit/virtus/attribute/float/coerce_spec.rb +117 -0
  74. data/spec/unit/virtus/attribute/get_spec.rb +80 -0
  75. data/spec/unit/virtus/attribute/inspect_spec.rb +27 -0
  76. data/spec/unit/virtus/attribute/instance_variable_name_spec.rb +12 -0
  77. data/spec/unit/virtus/attribute/integer/coerce_spec.rb +105 -0
  78. data/spec/unit/virtus/attribute/name_spec.rb +12 -0
  79. data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +1 -1
  80. data/spec/unit/virtus/attribute/numeric/class_methods/max_spec.rb +9 -0
  81. data/spec/unit/virtus/attribute/numeric/class_methods/min_spec.rb +9 -0
  82. data/spec/unit/virtus/attribute/object/class_methods/descendants_spec.rb +9 -7
  83. data/spec/unit/virtus/attribute/options_spec.rb +14 -0
  84. data/spec/unit/virtus/attribute/public_reader_spec.rb +24 -0
  85. data/spec/unit/virtus/attribute/public_writer_spec.rb +24 -0
  86. data/spec/unit/virtus/attribute/reader_visibility_spec.rb +24 -0
  87. data/spec/unit/virtus/attribute/set/coerce_spec.rb +13 -0
  88. data/spec/unit/virtus/attribute/set_spec.rb +49 -0
  89. data/spec/unit/virtus/attribute/string/coerce_spec.rb +11 -0
  90. data/spec/unit/virtus/attribute/time/coerce_spec.rb +67 -0
  91. data/spec/unit/virtus/attribute/value_coerced_spec.rb +19 -0
  92. data/spec/unit/virtus/attribute/writer_visibility_spec.rb +24 -0
  93. data/spec/unit/virtus/attribute_set/append_spec.rb +12 -0
  94. data/spec/unit/virtus/attribute_set/element_reference_spec.rb +4 -0
  95. data/spec/unit/virtus/attribute_set/element_set_spec.rb +29 -9
  96. data/spec/unit/virtus/attributes_accessor/inspect_spec.rb +9 -0
  97. data/spec/unit/virtus/class_methods/attribute_spec.rb +23 -5
  98. data/spec/unit/virtus/class_methods/attributes_spec.rb +3 -5
  99. data/spec/unit/virtus/class_methods/const_missing_spec.rb +27 -0
  100. data/spec/unit/virtus/class_methods/inherited_spec.rb +21 -0
  101. data/spec/unit/virtus/coercion/array/to_set_spec.rb +12 -0
  102. data/spec/unit/virtus/coercion/date/class_methods/to_date_spec.rb +10 -0
  103. data/spec/unit/virtus/coercion/date_time/class_methods/to_datetime_spec.rb +10 -0
  104. data/spec/unit/virtus/coercion/hash/class_methods/to_date_spec.rb +10 -3
  105. data/spec/unit/virtus/coercion/hash/class_methods/to_datetime_spec.rb +10 -3
  106. data/spec/unit/virtus/coercion/hash/class_methods/to_time_spec.rb +10 -3
  107. data/spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb +8 -8
  108. data/spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb +2 -2
  109. data/spec/unit/virtus/coercion/string/class_methods/to_constant_spec.rb +1 -1
  110. data/spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb +1 -1
  111. data/spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb +13 -13
  112. data/spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb +25 -1
  113. data/spec/unit/virtus/coercion/string/class_methods/to_float_spec.rb +25 -1
  114. data/spec/unit/virtus/coercion/string/class_methods/to_integer_spec.rb +30 -1
  115. data/spec/unit/virtus/coercion/string/class_methods/to_time_spec.rb +13 -13
  116. data/spec/unit/virtus/coercion/time/class_methods/to_time_spec.rb +10 -0
  117. data/spec/unit/virtus/coercion/true_class/class_methods/to_string_spec.rb +1 -1
  118. data/spec/unit/virtus/instance_methods/attributes_spec.rb +77 -20
  119. data/spec/unit/virtus/instance_methods/element_reference_spec.rb +1 -1
  120. data/spec/unit/virtus/instance_methods/element_set_spec.rb +2 -2
  121. data/spec/unit/virtus/instance_methods/to_hash_spec.rb +23 -0
  122. data/spec/unit/virtus/options/accept_options_spec.rb +10 -11
  123. data/spec/unit/virtus/options/accepted_options_spec.rb +1 -1
  124. data/spec/unit/virtus/options/options_spec.rb +27 -4
  125. data/tasks/metrics/ci.rake +2 -1
  126. data/tasks/metrics/heckle.rake +207 -0
  127. data/tasks/spec.rake +14 -7
  128. data/virtus.gemspec +1 -1
  129. metadata +111 -97
  130. data/VERSION +0 -1
  131. data/examples/custom_coercion_spec.rb +0 -50
  132. data/examples/default_values_spec.rb +0 -21
  133. data/examples/override_attribute_methods_spec.rb +0 -40
  134. data/spec/integration/virtus/attributes/attribute/set_spec.rb +0 -36
  135. data/spec/integration/virtus/class_methods/attribute_spec.rb +0 -82
  136. data/spec/integration/virtus/class_methods/attributes_spec.rb +0 -22
  137. data/spec/integration/virtus/class_methods/const_missing_spec.rb +0 -44
  138. data/spec/unit/shared/attribute.rb +0 -7
  139. data/spec/unit/shared/attribute/accept_options.rb +0 -37
  140. data/spec/unit/shared/attribute/accepted_options.rb +0 -5
  141. data/spec/unit/shared/attribute/get.rb +0 -44
  142. data/spec/unit/shared/attribute/inspect.rb +0 -7
  143. data/spec/unit/shared/attribute/set.rb +0 -37
  144. data/spec/unit/virtus/attribute/array_spec.rb +0 -24
  145. data/spec/unit/virtus/attribute/class_spec.rb +0 -24
  146. data/spec/unit/virtus/attribute/date_spec.rb +0 -59
  147. data/spec/unit/virtus/attribute/date_time_spec.rb +0 -87
  148. data/spec/unit/virtus/attribute/decimal_spec.rb +0 -109
  149. data/spec/unit/virtus/attribute/float_spec.rb +0 -109
  150. data/spec/unit/virtus/attribute/hash_spec.rb +0 -11
  151. data/spec/unit/virtus/attribute/integer_spec.rb +0 -99
  152. data/spec/unit/virtus/attribute/string_spec.rb +0 -21
  153. data/spec/unit/virtus/attribute/time_spec.rb +0 -82
  154. data/spec/unit/virtus/class_methods/new_spec.rb +0 -41
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::Boolean, '#define_reader_method' do
4
+ subject { object.define_reader_method(mod) }
5
+
6
+ let(:object) { described_class.new(:active) }
7
+ let(:mod) { mock('mod', :define_reader_method => nil) }
8
+
9
+ it { should equal(object) }
10
+
11
+ it 'defines a reader method in the module' do
12
+ mod.should_receive(:define_reader_method).with(object, 'active?', :public)
13
+ subject
14
+ end
15
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::Boolean, '#value_coerced?' do
4
+ subject { attribute.value_coerced?(value) }
5
+
6
+ let(:attribute) { described_class.new(:is_admin) }
7
+
8
+ context "with true" do
9
+ let(:value) { true }
10
+
11
+ it { should be(true) }
12
+ end
13
+
14
+ context "with false" do
15
+ let(:value) { false }
16
+
17
+ it { should be(true) }
18
+ end
19
+
20
+ context "with 1" do
21
+ let(:value) { 1 }
22
+
23
+ it { should be(false) }
24
+ end
25
+
26
+ context "with '1'" do
27
+ let(:value) { '1' }
28
+
29
+ it { should be(false) }
30
+ end
31
+
32
+ context "with 'true'" do
33
+ let(:value) { 'true' }
34
+
35
+ it { should be(false) }
36
+ end
37
+
38
+ context "with 'TRUE'" do
39
+ let(:value) { 'TRUE' }
40
+
41
+ it { should be(false) }
42
+ end
43
+
44
+ context "with 't'" do
45
+ let(:value) { 't' }
46
+
47
+ it { should be(false) }
48
+ end
49
+
50
+ context "with 'T'" do
51
+ let(:value) { 'T' }
52
+
53
+ it { should be(false) }
54
+ end
55
+
56
+ context "with 0" do
57
+ let(:value) { 0 }
58
+
59
+ it { should be(false) }
60
+ end
61
+
62
+ context "with '0'" do
63
+ let(:value) { '0' }
64
+
65
+ it { should be(false) }
66
+ end
67
+
68
+ context "with 'false'" do
69
+ let(:value) { 'false' }
70
+
71
+ it { should be(false) }
72
+ end
73
+
74
+ context "with 'FALSE'" do
75
+ let(:value) { 'FALSE' }
76
+
77
+ it { should be(false) }
78
+ end
79
+
80
+ context "with 'f'" do
81
+ let(:value) { 'f' }
82
+
83
+ it { should be(false) }
84
+ end
85
+
86
+ context "with 'F'" do
87
+ let(:value) { 'F' }
88
+
89
+ it { should be(false) }
90
+ end
91
+
92
+ context "with 'Foo'" do
93
+ let(:value) { 'Foo' }
94
+
95
+ it { should be(false) }
96
+ end
97
+ end
@@ -1,15 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Virtus::Attribute::Boolean do
4
- it_should_behave_like 'Attribute' do
5
- let(:attribute_name) { :is_admin }
6
- let(:attribute_value) { true }
7
- let(:attribute_value_other) { '1' }
8
- let(:attribute_default) { true }
9
- let(:attribute_default_proc) { lambda { |instance, attribute| attribute.name == :is_admin } }
10
- end
11
-
12
- describe "accessor names" do
4
+ describe 'accessor names' do
13
5
  let(:model) do
14
6
  Class.new do
15
7
  include Virtus
@@ -20,79 +12,8 @@ describe Virtus::Attribute::Boolean do
20
12
 
21
13
  let(:object) { model.new(:is_admin => true) }
22
14
 
23
- it "uses standard boolean reader naming conventions" do
15
+ it 'uses standard boolean reader naming conventions' do
24
16
  object.is_admin?.should be_true
25
17
  end
26
18
  end
27
-
28
- describe '#coerce' do
29
- let(:attribute) { described_class.new(:is_admin) }
30
-
31
- subject { attribute.coerce(value) }
32
-
33
- context "with 1" do
34
- let(:value) { 1 }
35
- it { should be(true) }
36
- end
37
-
38
- context "with '1'" do
39
- let(:value) { '1' }
40
- it { should be(true) }
41
- end
42
-
43
- context "with 'true'" do
44
- let(:value) { 'true' }
45
- it { should be(true) }
46
- end
47
-
48
- context "with 'TRUE'" do
49
- let(:value) { 'TRUE' }
50
- it { should be(true) }
51
- end
52
-
53
- context "with 't'" do
54
- let(:value) { 't' }
55
- it { should be(true) }
56
- end
57
-
58
- context "with 'T'" do
59
- let(:value) { 'T' }
60
- it { should be(true) }
61
- end
62
-
63
- context "with 0" do
64
- let(:value) { 0 }
65
- it { should be(false) }
66
- end
67
-
68
- context "with '0'" do
69
- let(:value) { '0' }
70
- it { should be(false) }
71
- end
72
-
73
- context "with 'false'" do
74
- let(:value) { 'false' }
75
- it { should be(false) }
76
- end
77
-
78
- context "with 'FALSE'" do
79
- let(:value) { 'FALSE' }
80
- it { should be(false) }
81
- end
82
-
83
- context "with 'f'" do
84
- let(:value) { 'f' }
85
- it { should be(false) }
86
- end
87
-
88
- context "with 'F'" do
89
- let(:value) { 'F' }
90
- it { should be(false) }
91
- end
92
-
93
- context "with 'Foo'" do
94
- let(:value) { 'Foo' }
95
- it { should equal(value) }
96
- end
97
- end
98
19
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::Class, '#coerce' do
4
+ subject { attribute.coerce(value) }
5
+
6
+ let(:attribute) { described_class.new(:type) }
7
+
8
+ context 'with a String' do
9
+ let(:value) { 'String' }
10
+
11
+ it { should be(String) }
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.accessor' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:options) { { :primitive => primitive, :coercion_method => coercion_method } }
6
+ let(:primitive) { stub('primitive') }
7
+ let(:coercion_method) { stub('coercion_method') }
8
+ let(:method) { :accessor }
9
+ let(:default) { :public }
10
+
11
+ it_should_behave_like 'an options class method'
12
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.build' do
4
+ let(:object) { described_class }
5
+ let(:name) { :name }
6
+ let(:type) { String }
7
+
8
+ context 'without options' do
9
+ subject { object.build(name, type) }
10
+
11
+ it { should be_instance_of(Virtus::Attribute::String) }
12
+
13
+ its(:name) { should be(name) }
14
+
15
+ its(:options) { should == Virtus::Attribute::String.options }
16
+ end
17
+
18
+ context 'with options' do
19
+ subject { object.build(name, type, options) }
20
+
21
+ let(:options) { {} }
22
+
23
+ it { should be_instance_of(Virtus::Attribute::String) }
24
+
25
+ its(:name) { should be(name) }
26
+
27
+ its(:options) { should == Virtus::Attribute::String.options }
28
+ end
29
+
30
+ context 'with an invalid type' do
31
+ subject { object.build(name, type) }
32
+
33
+ let(:type) { 'test' }
34
+
35
+ specify { expect { subject }.to raise_error(ArgumentError, '"test" does not map to an attribute type') }
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.coercion_method' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:method) { :coercion_method }
6
+ let(:default) { nil }
7
+
8
+ it_should_behave_like 'an options class method'
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.default' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:method) { :default }
6
+ let(:default) { nil }
7
+
8
+ it_should_behave_like 'an options class method'
9
+ end
@@ -13,9 +13,15 @@ describe Virtus::Attribute, '.determine_type' do
13
13
  end
14
14
 
15
15
  primitive = attribute_class.primitive
16
- context "with primitive #{primitive.inspect}" do
16
+ context "with #{attribute_class.inspect} and primitive #{primitive.inspect}" do
17
17
  subject { object.determine_type(primitive) }
18
18
 
19
+ before do
20
+ if [Virtus::Attribute::EmbeddedValue, Virtus::Attribute::Collection].include? attribute_class
21
+ pending
22
+ end
23
+ end
24
+
19
25
  it 'returns the corresponding attribute class' do
20
26
  should be(attribute_class)
21
27
  end
@@ -31,6 +37,14 @@ describe Virtus::Attribute, '.determine_type' do
31
37
  end
32
38
  end
33
39
 
40
+ context 'with a virtus model' do
41
+ subject { object.determine_type(primitive) }
42
+
43
+ let(:primitive) { Class.new { include Virtus } }
44
+
45
+ it { should equal(Virtus::Attribute::EmbeddedValue) }
46
+ end
47
+
34
48
  context 'when the primitive defaults to Object' do
35
49
  subject { object.determine_type(primitive) }
36
50
 
@@ -46,4 +60,20 @@ describe Virtus::Attribute, '.determine_type' do
46
60
 
47
61
  it { should be_nil }
48
62
  end
63
+
64
+ context 'with an instance of an array' do
65
+ subject { object.determine_type(primitive) }
66
+
67
+ let(:primitive) { Array[String] }
68
+
69
+ it { should equal(Virtus::Attribute::Array) }
70
+ end
71
+
72
+ context 'with an instance of a set' do
73
+ subject { object.determine_type(primitive) }
74
+
75
+ let(:primitive) { Set[String] }
76
+
77
+ it { should equal(Virtus::Attribute::Set) }
78
+ end
49
79
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.merge_options' do
4
+ subject { object.merge_options(type, options) }
5
+
6
+ let(:object) { described_class }
7
+ let(:type) { stub('type') }
8
+ let(:options) { stub('options') }
9
+
10
+ it { should == options }
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.primitive' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:method) { :primitive }
6
+ let(:default) { nil }
7
+
8
+ it_should_behave_like 'an options class method'
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.reader' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:method) { :reader }
6
+ let(:default) { nil }
7
+
8
+ it_should_behave_like 'an options class method'
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '.writer' do
4
+ let(:object) { Class.new(described_class) }
5
+ let(:method) { :writer }
6
+ let(:default) { nil }
7
+
8
+ it_should_behave_like 'an options class method'
9
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '#coerce' do
4
+ subject { object.coerce(value) }
5
+
6
+ let(:object) { described_class.new(:name, options) }
7
+ let(:options) { { :primitive => primitive, :coercion_method => coercion_method } }
8
+ let(:primitive) { stub('primitive') }
9
+ let(:coercion_method) { stub('coercion_method') }
10
+ let(:value) { mock('value', :class => value_class) }
11
+ let(:value_class) { stub('value_class') }
12
+ let(:coercer) { mock('coercer', :send => coerced) }
13
+ let(:coerced) { stub('coerced') }
14
+
15
+ before do
16
+ Virtus::Coercion.stub(:[]).with(value_class).and_return(coercer)
17
+ end
18
+
19
+ it { should be(coerced) }
20
+
21
+ it 'asks for a coercer object' do
22
+ Virtus::Coercion.should_receive(:[]).with(value_class)
23
+ subject
24
+ end
25
+
26
+ it 'asks the coercer to coerce the value' do
27
+ coercer.should_receive(:send).with(coercion_method, value)
28
+ subject
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute, '#coercion_method' do
4
+ subject { object.coercion_method }
5
+
6
+ let(:object) { described_class.new(:name, options) }
7
+ let(:options) { { :primitive => primitive, :coercion_method => coercion_method } }
8
+ let(:primitive) { stub('primitive') }
9
+ let(:coercion_method) { stub('coercion_method') }
10
+
11
+ it { should be(coercion_method) }
12
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::Collection, '.merge_options' do
4
+ subject { described_class.merge_options(type, options) }
5
+
6
+ let(:type) { mock('type') }
7
+ let(:member_type) { mock('member_type') }
8
+ let(:options) { Hash.new }
9
+
10
+ context 'when `type` responds to `size`' do
11
+ before do
12
+ type.should_receive(:respond_to?).with(:size).and_return(true)
13
+ type.should_receive(:size).and_return(size)
14
+ end
15
+
16
+ context 'when size is == 1' do
17
+ let(:size) { 1 }
18
+
19
+ before do
20
+ type.should_receive(:first).and_return(member_type)
21
+ end
22
+
23
+ specify { subject[:member_type].should eql(member_type) }
24
+ end
25
+
26
+ context 'when size is > 1' do
27
+ let(:size) { 2 }
28
+
29
+ specify { expect { subject }.to raise_error(NotImplementedError) }
30
+ end
31
+ end
32
+
33
+ context 'when `type` does not respond to `size`' do
34
+ before do
35
+ type.should_receive(:respond_to?).with(:size).and_return(false)
36
+ end
37
+
38
+ it { should eql(options) }
39
+ end
40
+ end