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
data/TODO.md ADDED
@@ -0,0 +1,6 @@
1
+ 1.0.0.rc ROADMAP:
2
+
3
+ - Refactor to use soon-to-be-extracted axiom-types
4
+ - Add ability to pass in custom reader/writer *objects*
5
+ - Refactor to use extracted equalizer gem
6
+ - Tune Adamantium usage to memoize common methods in Attribute
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 18
3
- total_score: 340
2
+ threshold: 13
3
+ total_score: 321
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 18.2
2
+ threshold: 21.4
@@ -1,3 +1,14 @@
1
1
  ---
2
2
  name: virtus
3
- namespace: Virtus
3
+ namespace:
4
+ - 'Virtus::Attribute'
5
+ - 'Virtus::AttributeSet'
6
+ - 'Virtus::ClassInclusions'
7
+ - 'Virtus::ClassMethods'
8
+ - 'Virtus::Configuration'
9
+ - 'Virtus::ConstMissingExtensions'
10
+ - 'Virtus::Extensions'
11
+ - 'Virtus::InstanceMethods'
12
+ - 'Virtus::ModuleBuilder'
13
+ - 'Virtus::ModuleExtensions'
14
+ - 'Virtus::ValueObject'
@@ -1,105 +1,96 @@
1
1
  ---
2
- UncommunicativeParameterName:
3
- accept: []
2
+ Attribute:
3
+ enabled: true
4
4
  exclude: []
5
+ BooleanParameter:
5
6
  enabled: true
6
- reject:
7
- - !ruby/regexp /^.$/
8
- - !ruby/regexp /[0-9]$/
9
- - !ruby/regexp /[A-Z]/
10
- LargeClass:
11
- max_methods: 14
12
7
  exclude: []
8
+ ClassVariable:
13
9
  enabled: true
14
- max_instance_variables: 8
15
- UncommunicativeMethodName:
16
- accept: []
17
10
  exclude: []
11
+ ControlParameter:
18
12
  enabled: true
19
- reject:
20
- - !ruby/regexp /^[a-z]$/
21
- - !ruby/regexp /[0-9]$/
22
- - !ruby/regexp /[A-Z]/
23
- LongParameterList:
24
- max_params: 3
25
13
  exclude: []
14
+ DataClump:
26
15
  enabled: true
27
- overrides: {}
16
+ exclude: []
17
+ max_copies: 2
18
+ min_clump_size: 2
19
+ DuplicateMethodCall:
20
+ enabled: false
28
21
  FeatureEnvy:
29
- exclude: [
30
- Virtus::Attribute::Boolean#value_coerced?,
31
- Virtus::ClassMethods#build_attribute,
32
- Virtus::Coercion::TimeCoercions#to_string,
33
- Virtus::Coercion::TimeCoercions#coerce_with_method,
34
- Virtus::TypeLookup#determine_type_from_primitive,
35
- Virtus::ValueObject::ClassMethods#attribute
36
- ]
37
22
  enabled: true
38
- ClassVariable:
39
23
  exclude: []
24
+ IrresponsibleModule:
40
25
  enabled: true
41
- BooleanParameter:
42
26
  exclude: []
27
+ LongParameterList:
43
28
  enabled: true
44
- IrresponsibleModule:
45
29
  exclude: []
30
+ max_params: 2
31
+ LongYieldList:
46
32
  enabled: true
47
- UncommunicativeModuleName:
48
- accept: []
49
33
  exclude: []
50
- enabled: true
51
- reject:
52
- - !ruby/regexp /^.$/
53
- - !ruby/regexp /[0-9]$/
34
+ max_params: 2
54
35
  NestedIterators:
36
+ enabled: true
37
+ max_allowed_nesting: 1
55
38
  ignore_iterators: []
56
39
  exclude: []
40
+ NilCheck:
57
41
  enabled: true
58
- max_allowed_nesting: 2
59
- LongMethod:
60
- max_statements: 6
61
42
  exclude: []
43
+ RepeatedConditional:
62
44
  enabled: true
63
- Duplication:
64
- allow_calls: []
65
- exclude: [
66
- Virtus::Attribute::DefaultValue#evaluate
67
- ]
45
+ exclude: []
46
+ max_ifs: 1
47
+ TooManyInstanceVariables:
68
48
  enabled: true
