mongoid 7.6.0 → 8.0.1

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 (313) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/README.md +3 -3
  4. data/Rakefile +21 -85
  5. data/lib/config/locales/en.yml +46 -30
  6. data/lib/mongoid/association/accessors.rb +32 -3
  7. data/lib/mongoid/association/bindable.rb +48 -0
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/eager_loadable.rb +29 -7
  10. data/lib/mongoid/association/embedded/batchable.rb +28 -5
  11. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  12. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  14. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  15. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  16. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  17. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  18. data/lib/mongoid/association/macros.rb +2 -1
  19. data/lib/mongoid/association/many.rb +5 -0
  20. data/lib/mongoid/association/nested/many.rb +2 -1
  21. data/lib/mongoid/association/proxy.rb +12 -0
  22. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  23. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  24. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  25. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  26. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  27. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  28. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  29. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -18
  30. data/lib/mongoid/association/referenced/has_many/proxy.rb +12 -9
  31. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  32. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  33. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  34. data/lib/mongoid/association/relatable.rb +38 -4
  35. data/lib/mongoid/attributes/processing.rb +9 -2
  36. data/lib/mongoid/attributes.rb +30 -27
  37. data/lib/mongoid/cacheable.rb +2 -2
  38. data/lib/mongoid/changeable.rb +37 -2
  39. data/lib/mongoid/clients/options.rb +4 -0
  40. data/lib/mongoid/clients/sessions.rb +2 -14
  41. data/lib/mongoid/config.rb +15 -11
  42. data/lib/mongoid/contextual/aggregable/memory.rb +23 -15
  43. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  44. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  45. data/lib/mongoid/contextual/memory.rb +55 -28
  46. data/lib/mongoid/contextual/mongo.rb +173 -287
  47. data/lib/mongoid/contextual/none.rb +33 -15
  48. data/lib/mongoid/copyable.rb +32 -8
  49. data/lib/mongoid/criteria/includable.rb +24 -20
  50. data/lib/mongoid/criteria/marshalable.rb +10 -2
  51. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -15
  52. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  53. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  54. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  55. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  56. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -16
  57. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  58. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  59. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  60. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +1 -1
  61. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  62. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  63. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  64. data/lib/mongoid/criteria/queryable/optional.rb +3 -9
  65. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  66. data/lib/mongoid/criteria/queryable/selectable.rb +2 -24
  67. data/lib/mongoid/criteria/queryable/selector.rb +90 -5
  68. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  69. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  70. data/lib/mongoid/criteria/queryable.rb +11 -6
  71. data/lib/mongoid/criteria.rb +1 -28
  72. data/lib/mongoid/deprecable.rb +36 -0
  73. data/lib/mongoid/deprecation.rb +25 -0
  74. data/lib/mongoid/document.rb +88 -33
  75. data/lib/mongoid/equality.rb +4 -4
  76. data/lib/mongoid/errors/document_not_found.rb +6 -2
  77. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  78. data/lib/mongoid/errors/invalid_field.rb +5 -1
  79. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  81. data/lib/mongoid/errors.rb +2 -2
  82. data/lib/mongoid/extensions/array.rb +8 -6
  83. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  84. data/lib/mongoid/extensions/binary.rb +42 -0
  85. data/lib/mongoid/extensions/boolean.rb +8 -2
  86. data/lib/mongoid/extensions/date.rb +26 -20
  87. data/lib/mongoid/extensions/date_time.rb +1 -1
  88. data/lib/mongoid/extensions/float.rb +4 -5
  89. data/lib/mongoid/extensions/hash.rb +12 -5
  90. data/lib/mongoid/extensions/integer.rb +4 -5
  91. data/lib/mongoid/extensions/object.rb +2 -0
  92. data/lib/mongoid/extensions/range.rb +41 -10
  93. data/lib/mongoid/extensions/regexp.rb +11 -4
  94. data/lib/mongoid/extensions/set.rb +11 -4
  95. data/lib/mongoid/extensions/string.rb +2 -13
  96. data/lib/mongoid/extensions/symbol.rb +3 -14
  97. data/lib/mongoid/extensions/time.rb +27 -16
  98. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  99. data/lib/mongoid/extensions.rb +1 -0
  100. data/lib/mongoid/factory.rb +42 -7
  101. data/lib/mongoid/fields/foreign_key.rb +7 -0
  102. data/lib/mongoid/fields/validators/macro.rb +3 -9
  103. data/lib/mongoid/fields.rb +49 -7
  104. data/lib/mongoid/findable.rb +21 -16
  105. data/lib/mongoid/indexable/specification.rb +1 -1
  106. data/lib/mongoid/indexable/validators/options.rb +4 -1
  107. data/lib/mongoid/interceptable.rb +69 -9
  108. data/lib/mongoid/persistable/creatable.rb +14 -5
  109. data/lib/mongoid/persistable/updatable.rb +12 -5
  110. data/lib/mongoid/persistence_context.rb +8 -42
  111. data/lib/mongoid/query_cache.rb +6 -258
  112. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  113. data/lib/mongoid/reloadable.rb +7 -3
  114. data/lib/mongoid/scopable.rb +9 -11
  115. data/lib/mongoid/selectable.rb +1 -2
  116. data/lib/mongoid/shardable.rb +11 -35
  117. data/lib/mongoid/stateful.rb +27 -1
  118. data/lib/mongoid/timestamps/created.rb +1 -1
  119. data/lib/mongoid/timestamps/updated.rb +1 -1
  120. data/lib/mongoid/touchable.rb +2 -3
  121. data/lib/mongoid/traversable.rb +1 -0
  122. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  123. data/lib/mongoid/version.rb +1 -5
  124. data/lib/mongoid/warnings.rb +3 -4
  125. data/lib/mongoid.rb +1 -0
  126. data/spec/config/mongoid.yml +16 -0
  127. data/spec/integration/app_spec.rb +8 -12
  128. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  129. data/spec/integration/associations/embedded_spec.rb +15 -0
  130. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  131. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  132. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  133. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  134. data/spec/integration/associations/has_one_spec.rb +97 -1
  135. data/spec/integration/associations/scope_option_spec.rb +1 -1
  136. data/spec/integration/callbacks_models.rb +95 -1
  137. data/spec/integration/callbacks_spec.rb +226 -4
  138. data/spec/integration/criteria/range_spec.rb +95 -1
  139. data/spec/integration/discriminator_key_spec.rb +115 -76
  140. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  141. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  142. data/spec/integration/matcher_examples_spec.rb +20 -13
  143. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  144. data/spec/integration/matcher_operator_spec.rb +3 -5
  145. data/spec/integration/persistence/range_field_spec.rb +350 -0
  146. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  147. data/spec/mongoid/association/depending_spec.rb +9 -9
  148. data/spec/mongoid/association/eager_spec.rb +2 -1
  149. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  150. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  151. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  152. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  153. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +198 -8
  154. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  155. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  156. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  157. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  158. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  159. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  160. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  161. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  162. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  163. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  164. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  165. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +38 -5
  166. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  167. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  168. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  169. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  170. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +62 -13
  171. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  172. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  173. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  174. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  175. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  176. data/spec/mongoid/association/syncable_spec.rb +14 -0
  177. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  178. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  179. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  180. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  181. data/spec/mongoid/attributes_spec.rb +480 -27
  182. data/spec/mongoid/cacheable_spec.rb +3 -3
  183. data/spec/mongoid/changeable_spec.rb +130 -13
  184. data/spec/mongoid/clients/factory_spec.rb +23 -30
  185. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  186. data/spec/mongoid/clients_spec.rb +2 -2
  187. data/spec/mongoid/config_spec.rb +52 -15
  188. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  189. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  190. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  191. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  192. data/spec/mongoid/contextual/memory_spec.rb +521 -14
  193. data/spec/mongoid/contextual/mongo_spec.rb +566 -426
  194. data/spec/mongoid/contextual/none_spec.rb +11 -19
  195. data/spec/mongoid/copyable_spec.rb +451 -2
  196. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  197. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  198. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  199. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  200. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  201. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  202. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +1 -2
  203. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  204. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  205. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +1 -2
  206. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  207. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  208. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  209. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  210. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  211. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  212. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  213. data/spec/mongoid/criteria/queryable/selector_spec.rb +16 -77
  214. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  215. data/spec/mongoid/criteria_spec.rb +469 -1201
  216. data/spec/mongoid/document_fields_spec.rb +173 -24
  217. data/spec/mongoid/document_spec.rb +32 -41
  218. data/spec/mongoid/equality_spec.rb +12 -12
  219. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  220. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  221. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  222. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  223. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  224. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  225. data/spec/mongoid/extensions/array_spec.rb +16 -2
  226. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  227. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  228. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  229. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  230. data/spec/mongoid/extensions/date_spec.rb +71 -1
  231. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  232. data/spec/mongoid/extensions/float_spec.rb +48 -76
  233. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  234. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  235. data/spec/mongoid/extensions/range_spec.rb +255 -54
  236. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  237. data/spec/mongoid/extensions/set_spec.rb +106 -0
  238. data/spec/mongoid/extensions/string_spec.rb +53 -25
  239. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  240. data/spec/mongoid/extensions/time_spec.rb +634 -66
  241. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  242. data/spec/mongoid/factory_spec.rb +61 -1
  243. data/spec/mongoid/fields_spec.rb +321 -50
  244. data/spec/mongoid/findable_spec.rb +64 -29
  245. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  246. data/spec/mongoid/indexable_spec.rb +16 -19
  247. data/spec/mongoid/interceptable_spec.rb +584 -5
  248. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  249. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  250. data/spec/mongoid/mongoizable_spec.rb +285 -0
  251. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  252. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  253. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  254. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  255. data/spec/mongoid/persistence_context_spec.rb +24 -0
  256. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  257. data/spec/mongoid/query_cache_spec.rb +1 -156
  258. data/spec/mongoid/reloadable_spec.rb +35 -2
  259. data/spec/mongoid/scopable_spec.rb +36 -34
  260. data/spec/mongoid/serializable_spec.rb +14 -7
  261. data/spec/mongoid/shardable_models.rb +0 -14
  262. data/spec/mongoid/shardable_spec.rb +61 -153
  263. data/spec/mongoid/stateful_spec.rb +28 -0
  264. data/spec/mongoid/timestamps_spec.rb +390 -0
  265. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  266. data/spec/mongoid/touchable_spec.rb +116 -0
  267. data/spec/mongoid/touchable_spec_models.rb +12 -8
  268. data/spec/mongoid/traversable_spec.rb +4 -11
  269. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  270. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  271. data/spec/mongoid/warnings_spec.rb +35 -0
  272. data/spec/mongoid_spec.rb +1 -7
  273. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  274. data/spec/rails/mongoid_spec.rb +4 -16
  275. data/spec/shared/lib/mrss/docker_runner.rb +1 -8
  276. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  277. data/spec/shared/lib/mrss/lite_constraints.rb +2 -10
  278. data/spec/shared/lib/mrss/server_version_registry.rb +24 -17
  279. data/spec/shared/lib/mrss/spec_organizer.rb +3 -32
  280. data/spec/shared/lib/mrss/utils.rb +6 -28
  281. data/spec/shared/share/Dockerfile.erb +107 -33
  282. data/spec/shared/shlib/distro.sh +0 -10
  283. data/spec/shared/shlib/server.sh +33 -64
  284. data/spec/shared/shlib/set_env.sh +71 -12
  285. data/spec/support/constraints.rb +24 -0
  286. data/spec/support/expectations.rb +17 -20
  287. data/spec/support/macros.rb +30 -0
  288. data/spec/support/models/augmentation.rb +12 -0
  289. data/spec/support/models/band.rb +3 -0
  290. data/spec/support/models/catalog.rb +24 -0
  291. data/spec/support/models/circus.rb +3 -0
  292. data/spec/support/models/fanatic.rb +8 -0
  293. data/spec/support/models/implant.rb +9 -0
  294. data/spec/support/models/label.rb +2 -0
  295. data/spec/support/models/passport.rb +9 -0
  296. data/spec/support/models/person.rb +1 -0
  297. data/spec/support/models/player.rb +2 -0
  298. data/spec/support/models/powerup.rb +12 -0
  299. data/spec/support/models/registry.rb +1 -0
  300. data/spec/support/models/school.rb +14 -0
  301. data/spec/support/models/shield.rb +18 -0
  302. data/spec/support/models/student.rb +14 -0
  303. data/spec/support/models/weapon.rb +12 -0
  304. data.tar.gz.sig +0 -0
  305. metadata +695 -641
  306. metadata.gz.sig +0 -0
  307. data/lib/mongoid/errors/eager_load.rb +0 -23
  308. data/lib/mongoid/errors/invalid_value.rb +0 -17
  309. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  310. data/spec/shared/CANDIDATE.md +0 -28
  311. data/spec/shared/lib/mrss/release/candidate.rb +0 -281
  312. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  313. data/spec/shared/lib/tasks/candidate.rake +0 -64
