virtus 0.0.10 → 0.1.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.
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