69
- max_calls: 1
70
- UtilityFunction:
71
- max_helper_calls: 1
72
- exclude: [
73
- Virtus::Attribute::Boolean#value_coerced?,
74
- Virtus::ClassMethods#build_attribute
75
- ]
49
+ exclude: []
50
+ max_instance_variables: 3
51
+ TooManyMethods:
76
52
  enabled: true
77
- Attribute:
78
53
  exclude: []
79
- enabled: false
80
- UncommunicativeVariableName:
81
- accept: []
54
+ max_methods: 10
55
+ TooManyStatements:
56
+ enabled: true
82
57
  exclude: []
58
+ max_statements: 4
59
+ UncommunicativeMethodName:
83
60
  enabled: true
61
+ exclude: []
84
62
  reject:
85
- - !ruby/regexp /^.$/
63
+ - !ruby/regexp /^[a-z]$/
86
64
  - !ruby/regexp /[0-9]$/
87
65
  - !ruby/regexp /[A-Z]/
88
- SimulatedPolymorphism:
66
+ accept: []
67
+ UncommunicativeModuleName:
68
+ enabled: true
89
69
  exclude: []
70
+ reject:
71
+ - !ruby/regexp /^.$/
72
+ - !ruby/regexp /[0-9]$/
73
+ accept: []
74
+ UncommunicativeParameterName:
90
75
  enabled: true
91
- max_ifs: 1
92
- DataClump:
93
76
  exclude: []
77
+ reject:
78
+ - !ruby/regexp /^.$/
79
+ - !ruby/regexp /[0-9]$/
80
+ - !ruby/regexp /[A-Z]/
81
+ accept: []
82
+ UncommunicativeVariableName:
94
83
  enabled: true
95
- max_copies: 2
96
- min_clump_size: 2
97
- ControlCouple:
98
- exclude: [
99
- 'Virtus::InstanceMethods#initialize'
100
- ]
84
+ exclude: []
85
+ reject:
86
+ - !ruby/regexp /^.$/
87
+ - !ruby/regexp /[0-9]$/
88
+ - !ruby/regexp /[A-Z]/
89
+ accept: []
90
+ UnusedParameters:
101
91
  enabled: true
102
- LongYieldList:
103
- max_params: 1
104
92
  exclude: []
93
+ UtilityFunction:
105
94
  enabled: true
95
+ exclude: []
96
+ max_helper_calls: 0
@@ -1,10 +1,4 @@
1
- require 'set'
2
- require 'date'
3
- require 'time'
4
- require 'bigdecimal'
5
- require 'bigdecimal/util'
6
1
  require 'ostruct'
7
- require 'backports'
8
2
 
9
3
  # Base module which adds Attribute API to your classes
10
4
  module Virtus
@@ -18,7 +12,7 @@ module Virtus
18
12
 
19
13
  # Extends base class or a module with virtus methods
20
14
  #
21
- # @param [Class] descendant
15
+ # @param [Object] object
22
16
  #
23
17
  # @return [undefined]
24
18
  #
@@ -26,8 +20,10 @@ module Virtus
26
20
  def self.included(object)
27
21
  super
28
22
  if Class === object
23
+ Virtus.warn("including Virtus module is deprecated. Use 'include Virtus.model' instead #{caller.first}")
29
24
  object.send(:include, ClassInclusions)
30
25
  else
26
+ Virtus.warn("including Virtus module is deprecated. Use 'include Virtus.module' instead #{caller.first}")
31
27
  object.extend(ModuleExtensions)
32
28
  end
33
29
  end
@@ -41,22 +37,135 @@ module Virtus
41
37
  #
42
38
  # @api private
43
39
  def self.extended(object)
40
+ Virtus.warn("extending with Virtus module is deprecated. Use 'extend(Virtus.model)' instead #{caller.first}")
44
41
  object.extend(Extensions)
45
42
  end
46
43
  private_class_method :extended
47
44
 