@@ -6,9 +6,6 @@ module Mongoid
6
6
  module Factory
7
7
  extend self
8
8
 
9
- # @deprecated
10
- TYPE = "_type".freeze
11
-
12
9
  # Builds a new +Document+ from the supplied attributes.
13
10
  #
14
11
  # This method either instantiates klass or a descendant of klass if the attributes include
@@ -23,16 +20,32 @@ module Mongoid
23
20
  #
24
21
  # @param [ Class ] klass The class to instantiate from if _type is not present.
25
22
  # @param [ Hash ] attributes The document attributes.
23
+ # @param [ true | false ] execute_callbacks Flag specifies whether callbacks
24
+ # should be run.
26
25
  #
27
26
  # @return [ Document ] The instantiated document.
28
27
  def build(klass, attributes = nil)
28
+ execute_build(klass, attributes, execute_callbacks: true)
29
+ end
30
+
31
+ # Execute the build.
32
+ #
33
+ # @param [ Class ] klass The class to instantiate from if _type is not present.
34
+ # @param [ Hash ] attributes The document attributes.
35
+ # @param [ true | false ] execute_callbacks Flag specifies whether callbacks
36
+ # should be run.
37
+ #
38
+ # @return [ Document ] The instantiated document.
39
+ #
40
+ # @api private
41
+ def execute_build(klass, attributes = nil, execute_callbacks: true)
29
42
  attributes ||= {}
