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.
Files changed (268) hide show
  1. data/.rspec +1 -1
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +6 -8
  5. data/Gemfile +8 -2
  6. data/Gemfile.devtools +24 -30
  7. data/Guardfile +17 -6
  8. data/README.md +215 -77
  9. data/TODO.md +6 -0
  10. data/config/flay.yml +2 -2
  11. data/config/flog.yml +1 -1
  12. data/config/mutant.yml +12 -1
  13. data/config/reek.yml +57 -66
  14. data/lib/virtus.rb +126 -42
  15. data/lib/virtus/attribute.rb +52 -240
  16. data/lib/virtus/attribute/accessor.rb +91 -0
  17. data/lib/virtus/attribute/boolean.rb +11 -8
  18. data/lib/virtus/attribute/builder.rb +120 -0
  19. data/lib/virtus/attribute/coercer.rb +51 -0
  20. data/lib/virtus/attribute/coercible.rb +14 -0
  21. data/lib/virtus/attribute/collection.rb +44 -90
  22. data/lib/virtus/attribute/default_value/from_callable.rb +1 -1
  23. data/lib/virtus/attribute/default_value/from_clonable.rb +1 -6
  24. data/lib/virtus/attribute/default_value/from_symbol.rb +3 -3
  25. data/lib/virtus/attribute/embedded_value.rb +37 -28
  26. data/lib/virtus/attribute/hash.rb +69 -71
  27. data/lib/virtus/attribute/lazy_default.rb +18 -0
  28. data/lib/virtus/attribute/strict.rb +16 -0
  29. data/lib/virtus/attribute_set.rb +81 -9
  30. data/lib/virtus/class_inclusions.rb +24 -17
  31. data/lib/virtus/class_methods.rb +13 -31
  32. data/lib/virtus/configuration.rb +77 -0
  33. data/lib/virtus/const_missing_extensions.rb +16 -0
  34. data/lib/virtus/extensions.rb +86 -61
  35. data/lib/virtus/instance_methods.rb +107 -128
  36. data/lib/virtus/model.rb +68 -0
  37. data/lib/virtus/module_builder.rb +184 -0
  38. data/lib/virtus/module_extensions.rb +27 -15
  39. data/lib/virtus/support/equalizer.rb +2 -3
  40. data/lib/virtus/support/type_lookup.rb +1 -1
  41. data/lib/virtus/value_object.rb +24 -31
  42. data/lib/virtus/version.rb +1 -1
  43. data/spec/integration/building_module_spec.rb +68 -0
  44. data/spec/integration/custom_attributes_spec.rb +8 -15
  45. data/spec/integration/custom_collection_attributes_spec.rb +101 -0
  46. data/spec/integration/default_values_spec.rb +9 -2
  47. data/spec/integration/defining_attributes_spec.rb +2 -2
  48. data/spec/integration/using_modules_spec.rb +5 -3
  49. data/spec/shared/freeze_method_behavior.rb +2 -2
  50. data/spec/shared/options_class_method.rb +1 -1
  51. data/spec/spec_helper.rb +25 -5
  52. data/spec/unit/virtus/attribute/boolean/value_coerced_predicate_spec.rb +25 -0
  53. data/spec/unit/virtus/attribute/class_methods/build_spec.rb +115 -22
  54. data/spec/unit/virtus/attribute/class_methods/coerce_spec.rb +32 -0
  55. data/spec/unit/virtus/attribute/coerce_spec.rb +38 -21
  56. data/spec/unit/virtus/attribute/coercible_predicate_spec.rb +20 -0
  57. data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +84 -0
  58. data/spec/unit/virtus/attribute/collection/coerce_spec.rb +37 -24
  59. data/spec/unit/virtus/attribute/custom_collection_spec.rb +23 -0
  60. data/spec/unit/virtus/attribute/embedded_value/class_methods/build_spec.rb +37 -0
  61. data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +46 -10
  62. data/spec/unit/virtus/attribute/get_spec.rb +15 -63
  63. data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +80 -0
  64. data/spec/unit/virtus/attribute/hash/coerce_spec.rb +75 -13
  65. data/spec/unit/virtus/attribute/lazy_predicate_spec.rb +20 -0
  66. data/spec/unit/virtus/attribute/set_default_value_spec.rb +74 -0
  67. data/spec/unit/virtus/attribute/set_spec.rb +16 -36
  68. data/spec/unit/virtus/attribute/value_coerced_predicate_spec.rb +19 -0
  69. data/spec/unit/virtus/attribute_set/append_spec.rb +3 -5
  70. data/spec/unit/virtus/attribute_set/define_reader_method_spec.rb +1 -1
  71. data/spec/unit/virtus/attribute_set/define_writer_method_spec.rb +1 -1
  72. data/spec/unit/virtus/attribute_set/each_spec.rb +3 -3
  73. data/spec/unit/virtus/attribute_set/element_reference_spec.rb +1 -1
  74. data/spec/unit/virtus/attribute_set/element_set_spec.rb +4 -4
  75. data/spec/unit/virtus/attribute_set/merge_spec.rb +10 -16
  76. data/spec/unit/virtus/attribute_set/reset_spec.rb +6 -10
  77. data/spec/unit/virtus/attribute_spec.rb +222 -0
  78. data/spec/unit/virtus/attributes_reader_spec.rb +41 -0
  79. data/spec/unit/virtus/attributes_writer_spec.rb +51 -0
  80. data/spec/unit/virtus/class_methods/new_spec.rb +39 -0
  81. data/spec/unit/virtus/config_spec.rb +13 -0
  82. data/spec/unit/virtus/element_reader_spec.rb +21 -0
  83. data/spec/unit/virtus/element_writer_spec.rb +19 -0
  84. data/spec/unit/virtus/freeze_spec.rb +21 -0
  85. data/spec/unit/virtus/model_spec.rb +134 -0
  86. data/spec/unit/virtus/module_spec.rb +76 -0
  87. data/spec/unit/virtus/set_default_attributes_spec.rb +25 -0
  88. data/spec/unit/virtus/value_object_spec.rb +105 -0
  89. data/virtus.gemspec +4 -2
  90. metadata +82 -191
  91. data/.rvmrc +0 -1
  92. data/TODO +0 -1
  93. data/config/roodi.yml +0 -17
  94. data/lib/virtus/attribute/array.rb +0 -24
  95. data/lib/virtus/attribute/class.rb +0 -21
  96. data/lib/virtus/attribute/date.rb +0 -34
  97. data/lib/virtus/attribute/date_time.rb +0 -36
  98. data/lib/virtus/attribute/decimal.rb +0 -21
  99. data/lib/virtus/attribute/embedded_value/from_open_struct.rb +0 -19
  100. data/lib/virtus/attribute/embedded_value/from_struct.rb +0 -19
  101. data/lib/virtus/attribute/float.rb +0 -30
  102. data/lib/virtus/attribute/integer.rb +0 -27
  103. data/lib/virtus/attribute/numeric.rb +0 -11
  104. data/lib/virtus/attribute/object.rb +0 -11
  105. data/lib/virtus/attribute/set.rb +0 -24
  106. data/lib/virtus/attribute/string.rb +0 -24
  107. data/lib/virtus/attribute/symbol.rb +0 -21
  108. data/lib/virtus/attribute/time.rb +0 -36
  109. data/lib/virtus/coercion.rb +0 -32
  110. data/lib/virtus/coercion/array.rb +0 -23
  111. data/lib/virtus/coercion/date.rb +0 -26
  112. data/lib/virtus/coercion/date_time.rb +0 -26
  113. data/lib/virtus/coercion/decimal.rb +0 -40
  114. data/lib/virtus/coercion/false_class.rb +0 -24
  115. data/lib/virtus/coercion/float.rb +0 -39
  116. data/lib/virtus/coercion/hash.rb +0 -71
  117. data/lib/virtus/coercion/integer.rb +0 -83
  118. data/lib/virtus/coercion/numeric.rb +0 -66
  119. data/lib/virtus/coercion/object.rb +0 -125
  120. data/lib/virtus/coercion/string.rb +0 -218
  121. data/lib/virtus/coercion/symbol.rb +0 -24
  122. data/lib/virtus/coercion/time.rb +0 -40
  123. data/lib/virtus/coercion/time_coercions.rb +0 -86
  124. data/lib/virtus/coercion/true_class.rb +0 -24
  125. data/spec/unit/virtus/attribute/array/coerce_spec.rb +0 -13
  126. data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +0 -85
  127. data/spec/unit/virtus/attribute/boolean/define_reader_method_spec.rb +0 -15
  128. data/spec/unit/virtus/attribute/boolean/value_coerced_spec.rb +0 -97
  129. data/spec/unit/virtus/attribute/boolean_spec.rb +0 -19
  130. data/spec/unit/virtus/attribute/class/coerce_spec.rb +0 -13
  131. data/spec/unit/virtus/attribute/class_methods/accessor_spec.rb +0 -12
  132. data/spec/unit/virtus/attribute/class_methods/coercion_method_spec.rb +0 -9
  133. data/spec/unit/virtus/attribute/class_methods/default_spec.rb +0 -9
  134. data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +0 -117
  135. data/spec/unit/virtus/attribute/class_methods/merge_options_spec.rb +0 -11
  136. data/spec/unit/virtus/attribute/class_methods/primitive_spec.rb +0 -9
  137. data/spec/unit/virtus/attribute/class_methods/reader_spec.rb +0 -9
  138. data/spec/unit/virtus/attribute/class_methods/writer_spec.rb +0 -9
  139. data/spec/unit/virtus/attribute/coercion_method_spec.rb +0 -12
  140. data/spec/unit/virtus/attribute/collection/class_methods/merge_options_spec.rb +0 -40
  141. data/spec/unit/virtus/attribute/collection/coerce_and_append_member_spec.rb +0 -16
  142. data/spec/unit/virtus/attribute/collection/member_coercion/coerce_and_append_member_spec.rb +0 -18
  143. data/spec/unit/virtus/attribute/collection/member_type_spec.rb +0 -17
  144. data/spec/unit/virtus/attribute/collection/new_collection_spec.rb +0 -9
  145. data/spec/unit/virtus/attribute/date/coerce_spec.rb +0 -47
  146. data/spec/unit/virtus/attribute/date/value_coerced_spec.rb +0 -46
  147. data/spec/unit/virtus/attribute/date_time/coerce_spec.rb +0 -80
  148. data/spec/unit/virtus/attribute/decimal/coerce_spec.rb +0 -123
  149. data/spec/unit/virtus/attribute/default_spec.rb +0 -28
  150. data/spec/unit/virtus/attribute/default_value/call_spec.rb +0 -21
  151. data/spec/unit/virtus/attribute/default_value/class_methods/build_spec.rb +0 -23
  152. data/spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb +0 -21
  153. data/spec/unit/virtus/attribute/default_value/from_callable/call_spec.rb +0 -19
  154. data/spec/unit/virtus/attribute/default_value/from_callable/class_methods/handle_spec.rb +0 -17
  155. data/spec/unit/virtus/attribute/default_value/from_clonable/call_spec.rb +0 -20
  156. data/spec/unit/virtus/attribute/default_value/from_clonable/class_methods/handle_spec.rb +0 -19
  157. data/spec/unit/virtus/attribute/default_value/from_symbol/call_spec.rb +0 -17
  158. data/spec/unit/virtus/attribute/default_value/from_symbol/class_methods/handle_spec.rb +0 -17
  159. data/spec/unit/virtus/attribute/default_value/value_spec.rb +0 -10
  160. data/spec/unit/virtus/attribute/define_accessor_methods_spec.rb +0 -26
  161. data/spec/unit/virtus/attribute/define_reader_method_spec.rb +0 -24
  162. data/spec/unit/virtus/attribute/define_writer_method_spec.rb +0 -24
  163. data/spec/unit/virtus/attribute/embedded_value/class_methods/determine_type_spec.rb +0 -23
  164. data/spec/unit/virtus/attribute/embedded_value/class_methods/merge_options_spec.rb +0 -17
  165. data/spec/unit/virtus/attribute/embedded_value/from_open_struct/coerce_spec.rb +0 -34
  166. data/spec/unit/virtus/attribute/embedded_value/from_struct/coerce_spec.rb +0 -34
  167. data/spec/unit/virtus/attribute/float/coerce_spec.rb +0 -123
  168. data/spec/unit/virtus/attribute/hash/class_methods/merge_options_spec.rb +0 -33
  169. data/spec/unit/virtus/attribute/hash/key_type_spec.rb +0 -10
  170. data/spec/unit/virtus/attribute/hash/value_type_spec.rb +0 -10
  171. data/spec/unit/virtus/attribute/inspect_spec.rb +0 -27
  172. data/spec/unit/virtus/attribute/integer/coerce_spec.rb +0 -117
  173. data/spec/unit/virtus/attribute/name_spec.rb +0 -12
  174. data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +0 -15
  175. data/spec/unit/virtus/attribute/numeric/class_methods/max_spec.rb +0 -9
  176. data/spec/unit/virtus/attribute/numeric/class_methods/min_spec.rb +0 -9
  177. data/spec/unit/virtus/attribute/options_spec.rb +0 -14
  178. data/spec/unit/virtus/attribute/public_reader_spec.rb +0 -24
  179. data/spec/unit/virtus/attribute/public_writer_spec.rb +0 -24
  180. data/spec/unit/virtus/attribute/set/coerce_spec.rb +0 -13
  181. data/spec/unit/virtus/attribute/string/coerce_spec.rb +0 -11
  182. data/spec/unit/virtus/attribute/symbol/coerce_spec.rb +0 -13
  183. data/spec/unit/virtus/attribute/time/coerce_spec.rb +0 -67
  184. data/spec/unit/virtus/attribute/value_coerced_spec.rb +0 -19
  185. data/spec/unit/virtus/class_methods/attribute_set_spec.rb +0 -9
  186. data/spec/unit/virtus/class_methods/attribute_spec.rb +0 -30
  187. data/spec/unit/virtus/class_methods/attributes_spec.rb +0 -22
  188. data/spec/unit/virtus/class_methods/const_missing_spec.rb +0 -27
  189. data/spec/unit/virtus/class_methods/inherited_spec.rb +0 -21
  190. data/spec/unit/virtus/coercion/array/class_methods/to_set_spec.rb +0 -12
  191. data/spec/unit/virtus/coercion/class_methods/element_reference_spec.rb +0 -17
  192. data/spec/unit/virtus/coercion/class_methods/primitive_spec.rb +0 -13
  193. data/spec/unit/virtus/coercion/date/class_methods/to_date_spec.rb +0 -10
  194. data/spec/unit/virtus/coercion/date/class_methods/to_datetime_spec.rb +0 -30
  195. data/spec/unit/virtus/coercion/date/class_methods/to_string_spec.rb +0 -12
  196. data/spec/unit/virtus/coercion/date/class_methods/to_time_spec.rb +0 -12
  197. data/spec/unit/virtus/coercion/date_time/class_methods/to_date_spec.rb +0 -30
  198. data/spec/unit/virtus/coercion/date_time/class_methods/to_datetime_spec.rb +0 -10
  199. data/spec/unit/virtus/coercion/date_time/class_methods/to_string_spec.rb +0 -12
  200. data/spec/unit/virtus/coercion/date_time/class_methods/to_time_spec.rb +0 -30
  201. data/spec/unit/virtus/coercion/decimal/class_methods/to_decimal_spec.rb +0 -9
  202. data/spec/unit/virtus/coercion/decimal/class_methods/to_float_spec.rb +0 -12
  203. data/spec/unit/virtus/coercion/decimal/class_methods/to_integer_spec.rb +0 -12
  204. data/spec/unit/virtus/coercion/decimal/class_methods/to_string_spec.rb +0 -12
  205. data/spec/unit/virtus/coercion/false_class/class_methods/to_string_spec.rb +0 -12
  206. data/spec/unit/virtus/coercion/float/class_methods/to_decimal_spec.rb +0 -12
  207. data/spec/unit/virtus/coercion/float/class_methods/to_float_spec.rb +0 -9
  208. data/spec/unit/virtus/coercion/float/class_methods/to_integer_spec.rb +0 -12
  209. data/spec/unit/virtus/coercion/float/class_methods/to_string_spec.rb +0 -12
  210. data/spec/unit/virtus/coercion/hash/class_methods/to_date_spec.rb +0 -38
  211. data/spec/unit/virtus/coercion/hash/class_methods/to_datetime_spec.rb +0 -38
  212. data/spec/unit/virtus/coercion/hash/class_methods/to_time_spec.rb +0 -38
  213. data/spec/unit/virtus/coercion/integer/class_methods/to_boolean_spec.rb +0 -25
  214. data/spec/unit/virtus/coercion/integer/class_methods/to_decimal_spec.rb +0 -12
  215. data/spec/unit/virtus/coercion/integer/class_methods/to_float_spec.rb +0 -12
  216. data/spec/unit/virtus/coercion/integer/class_methods/to_integer_spec.rb +0 -9
  217. data/spec/unit/virtus/coercion/integer/class_methods/to_string_spec.rb +0 -12
  218. data/spec/unit/virtus/coercion/numeric/class_methods/to_decimal_spec.rb +0 -10
  219. data/spec/unit/virtus/coercion/numeric/class_methods/to_float_spec.rb +0 -10
  220. data/spec/unit/virtus/coercion/numeric/class_methods/to_integer_spec.rb +0 -10
  221. data/spec/unit/virtus/coercion/numeric/class_methods/to_string_spec.rb +0 -12
  222. data/spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb +0 -33
  223. data/spec/unit/virtus/coercion/object/class_methods/to_array_spec.rb +0 -51
  224. data/spec/unit/virtus/coercion/object/class_methods/to_hash_spec.rb +0 -22
  225. data/spec/unit/virtus/coercion/object/class_methods/to_integer_spec.rb +0 -22
  226. data/spec/unit/virtus/coercion/object/class_methods/to_string_spec.rb +0 -22
  227. data/spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb +0 -29
  228. data/spec/unit/virtus/coercion/string/class_methods/to_constant_spec.rb +0 -49
  229. data/spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb +0 -23
  230. data/spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb +0 -50
  231. data/spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb +0 -47
  232. data/spec/unit/virtus/coercion/string/class_methods/to_float_spec.rb +0 -57
  233. data/spec/unit/virtus/coercion/string/class_methods/to_integer_spec.rb +0 -68
  234. data/spec/unit/virtus/coercion/string/class_methods/to_symbol_spec.rb +0 -9
  235. data/spec/unit/virtus/coercion/string/class_methods/to_time_spec.rb +0 -50
  236. data/spec/unit/virtus/coercion/symbol/class_methods/to_string_spec.rb +0 -12
  237. data/spec/unit/virtus/coercion/time/class_methods/to_integer_spec.rb +0 -10
  238. data/spec/unit/virtus/coercion/time/class_methods/to_time_spec.rb +0 -10
  239. data/spec/unit/virtus/coercion/time_coercions/to_date_spec.rb +0 -33
  240. data/spec/unit/virtus/coercion/time_coercions/to_datetime_spec.rb +0 -33
  241. data/spec/unit/virtus/coercion/time_coercions/to_string_spec.rb +0 -18
  242. data/spec/unit/virtus/coercion/time_coercions/to_time_spec.rb +0 -33
  243. data/spec/unit/virtus/coercion/true_class/class_methods/to_string_spec.rb +0 -12
  244. data/spec/unit/virtus/equalizer/append_spec.rb +0 -82
  245. data/spec/unit/virtus/equalizer/class_method/new_spec.rb +0 -111
  246. data/spec/unit/virtus/equalizer/methods/eql_spec.rb +0 -47
  247. data/spec/unit/virtus/equalizer/methods/equal_value_spec.rb +0 -57
  248. data/spec/unit/virtus/extensions/allowed_writer_methods_spec.rb +0 -25
  249. data/spec/unit/virtus/extensions/attribute_spec.rb +0 -26
  250. data/spec/unit/virtus/instance_methods/attributes_spec.rb +0 -140
  251. data/spec/unit/virtus/instance_methods/element_reference_spec.rb +0 -24
  252. data/spec/unit/virtus/instance_methods/element_set_spec.rb +0 -28
  253. data/spec/unit/virtus/instance_methods/freeze_spec.rb +0 -64
  254. data/spec/unit/virtus/instance_methods/initialize_spec.rb +0 -48
  255. data/spec/unit/virtus/instance_methods/to_hash_spec.rb +0 -23
  256. data/spec/unit/virtus/module_extensions/attribute_spec.rb +0 -31
  257. data/spec/unit/virtus/options/accept_options_spec.rb +0 -37
  258. data/spec/unit/virtus/options/accepted_options_spec.rb +0 -21
  259. data/spec/unit/virtus/options/options_spec.rb +0 -34
  260. data/spec/unit/virtus/type_lookup/class_methods/extended_spec.rb +0 -9
  261. data/spec/unit/virtus/type_lookup/determine_type_spec.rb +0 -81
  262. data/spec/unit/virtus/type_lookup/primitive_spec.rb +0 -9
  263. data/spec/unit/virtus/value_object/class_methods/allowed_writer_methods_spec.rb +0 -15
  264. data/spec/unit/virtus/value_object/class_methods/attribute_spec.rb +0 -50
  265. data/spec/unit/virtus/value_object/class_methods/equalizer_spec.rb +0 -24
  266. data/spec/unit/virtus/value_object/initialize_spec.rb +0 -19
  267. data/spec/unit/virtus/value_object/instance_methods/clone_spec.rb +0 -21
  268. data/spec/unit/virtus/value_object/instance_methods/with_spec.rb +0 -31
