virtus 0.5.5 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,68 @@
1
+ module Virtus
2
+
3
+ module Model
4
+
5
+ # @api private
6
+ def self.included(descendant)
7
+ super
8
+ descendant.send(:include, ClassInclusions) if Class === descendant
9
+ end
10
+
11
+ # @api private
12
+ def self.extended(descendant)
13
+ super
14
+ descendant.extend(Extensions)
15
+ end
16
+
17
+ module Core
18
+
19
+ # @api private
20
+ def self.included(descendant)
21
+ super
22
+ descendant.extend(ClassMethods)
23
+ descendant.send(:include, ClassInclusions::Methods)
24
+ descendant.send(:include, InstanceMethods)
25
+ end
26
+ private_class_method :included
27
+
28
+ # @api private
29
+ def self.extended(descendant)
30
+ super
31
+ descendant.extend(Extensions::Methods)
32
+ descendant.extend(InstanceMethods)
33
+ end
34
+ private_class_method :included
35
+
36
+ end # Core
37
+
38
+ module Constructor
39
+
40
+ # @api private
41
+ def self.included(descendant)
42
+ super
43
+ descendant.send(:include, InstanceMethods::Constructor)
44
+ end
45
+ private_class_method :included
46
+
47
+ end # Constructor
48
+
49
+ module MassAssignment
50
+
51
+ # @api private
52
+ def self.included(descendant)
53
+ super
54
+ descendant.send(:include, InstanceMethods::MassAssignment)
55
+ end
56
+ private_class_method :included
57
+
58
+ # @api private
59
+ def self.extended(descendant)
60
+ super
61
+ descendant.extend(InstanceMethods::MassAssignment)
62
+ end
63
+ private_class_method :included
64
+
65
+ end # MassAssignment
66
+
67
+ end # Model
68
+ end # Virtus
@@ -0,0 +1,184 @@
1
+ module Virtus
2
+
3
+ # Class to build a Virtus module with it's own configuration
4
+ #
5
+ # This allows for individual Virtus modules to be included in
6
+ # classes and not impacted by the global Virtus configuration,
7
+ # which is implemented using Virtus::Configuration.
8
+ #
9
+ # @private
10
+ class ExtensionBuilder
11
+
12
+ # Return module
13
+ #
14
+ # @return [Module]
15
+ #
16
+ # @api private
17
+ attr_reader :module
18
+
19
+ # Return configuration
20
+ #
21
+ # @return [Configuration]
22
+ #
23
+ # @api private
24
+ attr_reader :configuration
25
+
26
+ # Builds a new Virtus module
27
+ #
28
+ # The block is passed to Virtus::Configuration
29
+ #
30
+ # @example
31
+ # ModuleBuilder.call do |config|
32
+ # # config settings
33
+ # end
34
+ #
35
+ # @return [Module]
36
+ #
37
+ # @api public
38
+ def self.call(options = {}, &block)
39
+ config = Configuration.build(&block)
40
+ options.each { |key, value| config.public_send("#{key}=", value) }
41
+ builder = new(config)
42
+ builder.add_included_hook
43
+ builder.add_extended_hook
44
+ builder.module
45
+ end
46
+
47
+ # Initializes a new ModuleBuilder
48
+ #
49
+ # @param [Configuration] configuration
50
+ #
51
+ # @param [Module] mod
52
+ #
53
+ # @return [undefined]
54
+ #
55
+ # @api private
56
+ def initialize(configuration, mod = Module.new)
57
+ @configuration = configuration
58
+ @module = mod
59
+ end
60
+
61
+ # Adds the .included hook to the anonymous module which then defines the
62
+ # .attribute method to override the default.
63
+ #
64
+ # @return [Module]
65
+ #
66
+ # @api private
67
+ def add_included_hook
68
+ attribute_proc = attribute_method(configuration)
69
+ constructor = configuration.constructor
70
+ mass_assignment = configuration.mass_assignment
71
+ extensions = core_extensions
72
+ inclusions = core_inclusions
73
+
74
+ self.module.define_singleton_method :included do |object|
75
+ super(object)
76
+ extensions.each { |mod| object.extend(mod) }
77
+ inclusions.each { |mod| object.send(:include, mod) }
78
+ object.send(:include, Model::Constructor) if constructor
79
+ object.send(:include, Model::MassAssignment) if mass_assignment
80
+ object.send(:define_singleton_method, :attribute, attribute_proc)
81
+ end
82
+ end
83
+
84
+ # @api private
85
+ def add_extended_hook
86
+ attribute_proc = attribute_method(configuration)
87
+ mass_assignment = configuration.mass_assignment
88
+ extensions = core_inclusions + core_extensions
89
+
90
+ self.module.define_singleton_method :extended do |object|
91
+ super(object)
92
+ extensions.each { |mod| object.extend(mod) }
93
+ object.extend(Model::MassAssignment) if mass_assignment
94
+ object.send :define_singleton_method, :attribute, attribute_proc
95
+ end
96
+ end
97
+
98
+ # Wrapper for the attribute method that is used in .add_included_hook
99
+ # The coercer is passed in the unused key :configured_coercer to allow the
100
+ # property encapsulation by Virtus::Attribute::Coercer, where the
101
+ # coercion method is known.
102
+ #
103
+ # @return [Proc(lambda)]
104
+ #
105
+ # @api private
106
+ def attribute_method(configuration)
107
+ module_options = self.module_options
108
+
109
+ lambda do |name, type, options = {}|
110
+ super(name, type, module_options.merge(options))
111
+ end
112
+ end
113
+
114
+ # @api private
115
+ def module_options
116
+ { :coerce => configuration.coerce,
117
+ :strict => configuration.strict,
118
+ :configured_coercer => configuration.coercer }
119
+ end
120
+
121
+ # @api private
122
+ def core_inclusions
123
+ [Model::Core]
124
+ end
125
+
126
+ # @api private
127
+ def core_extensions
128
+ []
129
+ end
130
+
131
+ end # class ExtensionBuilder
132
+
133
+ # @private
134
+ class ModelExtensionBuilder < ExtensionBuilder
135
+ end # ModelExtensionBuilder
136
+
137
+ # @private
138
+ class ModuleExtensionBuilder < ExtensionBuilder
139
+
140
+ # @api private
141
+ def add_included_hook
142
+ attribute_proc = attribute_method(configuration)
143
+ inclusions = core_inclusions
144
+
145
+ inclusions << Model::Constructor if configuration.constructor
146
+ inclusions << Model::MassAssignment if configuration.mass_assignment
147
+
148
+ self.module.define_singleton_method :included do |object|
149
+ super(object)
150
+ object.extend(ModuleExtensions)
151
+ object.instance_variable_set('@inclusions', inclusions)
152
+ object.send(:define_singleton_method, :attribute, attribute_proc)
153
+ end
154
+ end
155
+
156
+ end # ModuleExtensionBuilder
157
+
158
+ # @private
159
+ class ValueObjectExtensionBuilder < ExtensionBuilder
160
+
161
+ # @api private
162
+ def initialize(configuration, mod = Module.new)
163
+ super
164
+ @configuration.constructor = true
165
+ end
166
+
167
+ # @api private
168
+ def module_options
169
+ super.update(:writer => :private)
170
+ end
171
+
172
+ # @api private
173
+ def core_inclusions
174
+ super << ValueObject::AllowedWriterMethods << ValueObject::InstanceMethods
175
+ end
176
+
177
+ # @api private
178
+ def core_extensions
179
+ super << ValueObject::AllowedWriterMethods
180
+ end
181
+
182
+ end # ValueObjectBuilder
183
+
184
+ end # module Virtus
@@ -2,7 +2,21 @@ module Virtus
2
2
 