30
43
  dvalue = attributes[klass.discriminator_key] || attributes[klass.discriminator_key.to_sym]
31
44
  type = klass.get_discriminator_mapping(dvalue)
32
45
  if type
33
- type.new(attributes)
46
+ type.construct_document(attributes, execute_callbacks: execute_callbacks)
34
47
  else
35
- klass.new(attributes)
48
+ klass.construct_document(attributes, execute_callbacks: execute_callbacks)
36
49
  end
37
50
  end
38
51
 
@@ -63,12 +76,34 @@ module Mongoid
63
76
  #
64
77
  # @return [ Document ] The instantiated document.
65
78
  def from_db(klass, attributes = nil, criteria = nil, selected_fields = nil)
79
+ execute_from_db(klass, attributes, criteria, selected_fields, execute_callbacks: true)
80
+ end
81
+
82
+ # Execute from_db.
83
+ #
84
+ # @param [ Class ] klass The class to instantiate from if _type is not present.
85
+ # @param [ Hash ] attributes The document attributes.
86
+ # @param [ Criteria ] criteria Optional criteria object.
87
+ # @param [ Hash ] selected_fields Fields which were retrieved via
88
+ # #only. If selected_fields are specified, fields not listed in it
89
+ # will not be accessible in the returned document.
90
+ # @param [ true | false ] execute_callbacks Whether this method should
91
+ # invoke the callbacks. If true, the callbacks will be invoked normally.
92
+ # If false, the callbacks will be stored in the +pending_callbacks+ list
93
+ # and caller is responsible for invoking +run_pending_callbacks+ at a
94
+ # later time. Use this option to defer callback execution until the
95
+ # entire object graph containing embedded associations is constructed.
96
+ #
97
+ # @return [ Document ] The instantiated document.
98
+ #
99
+ # @api private
100
+ def execute_from_db(klass, attributes = nil, criteria = nil, selected_fields = nil, execute_callbacks: true)
66
101
  if criteria