@@ -3,36 +3,30 @@ require 'spec_helper'
3
3
  describe Virtus::AttributeSet, '#merge' do
4
4
  subject { object.merge(other) }
5
5
 
6
- let(:attributes) { [] }
7
- let(:parent) { described_class.new }
8
- let(:object) { described_class.new(parent, attributes) }
9
- let(:name) { :name }
10
- let(:other) { [ attribute ] }
11
-
12
- before { attribute.stub(:define_accessor_methods) }
6
+ let(:parent) { described_class.new }
7
+ let(:object) { described_class.new(parent, attributes) }
8
+ let(:name) { :name }
9
+ let(:other) { [attribute] }
13
10
 
14
11
  context 'with a new attribute' do
15
- let(:attribute) { mock('Attribute', :name => name) }
12
+ let(:attributes) { [] }
13
+ let(:attribute) { Virtus::Attribute.build(String, :name => name) }
16
14
 
17
15
  it { should equal(object) }
18
16
 
19
17
  it 'adds an attribute' do
20
- expect { subject }.to change { object.to_a }.
21
- from(attributes).
22
- to([ attribute ])
18
+ expect { subject }.to change { object.to_a }.from(attributes).to([attribute])
23
19
  end
24
20
  end
25
21
 
26
22
  context 'with a duplicate attribute' do
