sbf-dm-core 1.3.0.beta

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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +29 -0
  3. data/.document +5 -0
  4. data/.gitignore +44 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +468 -0
  7. data/.travis.yml +57 -0
  8. data/.yardopts +1 -0
  9. data/Gemfile +70 -0
  10. data/LICENSE +20 -0
  11. data/README.md +269 -0
  12. data/Rakefile +4 -0
  13. data/dm-core.gemspec +21 -0
  14. data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
  15. data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
  16. data/lib/dm-core/adapters.rb +249 -0
  17. data/lib/dm-core/associations/many_to_many.rb +477 -0
  18. data/lib/dm-core/associations/many_to_one.rb +282 -0
  19. data/lib/dm-core/associations/one_to_many.rb +332 -0
  20. data/lib/dm-core/associations/one_to_one.rb +84 -0
  21. data/lib/dm-core/associations/relationship.rb +650 -0
  22. data/lib/dm-core/backwards.rb +11 -0
  23. data/lib/dm-core/collection.rb +1486 -0
  24. data/lib/dm-core/core_ext/kernel.rb +21 -0
  25. data/lib/dm-core/core_ext/pathname.rb +4 -0
  26. data/lib/dm-core/core_ext/symbol.rb +10 -0
  27. data/lib/dm-core/identity_map.rb +6 -0
  28. data/lib/dm-core/model/hook.rb +99 -0
  29. data/lib/dm-core/model/is.rb +30 -0
  30. data/lib/dm-core/model/property.rb +244 -0
  31. data/lib/dm-core/model/relationship.rb +366 -0
  32. data/lib/dm-core/model/scope.rb +87 -0
  33. data/lib/dm-core/model.rb +876 -0
  34. data/lib/dm-core/property/binary.rb +19 -0
  35. data/lib/dm-core/property/boolean.rb +35 -0
  36. data/lib/dm-core/property/class.rb +23 -0
  37. data/lib/dm-core/property/date.rb +45 -0
  38. data/lib/dm-core/property/date_time.rb +44 -0
  39. data/lib/dm-core/property/decimal.rb +47 -0
  40. data/lib/dm-core/property/discriminator.rb +40 -0
  41. data/lib/dm-core/property/float.rb +27 -0
  42. data/lib/dm-core/property/integer.rb +32 -0
  43. data/lib/dm-core/property/invalid_value_error.rb +17 -0
  44. data/lib/dm-core/property/lookup.rb +26 -0
  45. data/lib/dm-core/property/numeric.rb +35 -0
  46. data/lib/dm-core/property/object.rb +33 -0
  47. data/lib/dm-core/property/serial.rb +13 -0
  48. data/lib/dm-core/property/string.rb +47 -0
  49. data/lib/dm-core/property/text.rb +12 -0
  50. data/lib/dm-core/property/time.rb +46 -0
  51. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  52. data/lib/dm-core/property/typecast/time.rb +33 -0
  53. data/lib/dm-core/property.rb +856 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query/conditions/comparison.rb +886 -0
  56. data/lib/dm-core/query/conditions/operation.rb +710 -0
  57. data/lib/dm-core/query/direction.rb +33 -0
  58. data/lib/dm-core/query/operator.rb +34 -0
  59. data/lib/dm-core/query/path.rb +113 -0
  60. data/lib/dm-core/query/sort.rb +38 -0
  61. data/lib/dm-core/query.rb +1352 -0
  62. data/lib/dm-core/relationship_set.rb +69 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
  65. data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
  66. data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
  67. data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
  68. data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
  69. data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
  70. data/lib/dm-core/resource/persistence_state.rb +70 -0
  71. data/lib/dm-core/resource.rb +1220 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  74. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  75. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  76. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  77. data/lib/dm-core/spec/setup.rb +164 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
  83. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  84. data/lib/dm-core/support/assertions.rb +8 -0
  85. data/lib/dm-core/support/chainable.rb +18 -0
  86. data/lib/dm-core/support/deprecate.rb +12 -0
  87. data/lib/dm-core/support/descendant_set.rb +89 -0
  88. data/lib/dm-core/support/equalizer.rb +48 -0
  89. data/lib/dm-core/support/ext/array.rb +22 -0
  90. data/lib/dm-core/support/ext/blank.rb +25 -0
  91. data/lib/dm-core/support/ext/hash.rb +67 -0
  92. data/lib/dm-core/support/ext/module.rb +47 -0
  93. data/lib/dm-core/support/ext/object.rb +57 -0
  94. data/lib/dm-core/support/ext/string.rb +24 -0
  95. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  96. data/lib/dm-core/support/hook.rb +388 -0
  97. data/lib/dm-core/support/inflections.rb +60 -0
  98. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  99. data/lib/dm-core/support/inflector/methods.rb +151 -0
  100. data/lib/dm-core/support/lazy_array.rb +451 -0
  101. data/lib/dm-core/support/local_object_space.rb +13 -0
  102. data/lib/dm-core/support/logger.rb +201 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +109 -0
  105. data/lib/dm-core/support/ordered_set.rb +381 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +251 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/lib/dm-core.rb +274 -0
  110. data/script/performance.rb +275 -0
  111. data/script/profile.rb +218 -0
  112. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  113. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
  114. data/spec/public/associations/many_to_many_spec.rb +197 -0
  115. data/spec/public/associations/many_to_one_spec.rb +83 -0
  116. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  117. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  118. data/spec/public/associations/one_to_many_spec.rb +81 -0
  119. data/spec/public/associations/one_to_one_spec.rb +176 -0
  120. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  121. data/spec/public/collection_spec.rb +69 -0
  122. data/spec/public/finalize_spec.rb +77 -0
  123. data/spec/public/model/hook_spec.rb +245 -0
  124. data/spec/public/model/property_spec.rb +91 -0
  125. data/spec/public/model/relationship_spec.rb +1040 -0
  126. data/spec/public/model_spec.rb +456 -0
  127. data/spec/public/property/binary_spec.rb +43 -0
  128. data/spec/public/property/boolean_spec.rb +21 -0
  129. data/spec/public/property/class_spec.rb +27 -0
  130. data/spec/public/property/date_spec.rb +21 -0
  131. data/spec/public/property/date_time_spec.rb +21 -0
  132. data/spec/public/property/decimal_spec.rb +23 -0
  133. data/spec/public/property/discriminator_spec.rb +134 -0
  134. data/spec/public/property/float_spec.rb +22 -0
  135. data/spec/public/property/integer_spec.rb +22 -0
  136. data/spec/public/property/object_spec.rb +117 -0
  137. data/spec/public/property/serial_spec.rb +22 -0
  138. data/spec/public/property/string_spec.rb +21 -0
  139. data/spec/public/property/text_spec.rb +62 -0
  140. data/spec/public/property/time_spec.rb +21 -0
  141. data/spec/public/property_spec.rb +333 -0
  142. data/spec/public/resource/state_spec.rb +72 -0
  143. data/spec/public/resource_spec.rb +289 -0
  144. data/spec/public/sel_spec.rb +53 -0
  145. data/spec/public/setup_spec.rb +145 -0
  146. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  147. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  148. data/spec/public/shared/collection_shared_spec.rb +1637 -0
  149. data/spec/public/shared/finder_shared_spec.rb +1647 -0
  150. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  151. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  152. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  153. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  154. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  155. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  156. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  157. data/spec/semipublic/associations_spec.rb +177 -0
  158. data/spec/semipublic/collection_spec.rb +110 -0
  159. data/spec/semipublic/model_spec.rb +96 -0
  160. data/spec/semipublic/property/binary_spec.rb +13 -0
  161. data/spec/semipublic/property/boolean_spec.rb +47 -0
  162. data/spec/semipublic/property/class_spec.rb +33 -0
  163. data/spec/semipublic/property/date_spec.rb +43 -0
  164. data/spec/semipublic/property/date_time_spec.rb +46 -0
  165. data/spec/semipublic/property/decimal_spec.rb +83 -0
  166. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  167. data/spec/semipublic/property/float_spec.rb +82 -0
  168. data/spec/semipublic/property/integer_spec.rb +82 -0
  169. data/spec/semipublic/property/lookup_spec.rb +29 -0
  170. data/spec/semipublic/property/serial_spec.rb +13 -0
  171. data/spec/semipublic/property/string_spec.rb +13 -0
  172. data/spec/semipublic/property/text_spec.rb +31 -0
  173. data/spec/semipublic/property/time_spec.rb +50 -0
  174. data/spec/semipublic/property_spec.rb +114 -0
  175. data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
  176. data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
  177. data/spec/semipublic/query/path_spec.rb +471 -0
  178. data/spec/semipublic/query_spec.rb +3665 -0
  179. data/spec/semipublic/resource/state/clean_spec.rb +89 -0
  180. data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
  181. data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
  182. data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
  183. data/spec/semipublic/resource/state/transient_spec.rb +163 -0
  184. data/spec/semipublic/resource/state_spec.rb +230 -0
  185. data/spec/semipublic/resource_spec.rb +23 -0
  186. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  187. data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
  188. data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
  189. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  190. data/spec/spec_helper.rb +34 -0
  191. data/spec/support/core_ext/hash.rb +10 -0
  192. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  193. data/spec/support/properties/huge_integer.rb +17 -0
  194. data/spec/unit/array_spec.rb +23 -0
  195. data/spec/unit/blank_spec.rb +73 -0
  196. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  197. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  198. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  199. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  200. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  201. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  202. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  203. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  204. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  205. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  206. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  207. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  208. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  216. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  217. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  218. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  219. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  220. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  221. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  222. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  223. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  224. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  226. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  227. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  228. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  229. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  230. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  231. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  232. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  233. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  237. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  239. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  240. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  241. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  242. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  243. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  244. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  245. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  246. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  247. data/spec/unit/hash_spec.rb +27 -0
  248. data/spec/unit/hook_spec.rb +1216 -0
  249. data/spec/unit/inflections_spec.rb +14 -0
  250. data/spec/unit/lazy_array_spec.rb +1949 -0
  251. data/spec/unit/mash_spec.rb +289 -0
  252. data/spec/unit/module_spec.rb +70 -0
  253. data/spec/unit/object_spec.rb +38 -0
  254. data/spec/unit/try_dup_spec.rb +46 -0
  255. data/tasks/ci.rake +1 -0
  256. data/tasks/spec.rake +18 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +323 -0