67
102
  selected_fields ||= criteria.options[:fields]
68
103
  end
69
104
  type = (attributes || {})[klass.discriminator_key]
70
105
  if type.blank?
71
- obj = klass.instantiate(attributes, selected_fields)
106
+ obj = klass.instantiate_document(attributes, selected_fields, execute_callbacks: execute_callbacks)
72
107
  if criteria && criteria.association && criteria.parent_document
73
108
  obj.set_relation(criteria.association.inverse, criteria.parent_document)
74
109
  end
@@ -92,7 +127,7 @@ module Mongoid
92
127
  raise Errors::UnknownModel.new(camelized, type)
93
128
  end
94
129
 
95
- constantized.instantiate(attributes, selected_fields)
130
+ constantized.instantiate_document(attributes, selected_fields, execute_callbacks: execute_callbacks)
96
131
  end
97
132
  end
98
133
  end
@@ -60,6 +60,8 @@ module Mongoid
60
60
  if object_id_field? || object.is_a?(Document)
61
61
  if association.polymorphic?
62
62
  association.convert_to_foreign_key(object)
63
+ elsif object.is_a?(Document) && object.respond_to?(association.primary_key)
64
+ primary_key_field.evolve(object.send(association.primary_key))
63
65
  else
64
66
  object.__evolve_object_id__
65
67
  end
@@ -142,6 +144,11 @@ module Mongoid
142
144
  @related_id_field ||= association.klass.fields["_id"]
143
145
  end
144
146
 
147
+ def primary_key_field
148
+ @primary_key_field ||= association.klass.fields[association.primary_key]
149
+ end
150
+
151
+
145
152
  # This is used when default values need to be serialized. Most of the
146
153
  # time just return the object.
147
154
  #
@@ -8,9 +8,6 @@ module Mongoid
8
8
  module Macro
9
9
  extend self
10
10
 