27
- let(:attributes) { [ mock('Attribute', :name => name) ] }
28
- let(:attribute) { mock('Duplicate', :name => name) }
23
+ let(:attributes) { [Virtus::Attribute.build(String, :name => name)] }
24
+ let(:attribute) { Virtus::Attribute.build(String, :name => name) }
29
25
 
30
26
  it { should equal(object) }
31
27
 
32
28
  it 'replaces the original attribute' do
33
- expect { subject }.to change { object.to_a }.
34
- from(attributes).
35
- to([ attribute ])
29
+ expect { subject }.to change { object.to_a }.from(attributes).to([attribute])
36
30
  end
37
31
  end
38
32
  end
@@ -3,13 +3,11 @@ require 'spec_helper'
3
3
  describe Virtus::AttributeSet, '#reset' do
4
4
  subject { object.reset }
5
5
 
6
- let(:name) { :name }
7
- let(:attribute) { mock('Attribute', :name => name) }
6
+ let(:name) { :name }
7
+ let(:attribute) { Virtus::Attribute.build(String, :name => :name) }
8
8
  let(:attributes) { [ attribute ] }
9
9
  let(:object) { described_class.new(parent, attributes) }
10
10
 
11
- before { attribute.stub(:define_accessor_methods) }
12
-
13
11
  context 'when the parent has no attributes' do