45
+ # Sets the global coercer configuration
46
+ #
47
+ # @example
48
+ # Virtus.coercer do |config|
49
+ # config.string.boolean_map = { true => '1', false => '0' }
50
+ # end
51
+ #
52
+ # @return [Coercible::Coercer]
53
+ #
54
+ # @api public
55
+ def self.coercer(&block)
56
+ configuration.coercer(&block)
57
+ end
58
+
59
+ # Sets the global coercion configuration value
60
+ #
61
+ # @param [Boolean] value
62
+ #
63
+ # @return [Virtus]
64
+ #
65
+ # @api public
66
+ def self.coerce=(value)
67
+ configuration.coerce = value
68
+ self
69
+ end
70
+
71
+ # Returns the global coercion setting
72
+ #
73
+ # @return [Boolean]
74
+ #
75
+ # @api public
76
+ def self.coerce
77
+ configuration.coerce
78
+ end
79
+
80
+ # Provides access to the global Virtus configuration
81
+ #
82
+ # @example
83
+ # Virtus.config do |config|
84
+ # config.coerce = false
85
+ # end
86
+ #
87
+ # @return [Configuration]
88
+ #
89
+ # @api public
90
+ def self.config(&block)
91
+ configuration.call(&block)
92
+ end
93
+
94
+ # Provides access to the Virtus module builder
95
+ # see Virtus::ModuleBuilder
96
+ #
97
+ # @example
98
+ # MyVirtusModule = Virtus.module { |mod|
99
+ # mod.coerce = true
100
+ # mod.string.boolean_map = { 'yup' => true, 'nope' => false }
101
+ # }
102
+ #
103
+ # class Book
104
+ # include MyVirtusModule
105
+ #
106
+ # attribute :published, Boolean
107
+ # end
108
+ #
109
+ # # This could be made more succinct as well
110
+ # class OtherBook
111
+ # include Virtus.module { |m| m.coerce = false }
112
+ # end
113
+ #
114
+ # @return [Module]
115
+ #
116
+ # @api public
117
+ def self.model(options = {}, &block)
118
+ ModelExtensionBuilder.call(options, &block)
119
+ end
120
+
121
+ # Builds a module for...modules
122
+ #
123
+ # @api public
124
+ def self.module(options = {}, &block)
125
+ ModuleExtensionBuilder.call(options, &block)
126
+ end
127
+
128
+ # Builds a module for value object models
129
+ #
130
+ # @api public
131
+ def self.value_object(options = {}, &block)
132
+ ValueObjectExtensionBuilder.call(options, &block)
133
+ end
134
+
135
+ # Global configuration instance
136
+ #
137
+ # @ return [Configuration]
138
+ #
139
+ # @api private
140
+ def self.configuration
141
+ @configuration ||= Configuration.new
142
+ end
143
+
144
+ # @api private
145
+ def self.warn(msg)
146
+ Kernel.warn(msg)
147
+ end
148
+
48
149
  end # module Virtus
49
150
 
50
151
  require 'descendants_tracker'
152
+ require 'equalizer'
153
+ require 'axiom-types'
154
+ require 'coercible'
51
155
 
52
- require 'virtus/support/type_lookup'
53
- require 'virtus/support/options'
54
156
  require 'virtus/support/equalizer'
157
+ require 'virtus/support/options'
158
+ require 'virtus/support/type_lookup'
55
159
 
160
+ require 'virtus/model'
56
161
  require 'virtus/extensions'
162
+ require 'virtus/const_missing_extensions'
57
163
  require 'virtus/class_inclusions'
58
164
  require 'virtus/module_extensions'
59
165
 
166
+ require 'virtus/configuration'
167
+ require 'virtus/module_builder'
168
+
60
169
  require 'virtus/class_methods'
61
170
  require 'virtus/instance_methods'
62
171
 
@@ -64,45 +173,20 @@ require 'virtus/value_object'
64
173
 
65
174
  require 'virtus/attribute_set'
66
175
 
67
- require 'virtus/coercion'
68
- require 'virtus/coercion/object'
69
- require 'virtus/coercion/numeric'
70
- require 'virtus/coercion/integer'
71
- require 'virtus/coercion/float'
72
- require 'virtus/coercion/decimal'
73
- require 'virtus/coercion/false_class'
74
- require 'virtus/coercion/true_class'
75
- require 'virtus/coercion/hash'
76
- require 'virtus/coercion/array'
77
- require 'virtus/coercion/time_coercions'
78
- require 'virtus/coercion/date'
79
- require 'virtus/coercion/date_time'
80
- require 'virtus/coercion/time'
81
- require 'virtus/coercion/string'
82
- require 'virtus/coercion/symbol'
83
-
84
176
  require 'virtus/attribute/default_value'