11
- # The warning message to give when a field is of type Symbol.
12
- FIELD_TYPE_IS_SYMBOL = 'The BSON symbol type is deprecated; use String instead'.freeze
13
-
14
11
  OPTIONS = [
15
12
  :as,
16
13
  :default,
@@ -69,7 +66,7 @@ module Mongoid
69
66
  def validate_field_name(klass, name)
70
67
  [name, "#{name}?".to_sym, "#{name}=".to_sym].each do |n|
71
68
  if Mongoid.destructive_fields.include?(n)
72
- raise Errors::InvalidField.new(klass, n)
69
+ raise Errors::InvalidField.new(klass, name, n)
73
70
  end
74
71
  end
75
72
  end
@@ -91,7 +88,7 @@ module Mongoid
91
88
  def validate_name_uniqueness(klass, name, options)
92
89
  if !options[:overwrite] && klass.fields.keys.include?(name.to_s)
93
90
  if Mongoid.duplicate_fields_exception
94
- raise Errors::InvalidField.new(klass, name)
91
+ raise Errors::InvalidField.new(klass, name, name)
95
92
  else
96
93
  Mongoid.logger.warn("Overwriting existing field #{name} in class #{klass.name}.") if Mongoid.logger
97
94
  end
@@ -117,10 +114,7 @@ module Mongoid
117
114
  end
118
115
 
119
116
  if option == :type && options[option] == Symbol
120
- @field_type_is_symbol_warned ||= begin
121
- Mongoid.logger.warn(FIELD_TYPE_IS_SYMBOL)
122
- true
123
- end
117
+ Mongoid::Warnings.warn_symbol_type_deprecated
124
118
  end
125
119
  end
126
120
  end
@@ -42,6 +42,11 @@ module Mongoid
42
42
  # @api private
43
43
  IDS = [ :_id, '_id', ].freeze
44
44
 
45
+ # BSON classes that are not supported as field types
46
+ #
47
+ # @api private
48
+ INVALID_BSON_CLASSES = [ BSON::Decimal128, BSON::Int32, BSON::Int64 ].freeze
49
+
45
50
  module ClassMethods
46
51
  # Returns the list of id fields for this model class, as both strings
47
52
  # and symbols.
@@ -156,6 +161,7 @@ module Mongoid
156
161
  #
157
162
  # @return [ Array<String ] The names of the proc defaults.
158
163
  def apply_post_processed_defaults
164
+ pending_callbacks.delete(:apply_post_processed_defaults)
159
165
  post_processed_defaults.each do |name|
160
166
  apply_default(name)
161
167
  end
@@ -184,6 +190,7 @@ module Mongoid
184
190
  # @example Apply all the defaults.
185
191
  # model.apply_defaults
186
192
  def apply_defaults
193
+ pending_callbacks.delete(:apply_defaults)
187
194
  apply_pre_processed_defaults
188
195
  apply_post_processed_defaults
189
196
  end
@@ -239,6 +246,32 @@ module Mongoid
239
246
  self.class.using_object_ids?
240
247
  end
241
248
 
249
+ # Does this field start with a dollar sign ($) or contain a dot/period (.)?
250
+ #
251
+ # @api private
252
+ #
253
+ # @param [ String ] name The field name.
254
+ #
255
+ # @return [ true, false ] If this field is dotted or dollared.
256
+ def dot_dollar_field?(name)
257
+ n = aliased_fields[name] || name
258
+ fields.key?(n) && (n.include?('.') || n.start_with?('$'))
259
+ end
260
+
261
+ # Validate whether or not the field starts with a dollar sign ($) or
262
+ # contains a dot/period (.).
263
+ #
264
+ # @api private
265
+ #
266
+ # @raise [ InvalidDotDollarAssignment ] If contains dots or starts with a dollar.
267
+ #
268
+ # @param [ String ] name The field name.
269
+ def validate_writable_field_name!(name)
270
+ if dot_dollar_field?(name)
271
+ raise Errors::InvalidDotDollarAssignment.new(self.class, name)
272
+ end
273
+ end
274
+
242
275
  class << self
243
276
 
244
277
  # Stores the provided block to be run when the option name specified is
@@ -603,9 +636,7 @@ module Mongoid
603
636
  if lazy_settable?(field, raw)
604
637
  write_attribute(name, field.eval_default(self))
605
638
  else
606
- value = field.demongoize(raw)
607
- attribute_will_change!(name) if value.resizable?
608
- value
639
+ process_raw_attribute(name.to_s, raw, field)
609
640
  end
610
641
  end
611
642
  end
@@ -697,10 +728,8 @@ module Mongoid
697
728
  generated_methods.module_eval do
698
729
  re_define_method("#{meth}_translations=") do |value|
699
730
  attribute_will_change!(name)
700
- if value
701
- value.update_values do |_value|
702
- field.type.mongoize(_value)
703
- end
731
+ value&.transform_values! do |_value|
732
+ field.type.mongoize(_value)
704
733
  end
705
734
  attributes[name] = value
706
735
  end
@@ -737,6 +766,19 @@ module Mongoid
737
766
  opts = options.merge(klass: self)
738
767
  type_mapping = TYPE_MAPPINGS[options[:type]]
739
768
  opts[:type] = type_mapping || unmapped_type(options)
769
+ if !opts[:type].is_a?(Class)
770
+ raise Errors::InvalidFieldType.new(self, name, options[:type])
771
+ else
772
+ if INVALID_BSON_CLASSES.include?(opts[:type])
773
+ warn_message = "Using #{opts[:type]} as the field type is not supported. "
774
+ if opts[:type] == BSON::Decimal128
775
+ warn_message += "In BSON <= 4, the BSON::Decimal128 type will work as expected for both storing and querying, but will return a BigDecimal on query in BSON 5+."
776
+ else
777
+ warn_message += "Saving values of this type to the database will work as expected, however, querying them will return a value of the native Ruby Integer type."
778
+ end
779
+ Mongoid.logger.warn(warn_message)
780
+ end
781
+ end
740
782
  return Fields::Localized.new(name, opts) if options[:localize]
741
783
  return Fields::ForeignKey.new(name, opts) if options[:identity]
742
784
  Fields::Standard.new(name, opts)
@@ -38,6 +38,7 @@ module Mongoid
38
38
  :max,
39
39
  :min,
40
40
  :none,
41
+ :pick,
41
42
  :pluck,
42
43
  :read,
43
44
  :sum,
@@ -121,6 +122,13 @@ module Mongoid
121
122
  # strings will be transparently converted to +BSON::ObjectId+ instances
122
123
  # during query construction.
123
124
  #
125
+ # If this method is given a block, it delegates to +Enumerable#find+ and
126
+ # returns the first document of those found by the current Crieria object
127
+ # for which the block returns a truthy value. If both a block and ids are
128
+ # given, the block is ignored and the documents for the given ids are
129
+ # returned. If a block and a Proc are given, the method delegates to
130
+ # +Enumerable#find+ and uses the proc as the default.
131
+ #
124
132
  # The +find+ method takes into account the default scope defined on the
125
133
  # model class, if any.
126
134
  #
@@ -131,8 +139,13 @@ module Mongoid
131
139
  #
132
140
  # @raise Errors::DocumentNotFound If not all documents are found and
133
141
  # the +raise_not_found_error+ Mongoid configuration option is truthy.
134
- def find(*args)
135
- with_default_scope.find(*args)
142
+ def find(*args, &block)
143
+ empty_or_proc = args.empty? || (args.length == 1 && args.first.is_a?(Proc))
144
+ if block_given? && empty_or_proc
145
+ with_default_scope.find(*args, &block)
146
+ else
147
+ with_default_scope.find(*args)
148
+ end
136
149
  end
137
150
 
138
151
  # Find the first +Document+ given the conditions.
@@ -182,15 +195,11 @@ module Mongoid
182
195
  # @example Find the first document.
183
196
  # Person.first
184
197
  #
185
- # @param [ Integer | Hash ] limit_or_opts The number of documents to
186
- # return, or a hash of options.
187
- #
188
- # @option limit_or_opts [ :none ] :id_sort This option is deprecated.
189
- # Don't apply a sort on _id if no other sort is defined on the criteria.
198
+ # @param [ Integer ] limit The number of documents to return.
190
199
  #
191
200
  # @return [ Document ] The first matching document.
192
- def first(limit_or_opts = nil)
193
- with_default_scope.first(limit_or_opts)
201
+ def first(limit = nil)
202
+ with_default_scope.first(limit)
194
203
  end
195
204
  alias :one :first
196
205
 
@@ -199,15 +208,11 @@ module Mongoid
199
208
  # @example Find the last document.
200
209
  # Person.last
201
210
  #
202
- # @param [ Integer | Hash ] limit_or_opts The number of documents to
203
- # return, or a hash of options.
204
- #
205
- # @option limit_or_opts [ :none ] :id_sort This option is deprecated.
206
- # Don't apply a sort on _id if no other sort is defined on the criteria.
211
+ # @param [ Integer ] limit The number of documents to return.
207
212
  #
208
213
  # @return [ Document ] The last matching document.
209
- def last(limit_or_opts = nil)
210
- with_default_scope.last(limit_or_opts)
214
+ def last(limit = nil)
215
+ with_default_scope.last(limit)
211
216
  end
212
217
  end
213
218
  end
@@ -86,7 +86,7 @@ module Mongoid
86
86
  # @api private
87
87
  #
88
88
  # @example Normalize the index options.
89
- # specification.normalize_options(drop_dups: true)
89
+ # specification.normalize_options(unique: true)
90
90
  #
91
91
  # @param [ Hash ] opts The index options.
92
92
  #
@@ -13,7 +13,6 @@ module Mongoid
13
13
  :database,
14
14
  :default_language,
15
15
  :language_override,
16
- :drop_dups,
17
16
  :name,
18
17
  :sparse,
19
18
  :unique,
@@ -98,6 +97,10 @@ module Mongoid
98
97
  unless VALID_TYPES.include?(value)
99
98
  raise Errors::InvalidIndex.new(klass, spec, options)
100
99
  end
100
+
101
+ if value == "geoHaystack"
102
+ Mongoid::Warnings.warn_geo_haystack_deprecated
103
+ end
101
104
  end
102
105
  end
103
106
  end
@@ -27,7 +27,7 @@ module Mongoid
27
27
  :before_save,
28
28
  :before_update,
29
29
  :before_upsert,
30
- :before_validation
30
+ :before_validation,
31
31
  ].freeze