@@ -0,0 +1,19 @@
1
+ module DataMapper
2
+ class Property
3
+ class Binary < String
4
+ if RUBY_VERSION >= '1.9'
5
+
6
+ def load(value)
7
+ super.dup.force_encoding('BINARY') unless value.nil?
8
+ end
9
+
10
+ def dump(value)
11
+ value&.dup&.force_encoding('BINARY')
12
+ rescue
13
+ value
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ module DataMapper
2
+ class Property
3
+ class Boolean < Object
4
+ load_as ::TrueClass
5
+ dump_as ::TrueClass
6
+
7
+ TRUE_VALUES = [1, '1', 't', 'T', 'true', 'TRUE'].freeze
8
+ FALSE_VALUES = [0, '0', 'f', 'F', 'false', 'FALSE'].freeze
9
+ BOOLEAN_MAP = (TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])).to_h.freeze
10
+
11
+ # @api semipublic
12
+ def value_dumped?(value)
13
+ value_loaded?(value)
14
+ end
15
+
16
+ # @api semipublic
17
+ def value_loaded?(value)
18
+ [true, false].include?(value)
19
+ end
20
+
21
+ # Typecast a value to a true or false
22
+ #
23
+ # @param [Integer, #to_str] value
24
+ # value to typecast
25
+ #
26
+ # @return [Boolean]
27
+ # true or false constructed from value
28
+ #
29
+ # @api private
30
+ def typecast_to_primitive(value)
31
+ BOOLEAN_MAP.fetch(value, value)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module DataMapper
2
+ class Property
3
+ class Class < Object
4
+ load_as ::Class
5
+ dump_as ::Class
6
+
7
+ # Typecast a value to a Class
8
+ #
9
+ # @param [#to_s] value
10
+ # value to typecast
11
+ #
12
+ # @return [Class]
13
+ # Class constructed from value
14
+ #
15
+ # @api private
16
+ def typecast_to_primitive(value)
17
+ DataMapper::Ext::Module.find_const(model, value.to_s)
18
+ rescue NameError
19
+ value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ module DataMapper
2
+ class Property
3
+ class Date < Object
4
+ include Typecast::Time
5
+
6
+ load_as ::Date
7
+ dump_as ::Date
8
+
9
+ # Typecasts an arbitrary value to a Date
10
+ # Handles both Hashes and Date instances.
11
+ #
12
+ # @param [Hash, #to_mash, #to_s] value
13
+ # value to be typecast
14
+ #
15
+ # @return [Date]
16
+ # Date constructed from value
17
+ #
18
+ # @api private
19
+ def typecast_to_primitive(value)
20
+ if value.respond_to?(:to_date)
21
+ value.to_date
22
+ elsif value.is_a?(::Hash) || value.respond_to?(:to_mash)
23
+ typecast_hash_to_date(value)
24
+ else
25
+ ::Date.parse(value.to_s)
26
+ end
27
+ rescue ArgumentError
28
+ value
29
+ end
30
+
31
+ # Creates a Date instance from a Hash with keys :year, :month, :day
32
+ #
33
+ # @param [Hash, #to_mash] value
34
+ # value to be typecast
35
+ #
36
+ # @return [Date]
37
+ # Date constructed from hash
38
+ #
39
+ # @api private
40
+ def typecast_hash_to_date(value)
41
+ ::Date.new(*extract_time(value)[0, 3])
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ module DataMapper
2
+ class Property
3
+ class DateTime < Object
4
+ include Typecast::Time
5
+
6
+ load_as ::DateTime
7
+ dump_as ::DateTime
8
+
9
+ # Typecasts an arbitrary value to a DateTime.
10
+ # Handles both Hashes and DateTime instances.
11
+ #
12
+ # @param [Hash, #to_mash, #to_s] value
13
+ # value to be typecast
14
+ #
15
+ # @return [DateTime]
16
+ # DateTime constructed from value
17
+ #
18
+ # @api private
19
+ def typecast_to_primitive(value)
20
+ if value.is_a?(::Hash) || value.respond_to?(:to_mash)
21
+ typecast_hash_to_datetime(value)
22
+ else
23
+ ::DateTime.parse(value.to_s)
24
+ end
25
+ rescue ArgumentError
26
+ value
27
+ end
28
+
29
+ # Creates a DateTime instance from a Hash with keys :year, :month, :day,
30
+ # :hour, :min, :sec
31
+ #
32
+ # @param [Hash, #to_mash] value
33
+ # value to be typecast
34
+ #
35
+ # @return [DateTime]
36
+ # DateTime constructed from hash
37
+ #
38
+ # @api private
39
+ def typecast_hash_to_datetime(value)
40
+ ::DateTime.new(*extract_time(value))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ module DataMapper
2
+ class Property
3
+ class Decimal < Numeric
4
+ load_as BigDecimal
5
+ dump_as BigDecimal
6
+
7
+ DEFAULT_PRECISION = 10
8
+ DEFAULT_SCALE = 0
9
+
10
+ precision(DEFAULT_PRECISION)
11
+ scale(DEFAULT_SCALE)
12
+
13
+ protected def initialize(model, name, options = {})
14
+ super
15
+
16
+ %i(scale precision).each do |key|
17
+ unless @options.key?(key)
18
+ warn "options[#{key.inspect}] should be set for #{self.class}, defaulting to #{send(key).inspect} (#{caller.first})"
19
+ end
20
+ end
21
+
22
+ raise ArgumentError, "scale must be equal to or greater than 0, but was #{@scale.inspect}" unless @scale >= 0
23
+
24
+ return if @precision >= @scale
25
+
26
+ raise ArgumentError, "precision must be equal to or greater than scale, but was #{@precision.inspect} and scale was #{@scale.inspect}"
27
+ end
28
+
29
+ # Typecast a value to a BigDecimal
30
+ #
31
+ # @param [#to_str, #to_d, Integer] value
32
+ # value to typecast
33
+ #
34
+ # @return [BigDecimal]
35
+ # BigDecimal constructed from value
36
+ #
37
+ # @api private
38
+ protected def typecast_to_primitive(value)
39
+ if value.is_a?(::Integer)
40
+ value.to_s.to_d
41
+ else
42
+ typecast_to_numeric(value, :to_d)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ module DataMapper
2
+ class Property
3
+ class Discriminator < Class
4
+ default ->(resource, _property) { resource.model }
5
+ required true
6
+
7
+ # @api private
8
+ def bind
9
+ model.extend Model unless model < Model
10
+ end
11
+
12
+ module Model
13
+ def inherited(model)
14
+ super # setup self.descendants
15
+ set_discriminator_scope_for(model)
16
+ end
17
+
18
+ def new(*args, &block)
19
+ if args.size == 1 && args.first.is_a?(Hash)
20
+ discriminator = properties(repository_name).discriminator
21
+
22
+ if (discriminator_value = args.first[discriminator.name])
23
+ model = discriminator.typecast_to_primitive(discriminator_value)
24
+
25
+ return model.new(*args, &block) if model.is_a?(Model) && !model.equal?(self)
26
+ end
27
+ end
28
+
29
+ super
30
+ end
31
+
32
+ private def set_discriminator_scope_for(model)
33
+ discriminator = properties.discriminator
34
+ default_scope = model.default_scope(discriminator.repository_name)
35
+ default_scope.update(discriminator.name => model.descendants.dup << model)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ module DataMapper
2
+ class Property
3
+ class Float < Numeric
4
+ load_as ::Float
5
+ dump_as ::Float
6
+
7
+ DEFAULT_PRECISION = 10
8
+ DEFAULT_SCALE = nil
9
+
10
+ precision(DEFAULT_PRECISION)
11
+ scale(DEFAULT_SCALE)
12
+
13
+ # Typecast a value to a Float
14
+ #
15
+ # @param [#to_str, #to_f] value
16
+ # value to typecast
17
+ #
18
+ # @return [Float]
19
+ # Float constructed from value
20
+ #
21
+ # @api private
22
+ protected def typecast_to_primitive(value)
23
+ typecast_to_numeric(value, :to_f)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ module DataMapper
2
+ class Property
3
+ class Integer < Numeric
4
+ load_as ::Integer
5
+ dump_as ::Integer
6
+
7
+ accept_options :serial
8
+
9
+ # @api semipublic
10
+ protected def initialize(model, name, options = {})
11
+ if options.key?(:serial) && !is_a?(Serial)
12
+ raise "Integer #{name} with explicit :serial option is deprecated, use Serial instead (#{caller[2]})"
13
+ end
14
+
15
+ super
16
+ end
17
+
18
+ # Typecast a value to an Integer
19
+ #
20
+ # @param [#to_str, #to_i] value
21
+ # value to typecast
22
+ #
23
+ # @return [Integer]
24
+ # Integer constructed from value
25
+ #
26
+ # @api private
27
+ protected def typecast_to_primitive(value)
28
+ typecast_to_numeric(value, :to_i)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module DataMapper
2
+ class Property
3
+ # Exception raised when DataMapper is about to work with
4
+ # invalid property values.
5
+ class InvalidValueError < StandardError
6
+ attr_reader :property, :value
7
+
8
+ def initialize(property, value)
9
+ msg = format('Invalid value %s for property %s (%s) on model %s', value.inspect, property.name.inspect, property.class.name,
10
+ property.model.name)
11
+ super(msg)
12
+ @property = property
13
+ @value = value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module DataMapper
2
+ class Property
3
+ module Lookup
4
+ #
5
+ # Provides transparent access to the Properties defined in
6
+ # {Property}.
7
+ #
8
+ # @param [Symbol] name
9
+ # The name of the property to lookup.
10
+ #
11
+ # @return [Property]
12
+ # The property with the given name.
13
+ #
14
+ # @raise [NameError]
15
+ # The property could not be found.
16
+ #
17
+ # @api private
18
+ #
19
+ # @since 1.0.1
20
+ #
21
+ protected def const_missing(name)
22
+ Property.find_class(name.to_s) || super
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ module DataMapper
2
+ class Property
3
+ class Numeric < Object
4
+ include Typecast::Numeric
5
+
6
+ accept_options :precision, :scale, :min, :max
7
+ attr_reader :precision, :scale, :min, :max
8
+
9
+ DEFAULT_NUMERIC_MIN = 0
10
+ DEFAULT_NUMERIC_MAX = (2**31) - 1
11
+
12
+ protected def initialize(model, name, options = {})
13
+ super
14
+
15
+ if is_a?(Decimal) || is_a?(Float)
16
+ @precision = @options.fetch(:precision)
17
+ @scale = @options.fetch(:scale)
18
+
19
+ raise ArgumentError, "precision must be greater than 0, but was #{@precision.inspect}" unless @precision > 0
20
+ end
21
+
22
+ return unless @options.key?(:min) || @options.key?(:max)
23
+
24
+ @min = @options.fetch(:min, self.class::DEFAULT_NUMERIC_MIN)
25
+ @max = @options.fetch(:max, self.class::DEFAULT_NUMERIC_MAX)
26
+
27
+ if @max < DEFAULT_NUMERIC_MIN && !@options.key?(:min)
28
+ raise ArgumentError, "min should be specified when the max is less than #{DEFAULT_NUMERIC_MIN}"
29
+ elsif @max < @min
30
+ raise ArgumentError, "max must be less than the min, but was #{@max} while the min was #{@min}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ module DataMapper
2
+ class Property
3
+ class Object < Property
4
+ load_as ::Object
5
+ dump_as ::Object
6
+
7
+ # @api semipublic
8
+ def dump(value)
9
+ instance_of?(Object) ? marshal(value) : value
10
+ end
11
+
12
+ # @api semipublic
13
+ def load(value)
14
+ typecast(instance_of?(Object) ? unmarshal(value) : value)
15
+ end
16
+
17
+ # @api semipublic
18
+ def marshal(value)
19
+ [Marshal.dump(value)].pack('m') unless value.nil?
20
+ end
21
+
22
+ # @api semipublic
23
+ def unmarshal(value)
24
+ Marshal.load(value.unpack1('m')) unless value.nil?
25
+ end
26
+
27
+ # @api private
28
+ def to_child_key
29
+ self.class
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module DataMapper
2
+ class Property
3
+ class Serial < Integer
4
+ serial true
5
+ min 1
6
+
7
+ # @api private
8
+ def to_child_key
9
+ Property::Integer
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ module DataMapper
2
+ class Property
3
+ class String < Object
4
+ load_as ::String
5
+ dump_as ::String
6
+
7
+ accept_options :length
8
+
9
+ DEFAULT_LENGTH = 50
10
+ length(DEFAULT_LENGTH)
11
+
12
+ # Returns maximum property length (if applicable).
13
+ # This usually only makes sense when property is of
14
+ # type Range or custom
15
+ #
16
+ # @return [Integer, nil]
17
+ # the maximum length of this property
18
+ #
19
+ # @api semipublic
20
+ def length
21
+ if @length.is_a?(Range)
22
+ @length.max
23
+ else
24
+ @length
25
+ end
26
+ end
27
+
28
+ protected def initialize(model, name, options = {})
29
+ super
30
+ @length = @options.fetch(:length)
31
+ end
32
+
33
+ # Typecast a value to a String
34
+ #
35
+ # @param [#to_s] value
36
+ # value to typecast
37
+ #
38
+ # @return [String]
39
+ # String constructed from value
40
+ #
41
+ # @api private
42
+ protected def typecast_to_primitive(value)
43
+ value.to_s
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ module DataMapper
2
+ class Property
3
+ class Text < String
4
+ length 65_535
5
+ lazy true
6
+
7
+ def primitive?(value)
8
+ value.is_a?(::String)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ module DataMapper
2
+ class Property
3
+ class Time < Object
4
+ include Typecast::Time
5
+
6
+ load_as ::Time
7
+ dump_as ::Time
8
+
9
+ # Typecasts an arbitrary value to a Time
10
+ # Handles both Hashes and Time instances.
11
+ #
12
+ # @param [Hash, #to_mash, #to_s] value
13
+ # value to be typecast
14
+ #
15
+ # @return [Time]
16
+ # Time constructed from value
17
+ #
18
+ # @api private
19
+ def typecast_to_primitive(value)
20
+ if value.respond_to?(:to_time)
21
+ value.to_time
22
+ elsif value.is_a?(::Hash) || value.respond_to?(:to_mash)
23
+ typecast_hash_to_time(value)
24
+ else
25
+ ::Time.parse(value.to_s)
26
+ end
27
+ rescue ArgumentError
28
+ value
29
+ end
30
+
31
+ # Creates a Time instance from a Hash with keys :year, :month, :day,
32
+ # :hour, :min, :sec
33
+ #
34
+ # @param [Hash, #to_mash] value
35
+ # value to be typecast
36
+ #
37
+ # @return [Time]
38
+ # Time constructed from hash
39
+ #
40
+ # @api private
41
+ def typecast_hash_to_time(value)
42
+ ::Time.local(*extract_time(value))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ module DataMapper
2
+ class Property
3
+ module Typecast
4
+ module Numeric
5
+ # Match numeric string
6
+ #
7
+ # @param [#to_str, Numeric] value
8
+ # value to typecast
9
+ # @param [Symbol] method
10
+ # method to typecast with
11
+ #
12
+ # @return [Numeric]
13
+ # number if matched, value if no match
14
+ #
15
+ # @api private
16
+ def typecast_to_numeric(value, method)
17
+ if value.respond_to?(:to_str)
18
+ if value.to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
19
+ ::Regexp.last_match(1).send(method)
20
+ else
21
+ value
22
+ end
23
+ elsif value.respond_to?(method)
24
+ value.send(method)
25
+ else
26
+ value
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module DataMapper
2
+ class Property
3
+ module Typecast
4
+ module Time
5
+ include Numeric
6
+
7
+ # Extracts the given args from the hash. If a value does not exist, it
8
+ # uses the value of Time.now.
9
+ #
10
+ # @param [Hash, #to_mash] value
11
+ # value to extract time args from
12
+ #
13
+ # @return [Array]
14
+ # Extracted values
15
+ #
16
+ # @api private
17
+ def extract_time(value)
18
+ mash = if value.respond_to?(:to_mash)
19
+ value.to_mash
20
+ else
21
+ DataMapper::Ext::Hash.to_mash(value)
22
+ end
23
+
24
+ now = ::Time.now
25
+
26
+ %i(year month day hour min sec).map do |segment|
27
+ typecast_to_numeric(mash.fetch(segment, now.send(segment)), :to_i)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end