85
177
  require 'virtus/attribute/default_value/from_clonable'
86
178
  require 'virtus/attribute/default_value/from_callable'
87
179
  require 'virtus/attribute/default_value/from_symbol'
88
180
 
89
181
  require 'virtus/attribute'
90
- require 'virtus/attribute/object'
91
- require 'virtus/attribute/class'
92
- require 'virtus/attribute/collection'
93
- require 'virtus/attribute/array'
94
- require 'virtus/attribute/set'
182
+ require 'virtus/attribute/builder'
183
+ require 'virtus/attribute/coercer'
184
+ require 'virtus/attribute/accessor'
185
+ require 'virtus/attribute/coercible'
186
+ require 'virtus/attribute/strict'
187
+ require 'virtus/attribute/lazy_default'
188
+
95
189
  require 'virtus/attribute/boolean'
96
- require 'virtus/attribute/date'
97
- require 'virtus/attribute/date_time'
98
- require 'virtus/attribute/numeric'
99
- require 'virtus/attribute/decimal'
100
- require 'virtus/attribute/float'
190
+ require 'virtus/attribute/collection'
101
191
  require 'virtus/attribute/hash'
102
- require 'virtus/attribute/integer'
103
- require 'virtus/attribute/symbol'
104
- require 'virtus/attribute/string'
105
- require 'virtus/attribute/time'
106
192
  require 'virtus/attribute/embedded_value'
107
- require 'virtus/attribute/embedded_value/from_struct'
108
- require 'virtus/attribute/embedded_value/from_open_struct'
@@ -1,49 +1,28 @@
1
1
  module Virtus
2
2
 
3
- # Abstract class implementing base API for attribute types
4
- #
5
- # @abstract
6
3
  class Attribute
7
- extend DescendantsTracker
8
- extend TypeLookup
9
- extend Options
10
- include Equalizer.new(inspect) << :name << :options
4
+ extend DescendantsTracker, Options, TypeLookup
11
5
 
12
- accept_options :primitive, :accessor, :reader,
13
- :writer, :coercion_method, :default
6
+ include ::Equalizer.new(:type, :options)
14
7
 
8
+ accept_options :primitive, :accessor, :default, :lazy, :strict
9
+
10
+ strict false
15
11
  accessor :public
16
12
 
17
- # Returns name of the attribute
18
- #
19
- # @example
20
- # User.attributes[:age].name # => :age
13
+ # @see Virtus.coerce
21
14
  #
22
- # @return [Symbol]
15
+ # @deprecated
23
16
  #
24
17
  # @api public
25
- attr_reader :name
26
-
27
- # Returns options hash for the attribute
28
- #
29
- # @return [Hash]
30
- #
31
- # @api private
32
- attr_reader :options
18
+ def self.coerce(value = Undefined)
19
+ Virtus.warn "#{self}.coerce is deprecated and will be removed in 1.0.0. Use Virtus.coerce instead: ##{caller.first}"
20
+ return Virtus.coerce if value.equal?(Undefined)
21
+ Virtus.coerce = value
22
+ self
23
+ end
33
24
 
34
- # Returns method name that should be used for coerceing
35
- #
36
- # @return [Symbol]
37
- #
38
- # @api private
39
- attr_reader :coercion_method
40
-
41
- # Returns default value
42
- #
43
- # @return [Object]
44
- #
45
- # @api private
46
- attr_reader :default
25
+ attr_reader :type, :primitive, :options, :default_value, :coercer
47
26
 
48
27
  # Builds an attribute instance
49
28
  #
@@ -59,54 +38,25 @@ module Virtus
59
38
  # @return [Attribute]
60
39
  #
61
40
  # @api private
62
- def self.build(name, type = Object, options = {})
63
- attribute_class = determine_type(type) or
64
- raise ArgumentError, "#{type.inspect} does not map to an attribute type"
65
- attribute_options = attribute_class.merge_options(type, options)
66
- attribute_class.new(name, attribute_options)
41
+ def self.build(type, options = {})
42
+ Builder.call(type, options)
67
43
  end