14
12
  let(:parent) { described_class.new }
15
13
 
@@ -19,7 +17,7 @@ describe Virtus::AttributeSet, '#reset' do
19
17
  end
20
18
 
21
19
  context 'when the parent has attributes that are not duplicates' do
22
- let(:parent_attribute) { mock('Parent Attribute', :name => :parent_name) }
20
+ let(:parent_attribute) { Virtus::Attribute.build(String, :name => :parent_name) }
23
21
  let(:parent) { described_class.new([ parent_attribute ]) }
24
22
 
25
23
  it { should equal(object) }
@@ -28,7 +26,7 @@ describe Virtus::AttributeSet, '#reset' do
28
26
  end
29
27
 
30
28
  context 'when the parent has attributes that are duplicates' do
31
- let(:parent_attribute) { mock('Parent Attribute', :name => name) }
29
+ let(:parent_attribute) { Virtus::Attribute.build(String, :name => name) }
32
30
  let(:parent) { described_class.new([ parent_attribute ]) }
33
31
 
34
32
  it { should equal(object) }
@@ -37,11 +35,9 @@ describe Virtus::AttributeSet, '#reset' do
37
35
  end
38
36
 
39
37
  context 'when the parent has changed' do
40
- let(:parent_attribute) { mock('Parent Attribute', :name => :parent_name) }
38
+ let(:parent_attribute) { Virtus::Attribute.build(String, :name => :parent_name) }
41
39
  let(:parent) { described_class.new([ parent_attribute ]) }
