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
@@ -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