68
44
 
69
- # Determine attribute type based on class or name
70
- #
71
- # Returns Attribute::EmbeddedValue if a virtus class is passed
72
- #
73
- # @example
74
- # address_class = Class.new { include Virtus }
75
- # Virtus::Attribute.determine_type(address_class) # => Virtus::Attribute::EmbeddedValue
76
- #
77
- # @see Virtus::Support::TypeLookup.determine_type
78
- #
79
- # @return [Class]
80
- #
81
- # @api public
82
- def self.determine_type(class_or_name)
83
- case class_or_name
84
- when ::Class
85
- Attribute::EmbeddedValue.determine_type(class_or_name) || super
86
- when ::String
87
- super
88
- when ::Enumerable
89
- super(class_or_name.class)
90
- else
91
- super
92
- end
45
+ # @api private
46
+ def self.new(*args)
47
+ attribute = super
48
+ yield(attribute)
49
+ attribute.finalize
93
50
  end
94
51
 
95
- # A hook for Attributes to update options based on the type from the caller
96
- #
97
- # @param [Object] type
98
- # The raw type, typically given by the caller of ClassMethods#attribute
99
- # @param [Hash] options
100
- # Attribute configuration options
101
- #
102
- # @return [Hash]
103
- # New Hash instance, potentially updated with information from the args
104
- #
105
52
  # @api private
106
- #
107
- # @todo add type arg to Attribute#initialize signature and handle there?
108
- def self.merge_options(type, options)
109
- options
53
+ def self.build_type(options)
54
+ Axiom::Types.infer(options[:primitive])
55
+ end
56
+
57
+ # @api private
58
+ def self.merge_options!(*)
59
+ # noop
110
60
  end
111
61
 
112
62
  # Initializes an attribute instance
@@ -120,192 +70,54 @@ module Virtus
120
70
  # @return [undefined]
121
71
  #
122
72
  # @api private
123
- def initialize(name, options = {})
124
- @name = name.to_sym
125
- @options = self.class.options.merge(options).freeze
126
- @instance_variable_name = "@#{@name}".to_sym
127
- @primitive = @options.fetch(:primitive)
128
- @coercion_method = @options.fetch(:coercion_method)
129
- @default = DefaultValue.build(@options[:default])
130
- initialize_visibility
131
- end
132
-
133
- # Returns a concise string representation of the attribute instance
134
- #
135
- # @example
136
- # attribute = Virtus::Attribute::String.new(:name)
137
- # attribute.inspect # => #<Virtus::Attribute::String @name=:name>
138
- #
139
- # @return [String]
140
- #
141
- # @api public
142
- def inspect
143
- "#<#{self.class.inspect} @name=#{name.inspect}>"
73
+ def initialize(type, options)
74
+ @type = type
75
+ @primitive = type.primitive
76
+ @options = options
77
+ @default_value = options.fetch(:default_value)
78
+ @coercer = options.fetch(:coercer)
144
79
  end
145
80
 
146
- # Returns value of an attribute for the given instance
147
- #
148
- # Sets the default value if an ivar is not set and default
149
- # value is configured
150
- #
151
- # @example
152
- # attribute.get(instance) # => value
153
- #
154
- # @return [Object]
155
- # value of an attribute
156
- #
157
81
  # @api public
158
- def get(instance)
159
- if instance.instance_variable_defined?(@instance_variable_name)
160
- get!(instance)
161
- else
162
- value = default.call(instance, self)
163
- set!(instance, value)
164
- value
165
- end
82
+ def coerce(value)
83
+ coercer.call(value)
166
84
  end
167
85
 
168
- # Returns the instance variable of the attribute
169
- #
170
- # @example
171
- # attribute.get!(instance) # => value
172
- #
173
- # @return [Object]
174
- # value of an attribute
175
- #
176
86
  # @api public
177
- def get!(instance)
178
- instance.instance_variable_get(@instance_variable_name)
87
+ def value_coerced?(value)
88
+ coercer.success?(primitive, value)
179
89
  end
180
90
 
181
- # Sets the value on the instance
182
- #
183
- # @example
184
- # attribute.set(instance, value) # => value
91
+ # Return if the attribute is coercible
185
92
  #