32
32
 
33
33
  included do
@@ -37,6 +37,12 @@ module Mongoid
37
37
  define_model_callbacks :build, :find, :initialize, :touch, only: :after
38
38
  define_model_callbacks :create, :destroy, :save, :update, :upsert
39
39
 
40
+ # This callback is used internally by Mongoid to save association
41
+ # targets for referenced associations after the parent model is persisted.
42
+ #
43
+ # @api private
44
+ define_model_callbacks :persist_parent
45
+
40
46
  attr_accessor :before_callback_halted
41
47
  end
42
48
 
@@ -109,22 +115,76 @@ module Mongoid
109
115
  # end
110
116
  #
111
117
  # @param [ Symbol ] kind The type of callback to execute.
112
- # @param [ Array ] args Any options.
113
- #
114
- # @return [ Document ] The document
115
- ruby2_keywords def run_callbacks(kind, *args, &block)
116
- cascadable_children(kind).each do |child|
117
- if child.run_callbacks(child_callback_type(kind, child), *args) == false
118
- return false
118
+ # @param [ true | false ] with_children Flag specifies whether callbacks of embedded document should be run.
119
+ def run_callbacks(kind, with_children: true, &block)
120
+ if with_children
121
+ cascadable_children(kind).each do |child|
122
+ if child.run_callbacks(child_callback_type(kind, child), with_children: with_children) == false
123
+ return false
124
+ end
119
125
  end