42
- let(:new_attribute) { mock('New Attribute', :name => :parent_name) }
43
-
44
- before { new_attribute.stub(:define_accessor_methods) }
40
+ let(:new_attribute) { Virtus::Attribute.build(String, :name => :parent_name) }
45
41
 
46
42
  it { should equal(object) }
47
43
 
@@ -0,0 +1,222 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus, '#attribute' do
4
+ let(:name) { :test }
5
+ let(:options) { {} }
6
+
7
+ share_examples_for 'a class with boolean attribute' do
8
+ subject { Test }
9
+
10
+ let(:object) { subject.new }
11
+
12
+ it 'defines reader and writer' do
13
+ object.test = true
14
+ expect(object.test).to be(true)
15
+ end
16
+
17
+ it 'defines predicate method' do
18
+ object.test = false
19
+
20
+ expect(object).to_not be_test
21
+ end
22
+ end
23
+
24
+ share_examples_for 'an object with string attribute' do
25
+ it { should respond_to(:test) }
26
+ it { should respond_to(:test=) }
27
+
28
+ it 'can write and read the attribute' do
29
+ subject.test = :foo
30
+ expect(subject.test).to eql('foo')
31
+ end
32
+ end
33
+
34
+ it 'returns self' do
35
+ klass = Class.new { include Virtus }
36
+ expect(klass.attribute(:test, String)).to be(klass)
37
+ end
38
+
39
+ it 'raises error when :name is a reserved name on a class' do
40
+ klass = Class.new { include Virtus }
41
+ expect { klass.attribute(:attributes, Set) }.to raise_error(
42
+ ArgumentError, ':attributes is not allowed as an attribute name'
43
+ )
44
+ end
45
+
46
+ it 'raises error when :name is a reserved name on an instance' do
47
+ object = Class.new.new.extend(Virtus)
48
+ expect { object.attribute(:attributes, Set) }.to raise_error(
49
+ ArgumentError, ':attributes is not allowed as an attribute name'
50
+ )
51
+ end
52
+
53
+ it 'allows :attributes as an attribute name when mass-assignment is not included' do
54
+ klass = Class.new { include Virtus::Model::Core }
55
+ klass.attribute(:attributes, Set)
56
+ expect(klass.attribute_set[:attributes]).to be_instance_of(Virtus::Attribute::Collection)
57
+ end
58
+
59
+ context 'with a class' do
60
+ context 'when type is Boolean' do
61
+ before :all do
62
+ class Test
63
+ include Virtus
64
+
65
+ attribute :test, Boolean
66
+ end
67
+ end
68
+
69
+ after :all do
70
+ Object.send(:remove_const, :Test)
71
+ end
72
+
73
+ it_behaves_like 'a class with boolean attribute'
74
+ end
75
+
76
+ context 'when type is "Boolean"' do
77
+ before :all do
78
+ class Test
79
+ include Virtus
80
+
81
+ attribute :test, 'Boolean'
82
+ end
83
+ end
84
+
85
+ after :all do
86
+ Object.send(:remove_const, :Test)
87
+ end
88
+
89
+ it_behaves_like 'a class with boolean attribute'
90
+ end
91
+
92
+ context 'when type is Axiom::Types::Boolean' do
93
+ before :all do
94
+ class Test
95
+ include Virtus
96
+
97
+ attribute :test, Axiom::Types::Boolean
98
+ end
99
+ end
100
+
101
+ after :all do
102
+ Object.send(:remove_const, :Test)
103
+ end
104
+
105
+ it_behaves_like 'a class with boolean attribute' do
106
+ before do
107
+ pending 'this will be fixed once Attribute::Boolean subclass is gone'
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'when type is :Boolean' do
113
+ before :all do
114
+ class Test
115
+ include Virtus
116
+
117
+ attribute :test, 'Boolean'
118
+ end
119
+ end
120
+
121
+ after :all do
122
+ Object.send(:remove_const, :Test)
123
+ end
124
+
125
+ it_behaves_like 'a class with boolean attribute'
126
+
127
+ context 'with a subclass' do
128
+ it_behaves_like 'a class with boolean attribute' do
129
+ subject { Class.new(Test) }
130
+
131
+ it 'gets attributes from the parent class' do
132
+ Test.attribute :other, Integer
133
+ expect(subject.attribute_set[:other]).to eql(Test.attribute_set[:other])
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ context 'when type is Decimal' do
140
+ before :all do
141
+ class Test
142
+ include Virtus
143
+
144
+ attribute :test, Decimal
145
+ end
146
+ end
147
+
148
+ after :all do
149
+ Object.send(:remove_const, :Test)
150
+ end
151
+
152
+ it 'maps type to the corresponding axiom type' do
153
+ expect(Test.attribute_set[:test].type).to be(Axiom::Types::Decimal)
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'with a module' do
159
+ let(:mod) {
160
+ Module.new {
161
+ include Virtus
162
+
163
+ attribute :test, String
164
+ }
165
+ }
166
+
167
+ let(:model) { Class.new }
168
+
169
+ context 'included in the class' do
170
+ before do
171
+ model.send(:include, mod)
172
+ end
173
+
174
+ it 'adds attributes from the module to a class that includes it' do
175
+ expect(model.attribute_set[:test]).to be_instance_of(Virtus::Attribute)
176
+ end
177
+
178
+ it_behaves_like 'an object with string attribute' do
179
+ subject { model.new }
180
+ end
181
+ end
182
+
183
+ context 'included in the class' do
184
+ it_behaves_like 'an object with string attribute' do
185
+ subject { model.new.extend(mod) }
186
+ end
187
+ end
188
+ end
189
+
190
+ context 'with an instance' do
191
+ subject { model.new }
192
+
193
+ let(:model) { Class.new }
194
+
195
+ before do
196
+ subject.extend(Virtus)
197
+ subject.attribute(:test, String)
198
+ end
199
+
200
+ it_behaves_like 'an object with string attribute'
201
+ end
202
+
203
+ context 'using custom module' do
204
+ subject { model.new }
205
+
206
+ let(:model) {
207
+ Class.new {
208
+ include Virtus.model { |config| config.coerce = false }
209
+
210
+ attribute :test, String
211
+ }
212
+ }
213
+
214
+ it { should respond_to(:test) }
215
+ it { should respond_to(:test=) }
216
+
217
+ it 'writes and reads attributes' do
218
+ subject.test = :foo
219
+ expect(subject.test).to be(:foo)
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus, '#attributes' do
4
+
5
+ share_examples_for 'attribute hash' do
6
+ it 'includes all attributes' do
7
+ subject.attributes = { :test => 'Hello World', :test_priv => 'Yo' }
8
+
9
+ expect(subject.attributes).to eql(:test => 'Hello World')
10
+ end
11
+ end
12
+
13
+ context 'with a class' do
14
+ let(:model) {
15
+ Class.new {
16
+ include Virtus
17
+
18
+ attribute :test, String
19
+ attribute :test_priv, String, :reader => :private
20
+ }
21
+ }
22
+
23
+ it_behaves_like 'attribute hash' do
24
+ subject { model.new }
25
+ end
26
+ end
27
+
28
+ context 'with an instance' do
29
+ subject { model.new }
30
+
31
+ let(:model) { Class.new }
32
+
33
+ before do
34
+ subject.extend(Virtus)
35
+ subject.attribute :test, String
36
+ subject.attribute :test_priv, String, :reader => :private
37
+ end
38
+
39
+ it_behaves_like 'attribute hash'
40
+ end
41
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus, '#attributes=' do
4
+
5
+ share_examples_for 'mass-assignment' do
6
+ it 'allows writing known attributes' do
7
+ subject.attributes = { :test => 'Hello World' }
8
+
9
+ expect(subject.test).to eql('Hello World')
10
+ end
11
+
12
+ it 'skips writing unknown attributes' do
13
+ subject.attributes = { :test => 'Hello World', :nothere => 'boom!' }
14
+
15
+ expect(subject.test).to eql('Hello World')
16
+ end
17
+ end
18
+
19
+ context 'with a class' do
20
+ let(:model) {
21
+ Class.new {
22
+ include Virtus
23
+
24
+ attribute :test, String
25
+ }
26
+ }
27
+
28
+ it_behaves_like 'mass-assignment' do
29
+ subject { model.new }
30
+ end
31
+
32
+ it 'raises when attributes is not hash-like object' do
33
+ expect { model.new('not a hash, really') }.to raise_error(
34
+ NoMethodError, 'Expected "not a hash, really" to respond to #to_hash'
35
+ )
36
+ end
37
+ end
38
+
39
+ context 'with an instance' do
40
+ subject { model.new }
41
+
42
+ let(:model) { Class.new }
43
+
44
+ before do
45
+ subject.extend(Virtus)
46
+ subject.attribute :test, String
47
+ end
48
+
49
+ it_behaves_like 'mass-assignment'
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus, '.new' do
4
+ let(:model) {
5
+ Class.new {
6
+ include Virtus
7
+
8
+ attribute :id, Integer
9
+ attribute :name, String, :default => 'John Doe'
10
+ attribute :email, String, :default => 'john@doe.com', :lazy => true, :writer => :private
11
+ }
12
+ }
13
+
14
+ context 'without attribute hash' do
15
+ subject { model.new }
16
+
17
+ it 'sets default values for non-lazy attributes' do
18
+ expect(subject.instance_variable_get('@name')).to eql('John Doe')
19
+ end
20
+
21
+ it 'skips setting default values for lazy attributes' do
22
+ expect(subject.instance_variable_get('@email')).to be(nil)
23
+ end
24
+ end
25
+
26
+ context 'with attribute hash' do
27
+ subject { model.new(:id => 1, :name => 'Jane Doe') }
28
+
29
+ it 'sets attributes with public writers' do
30
+ expect(subject.id).to be(1)
31
+ expect(subject.name).to eql('Jane Doe')
32
+ end
33
+
34
+ it 'skips setting attributes with private writers' do
35
+ expect(subject.instance_variable_get('@email')).to be(nil)
36
+ end
37
+ end
38
+
39
+ end