3
3
  # Virtus module that can define attributes for later inclusion
4
4
  #
5
+ # @private
5
6
  module ModuleExtensions
7
+ include ConstMissingExtensions
8
+
9
+ # @api private
10
+ def self.extended(mod)
11
+ super
12
+ setup(mod)
13
+ end
14
+
15
+ # @api private
16
+ def self.setup(mod, inclusions = [Model], attribute_definitions = [])
17
+ mod.instance_variable_set('@inclusions', inclusions)
18
+ mod.instance_variable_set('@attribute_definitions', attribute_definitions)
19
+ end
6
20
 
7
21
  # Define an attribute in the module
8
22
  #
@@ -11,12 +25,12 @@ module Virtus
11
25
  # @return [self]
12
26
  #
13
27
  # @api private
14
- def attribute(*args)
15
- attribute_definitions << args
28
+ def attribute(name, type, options = {})
29
+ @attribute_definitions << [name, type, options]
16
30
  self
17
31
  end
18
32
 
19
- private
33
+ private
20
34
 
21
35
  # Extend an object with Virtus methods and define attributes
22
36
  #
@@ -27,8 +41,9 @@ module Virtus
27
41
  # @api private
28
42
  def extended(object)
29
43
  super
30
- object.extend(Virtus)
44
+ @inclusions.each { |mod| object.extend(mod) }
31
45
  define_attributes(object)
46
+ object.set_default_attributes
32
47
  end
33
48
 
34
49
  # Extend a class with Virtus methods and define attributes
@@ -40,17 +55,14 @@ module Virtus
40
55
  # @api private
41
56
  def included(object)
42
57
  super
43
- object.module_eval { include Virtus }
44
- define_attributes(object)
45
- end
46
58
 
47
- # Return attribute definitions
48
- #
49
- # @return [Array<Hash>]
50
- #
51
- # @api private
52
- def attribute_definitions
53
- @_attribute_definitions ||= []
59
+ if Class === object
60
+ @inclusions.each { |mod| object.send(:include, mod) }
61
+ define_attributes(object)
62
+ else
63
+ object.extend(ModuleExtensions)
64
+ ModuleExtensions.setup(object, @inclusions, @attribute_definitions)
65
+ end
54
66
  end