120
126
  end
121
127
  if callback_executable?(kind)
122
- super(kind, *args, &block)
128
+ super(kind, &block)
123
129
  else
124
130
  true
125
131
  end
126
132
  end
127
133
 
134
+ # Run the callbacks for embedded documents.
135
+ #
136
+ # @param [ Symbol ] kind The type of callback to execute.
137
+ # @param [ Array<Document> ] children Children to exeute callbacks on. If
138
+ # nil, callbacks will be executed on all cascadable children of
139
+ # the document.
140
+ #
141
+ # @api private
142
+ def _mongoid_run_child_callbacks(kind, children: nil, &block)
143
+ child, *tail = (children || cascadable_children(kind))
144
+ if child.nil?
145
+ return block&.call
146
+ elsif tail.empty?
147
+ return child.run_callbacks(child_callback_type(kind, child), &block)
148
+ else
149
+ return child.run_callbacks(child_callback_type(kind, child)) do
150
+ _mongoid_run_child_callbacks(kind, children: tail, &block)
151
+ end
152
+ end
153
+ end
154
+
155
+ # This is used to store callbacks to be executed later. A good use case for
156
+ # this is delaying the after_find and after_initialize callbacks until the
157
+ # associations are set on the document. This can also be used to delay
158
+ # applying the defaults on a document.
159
+ #
160
+ # @return [ Array<Symbol> ] an array of symbols that represent the pending callbacks.
161
+ #
162
+ # @api private
163
+ def pending_callbacks
164
+ @pending_callbacks ||= [].to_set
165
+ end
166
+
167
+ # @api private
168
+ def pending_callbacks=(value)
169
+ @pending_callbacks = value
170
+ end
171
+
172
+ # Run the pending callbacks. If the callback is :apply_defaults, we will apply
173
+ # the defaults for this document. Otherwise, the callback is passed to the
174
+ # run_callbacks function.
175
+ #
176
+ # @api private
177
+ def run_pending_callbacks
178
+ pending_callbacks.each do |cb|
179
+ if [:apply_defaults, :apply_post_processed_defaults].include?(cb)
180
+ send(cb)
181
+ else
182
+ self.run_callbacks(cb, with_children: false)
183
+ end
184
+ end
185
+ pending_callbacks.clear
186
+ end
187
+
128
188
  private
129
189
 
130
190
  # We need to hook into this for autosave, since we don't want it firing if
@@ -102,13 +102,22 @@ module Mongoid
102
102
  def prepare_insert(options = {})
103
103
  return self if performing_validations?(options) &&
104
104
  invalid?(options[:context] || :create)
105
- result = run_callbacks(:save) do
106
- run_callbacks(:create) do
107
- yield(self)
108
- post_process_insert
105
+ run_callbacks(:save, with_children: false) do
106
+ run_callbacks(:create, with_children: false) do
107
+ run_callbacks(:persist_parent, with_children: false) do
108
+ _mongoid_run_child_callbacks(:save) do
109
+ _mongoid_run_child_callbacks(:create) do
110
+ result = yield(self)
111
+ if !result.is_a?(Document) || result.errors.empty?
112
+ post_process_insert
113
+ post_process_persist(result, options)
114
+ end
115
+ end
116
+ end
117
+ end
109
118
  end