186
- # @return [self]
93
+ # @return [Boolean]
187
94
  #
188
95
  # @api public
189
- def set(instance, value)
190
- set!(instance, coerce(value))
96
+ def coercible?
97
+ kind_of?(Coercible)
191
98
  end
192
99
 
193
- # Sets instance variable of the attribute
194
- #
195
- # @example
196
- # attribute.set!(instance, value) # => value
197
- #
198
- # @return [self]
199
- #
200
100
  # @api public
201
- def set!(instance, value)
202
- instance.instance_variable_set(@instance_variable_name, value)
203
- self
101
+ def lazy?
102
+ kind_of?(LazyDefault)
204
103
  end
205
104
 
206
- # Converts the given value to the primitive type
207
- #
208
- # @example
209
- # attribute.coerce(value) # => primitive_value
210
- #
211
- # @param [Object] value
212
- # the value
213
- #
214
- # @return [Object]
215
- # nil, original value or value converted to the primitive type
216
- #
217
105
  # @api public
218
- def coerce(value)
219
- Coercion[value.class].public_send(coercion_method, value)
106
+ def strict?
107
+ kind_of?(Strict)
220
108
  end
221
109
 
222
- # Is the given value coerced into the target type for this attribute?
223
- #
224
- # @example
225
- # string_attribute = Virtus::Attribute::String.new(:str)
226
- # string_attribute.value_coerced?('foo') # => true
227
- # string_attribute.value_coerced?(:foo) # => false
228
- # integer_attribute = Virtus::Attribute::Integer.new(:integer)
229
- # integer_attribute.value_coerced?(5) # => true
230
- # integer_attribute.value_coerced?('5') # => false
231
- # date_attribute = Virtus::Attribute::Date.new(:date)
232
- # date_attribute.value_coerced?('2011-12-31') # => false
233
- # date_attribute.value_coerced?(Date.today) # => true
234
- #
235
- # @return [Boolean]
236
- #
237
110
  # @api private
238
- def value_coerced?(value)
239
- @primitive === value
111
+ def define_accessor_methods(attribute_set)
112
+ attribute_set.define_reader_method(self, name, options[:reader])
113
+ attribute_set.define_writer_method(self, "#{name}=", options[:writer])
240
114
  end
241
115
 
242
- # Define reader and writer methods for an Attribute
243
- #
244
- # @param [Attribute] attribute
245
- #
246
- # @return [self]
247
- #
248
- # @api private
249
- def define_accessor_methods(mod)
250
- define_reader_method(mod)
251
- define_writer_method(mod)
252
- self
253
- end
254
-
255
- # Creates an attribute reader method
256
- #
257
- # @param [Module] mod
258
- #
259
- # @return [self]
260
- #
261
116
  # @api private
262
- def define_reader_method(mod)
263
- mod.define_reader_method(self, name, @reader_visibility)
264
- self
265
- end
266
-
267
- # Creates an attribute writer method
268
- #
269
- # @param [Module] mod
270
- #
271
- # @return [self]
272
- #
273
- # @api private
274
- def define_writer_method(mod)
275
- mod.define_writer_method(self, "#{name}=".to_sym, @writer_visibility)
276
- self
277
- end
278
-
279
- # Returns a Boolean indicating whether the reader method is public
280
- #
281
- # @return [Boolean]
282
- #
283
- # @api private
284
- def public_reader?
285
- @reader_visibility == :public
286
- end
287
-
288
- # Returns a Boolean indicating whether the writer method is public
289
- #
290
- # @return [Boolean]
291
- #
292
- # @api private
293
- def public_writer?
294
- @writer_visibility == :public
295
- end
296
-
297
- private
298
-
299
- # Initialize visibility of reader/write methods based on the options hash
300
- #
301
- # @return [undefined]
302
- #
303
- # @api private
304
- def initialize_visibility
305
- default_accessor = @options.fetch(:accessor)
306
- @reader_visibility = @options.fetch(:reader, default_accessor)
307
- @writer_visibility = @options.fetch(:writer, default_accessor)
117
+ def finalize
118
+ freeze
308
119
  end
309
120
 
310
121
  end # class Attribute
122
+
311
123
  end # module Virtus