55
67
 
56
68
  # Define attributes on a class or instance
@@ -61,7 +73,7 @@ module Virtus
61
73
  #
62
74
  # @api private
63
75
  def define_attributes(object)
64
- attribute_definitions.each do |attribute_args|
76
+ @attribute_definitions.each do |attribute_args|
65
77
  object.attribute(*attribute_args)
66
78
  end
67
79
  end
@@ -105,7 +105,7 @@ module Virtus
105
105
  #
106
106
  # @api public
107
107
  def eql?(other)
108
- instance_of?(other.class) and cmp?(__method__, other)
108
+ instance_of?(other.class) && cmp?(__method__, other)
109
109
  end
110
110
 
111
111
  # Compare the object with other object for equivalency
@@ -120,8 +120,7 @@ module Virtus
120
120
  #
121
121
  # @api public
122
122
  def ==(other)
123
- return false unless self.class <=> other.class
124
- cmp?(__method__, other)
123
+ other.kind_of?(self.class) && cmp?(__method__, other)
125
124
  end
126
125
 
127
126
  end # module Methods
@@ -81,7 +81,7 @@ module Virtus
81
81
  # @api private
82
82
  def determine_type_from_primitive(primitive)
83
83
  type = nil
84
- descendants.reverse_each do |descendant|
84
+ descendants.select(&:primitive).reverse_each do |descendant|
85
85
  descendant_primitive = descendant.primitive
86
86
  next unless primitive <= descendant_primitive
87
87
  type = descendant if type.nil? or type.primitive > descendant_primitive
@@ -31,10 +31,13 @@ module Virtus
31
31
  #
32
32
  # @api private
33
33
  def self.included(base)
34
+ Virtus.warn "Virtus::ValueObject is deprecated and will be removed in 1.0.0 #{caller.first}"
35
+
34
36
  base.instance_eval do
35
37
  include ::Virtus
36
38
  include InstanceMethods
37
39
  extend ClassMethods
40
+ extend AllowedWriterMethods
38
41
  private :attributes=
39
42
  end
40
43
  end
@@ -43,19 +46,6 @@ module Virtus
43
46
 
44
47
  module InstanceMethods
45
48
 
46
- # the #get_attributes method accept a Proc object that will filter
47
- # out an attribute when the block returns false. the ValueObject
48
- # needs all the attributes, so we allow every attribute.
49
- FILTER_NONE = proc { true }
50
-
51
- def initialize(attributes = {})
52
- set_attributes(attributes)
53
- end
54
-
55
- def with(attribute_updates)
56
- self.class.new(get_attributes(&FILTER_NONE).merge(attribute_updates))
57
- end
58
-
59
49
  # ValueObjects are immutable and can't be cloned
60
50
  #
61
51
  # They always represent the same value
@@ -74,6 +64,22 @@ module Virtus
74
64
 
75
65
  end
76
66
 
67
+ module AllowedWriterMethods
68
+ # The list of writer methods that can be mass-assigned to in #attributes=
69
+ #
70
+ # @return [Set]
71
+ #
72
+ # @api private
73
+ def allowed_writer_methods
74
+ @allowed_writer_methods ||=
75
+ begin
76
+ allowed_writer_methods = super
77
+ allowed_writer_methods += attribute_set.map{|attr| "#{attr.name}="}
78
+ allowed_writer_methods.to_set.freeze
79
+ end
80
+ end
81
+ end
82
+
77
83
  module ClassMethods
78
84
 
79
85
  # Define an attribute on the receiver
@@ -94,10 +100,9 @@ module Virtus
94
100
  # @return [self]
95
101
  #
96
102
  # @api public
97
- def attribute(name, *args)
103
+ def attribute(name, type, options = {})
98
104
  equalizer << name
99
- options = args.last.kind_of?(Hash) ? args.pop : {}
100
- super name, *args << options.merge(:writer => :private)
105
+ super name, type, options.merge(:writer => :private)
101
106
  end
102
107
 
103
108
  # Define and include a module that provides Value Object semantics
@@ -116,26 +121,14 @@ module Virtus
116
121
  def equalizer
117
122
  @equalizer ||=
118
123
  begin
119
- equalizer = Equalizer.new(name || inspect)
124
+ equalizer = Virtus::Equalizer.new(name || inspect)
120
125
  include equalizer
121
126
  equalizer
122
127
  end
123
128
  end
124
129
 
125
- # The list of writer methods that can be mass-assigned to in #attributes=
126
- #
127
- # @return [Set]
128
- #
129
- # @api private
130
- def allowed_writer_methods
131
- @allowed_writer_methods ||=
132
- begin
133
- allowed_writer_methods = super
134
- allowed_writer_methods += attribute_set.map{|attr| "#{attr.name}="}
135
- allowed_writer_methods.to_set.freeze
136
- end
137
- end
138
-
139
130
  end # module ClassMethods
131
+
140
132
  end # module ValueObject
133
+
141
134
  end # module Virtus