110
119
  end
111
- post_process_persist(result, options) and self
120
+ self
112
121
  end
113
122
 
114
123
  module ClassMethods
@@ -96,13 +96,20 @@ module Mongoid
96
96
  return false if performing_validations?(options) &&
97
97
  invalid?(options[:context] || :update)
98
98
  process_flagged_destroys
99
- result = run_callbacks(:save) do
100
- run_callbacks(:update) do
101
- yield(self)
102
- true
99
+ run_callbacks(:save, with_children: false) do
100
+ run_callbacks(:update, with_children: false) do
101
+ run_callbacks(:persist_parent, with_children: false) do
102
+ _mongoid_run_child_callbacks(:save) do
103
+ _mongoid_run_child_callbacks(:update) do
104
+ result = yield(self)
105
+ self.previously_new_record = false
106
+ post_process_persist(result, options)
107
+ true
108
+ end
109
+ end
110
+ end
103
111
  end
104
112
  end
105
- post_process_persist(result, options) and result
106
113
  end
107
114
 
108
115
  # Update the document in the database.
@@ -57,7 +57,9 @@ module Mongoid
57
57
  # @return [ Mongo::Collection ] The collection for this persistence
58
58
  # context.
59
59
  def collection(parent = nil)
60
- parent ? parent.collection.with(client_options) : client[collection_name.to_sym]
60
+ parent ?
61
+ parent.collection.with(client_options.except(:database, "database")) :
62
+ client[collection_name.to_sym]
61
63
  end
62
64
 
63
65
  # Get the collection name for this persistence context.
@@ -187,7 +189,8 @@ module Mongoid
187
189
  #
188
190
  # @return [ Mongoid::PersistenceContext ] The persistence context for the object.
189
191
  def set(object, options_or_context)
190
- existing_context = get_context(object)
192
+ key = "[mongoid][#{object.object_id}]:context"
193
+ existing_context = Thread.current[key]
191
194
  existing_options = if existing_context
192
195
  existing_context.options
193
196
  else
@@ -198,7 +201,7 @@ module Mongoid
198
201
  end
199
202
  new_options = existing_options.merge(options_or_context)
200
203
  context = PersistenceContext.new(object, new_options)
201
- store_context(object, context)
204
+ Thread.current[key] = context
202
205
  end
203
206
 
204
207
  # Get the persistence context for a particular class or model instance.
@@ -210,7 +213,7 @@ module Mongoid
210
213
  #
211
214
  # @return [ Mongoid::PersistenceContext ] The persistence context for the object.
212
215
  def get(object)
213
- get_context(object)
216
+ Thread.current["[mongoid][#{object.object_id}]:context"]
214
217
  end
215
218
 
216
219
  # Clear the persistence context for a particular class or model instance.
@@ -229,44 +232,7 @@ module Mongoid
229
232
  end
230
233
  end
231
234
  ensure
232
- store_context(object, original_context)
233
- end
234
-
235
- private
236
-
237
- # Key to store persistence contexts in the thread local storage.
238
- #
239
- # @api private
240
- PERSISTENCE_CONTEXT_KEY = :"[mongoid]:persistence_context"
241
-
242
- # Get the persistence context for a given object from the thread local
243
- # storage.
244
- #
245
- # @param [ Object ] object Object to get the persistance context for.
246
- #
247
- # @return [ Mongoid::PersistenceContext | nil ] The persistence context
248
- # for the object if previously stored, otherwise nil.
249
- #
250
- # @api private
251
- def get_context(object)
252
- Thread.current[PERSISTENCE_CONTEXT_KEY] ||= {}
253
- Thread.current[PERSISTENCE_CONTEXT_KEY][object.object_id]
254
- end
255
-
256
- # Store persistence context for a given object in the thread local
257
- # storage.
258
- #
259
- # @param [ Object ] object Object to store the persistance context for.
260
- # @param [ Mongoid::PersistenceContext ] context Context to store
261
- #
262
- # @api private
263
- def store_context(object, context)
264
- if context.nil?
265
- Thread.current[PERSISTENCE_CONTEXT_KEY]&.delete(object.object_id)
266
- else
267
- Thread.current[PERSISTENCE_CONTEXT_KEY] ||= {}
268
- Thread.current[PERSISTENCE_CONTEXT_KEY][object.object_id] = context
269
- end
235
+ Thread.current["[mongoid][#{object.object_id}]:context"] = original_context
270
236
  end
271
237
  end
272
238
  end