mongoid 7.4.0 → 8.0.3

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 (391) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +52 -28
  5. data/lib/mongoid/association/accessors.rb +38 -9
  6. data/lib/mongoid/association/bindable.rb +50 -2
  7. data/lib/mongoid/association/builders.rb +4 -2
  8. data/lib/mongoid/association/constrainable.rb +0 -1
  9. data/lib/mongoid/association/eager_loadable.rb +29 -7
  10. data/lib/mongoid/association/embedded/batchable.rb +53 -13
  11. data/lib/mongoid/association/embedded/cyclic.rb +1 -1
  12. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  13. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -2
  14. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  15. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  16. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  17. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +50 -28
  18. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  19. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  20. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +23 -4
  21. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  22. data/lib/mongoid/association/macros.rb +22 -1
  23. data/lib/mongoid/association/many.rb +11 -7
  24. data/lib/mongoid/association/nested/many.rb +5 -4
  25. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  26. data/lib/mongoid/association/nested/one.rb +5 -5
  27. data/lib/mongoid/association/one.rb +2 -2
  28. data/lib/mongoid/association/options.rb +9 -9
  29. data/lib/mongoid/association/proxy.rb +14 -3
  30. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  31. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  32. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  33. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  34. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  35. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  36. data/lib/mongoid/association/referenced/eager.rb +2 -2
  37. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +66 -13
  38. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  39. data/lib/mongoid/association/referenced/has_many/enumerable.rb +20 -24
  40. data/lib/mongoid/association/referenced/has_many/proxy.rb +24 -18
  41. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  42. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  43. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  44. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  45. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  46. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  47. data/lib/mongoid/association/reflections.rb +2 -2
  48. data/lib/mongoid/association/relatable.rb +44 -10
  49. data/lib/mongoid/association.rb +5 -5
  50. data/lib/mongoid/atomic/modifiers.rb +2 -2
  51. data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
  52. data/lib/mongoid/attributes/dynamic.rb +3 -3
  53. data/lib/mongoid/attributes/nested.rb +5 -5
  54. data/lib/mongoid/attributes/processing.rb +10 -3
  55. data/lib/mongoid/attributes/projector.rb +1 -1
  56. data/lib/mongoid/attributes/readonly.rb +2 -2
  57. data/lib/mongoid/attributes.rb +43 -40
  58. data/lib/mongoid/cacheable.rb +2 -2
  59. data/lib/mongoid/changeable.rb +42 -7
  60. data/lib/mongoid/clients/options.rb +5 -1
  61. data/lib/mongoid/clients/sessions.rb +2 -14
  62. data/lib/mongoid/clients/validators/storage.rb +3 -3
  63. data/lib/mongoid/config/environment.rb +20 -4
  64. data/lib/mongoid/config/validators/client.rb +6 -6
  65. data/lib/mongoid/config.rb +32 -17
  66. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  67. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  68. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  69. data/lib/mongoid/contextual/atomic.rb +1 -1
  70. data/lib/mongoid/contextual/geo_near.rb +7 -7
  71. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  72. data/lib/mongoid/contextual/memory.rb +180 -21
  73. data/lib/mongoid/contextual/mongo.rb +237 -217
  74. data/lib/mongoid/contextual/none.rb +67 -5
  75. data/lib/mongoid/contextual/queryable.rb +1 -1
  76. data/lib/mongoid/contextual.rb +2 -2
  77. data/lib/mongoid/copyable.rb +32 -8
  78. data/lib/mongoid/criteria/findable.rb +7 -4
  79. data/lib/mongoid/criteria/includable.rb +24 -20
  80. data/lib/mongoid/criteria/marshalable.rb +10 -2
  81. data/lib/mongoid/criteria/permission.rb +1 -1
  82. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  83. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -13
  84. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  85. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  86. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  87. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  88. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -14
  89. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  90. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  91. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  92. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  93. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  94. data/lib/mongoid/criteria/queryable/extensions/string.rb +3 -3
  95. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -2
  96. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  97. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  98. data/lib/mongoid/criteria/queryable/key.rb +3 -3
  99. data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
  100. data/lib/mongoid/criteria/queryable/optional.rb +5 -11
  101. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  102. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  103. data/lib/mongoid/criteria/queryable/selectable.rb +31 -37
  104. data/lib/mongoid/criteria/queryable/selector.rb +92 -7
  105. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  106. data/lib/mongoid/criteria/queryable.rb +12 -7
  107. data/lib/mongoid/criteria/scopable.rb +2 -2
  108. data/lib/mongoid/criteria.rb +15 -35
  109. data/lib/mongoid/deprecable.rb +36 -0
  110. data/lib/mongoid/deprecation.rb +25 -0
  111. data/lib/mongoid/document.rb +98 -34
  112. data/lib/mongoid/equality.rb +12 -12
  113. data/lib/mongoid/errors/document_not_found.rb +33 -12
  114. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  115. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  116. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  117. data/lib/mongoid/errors/invalid_field.rb +6 -2
  118. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  119. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  120. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  121. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  122. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  123. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  124. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  125. data/lib/mongoid/errors/no_client_database.rb +1 -1
  126. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  127. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  128. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  129. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  130. data/lib/mongoid/errors.rb +2 -2
  131. data/lib/mongoid/extensions/array.rb +9 -7
  132. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  133. data/lib/mongoid/extensions/binary.rb +42 -0
  134. data/lib/mongoid/extensions/boolean.rb +8 -2
  135. data/lib/mongoid/extensions/date.rb +26 -20
  136. data/lib/mongoid/extensions/date_time.rb +1 -1
  137. data/lib/mongoid/extensions/false_class.rb +1 -1
  138. data/lib/mongoid/extensions/float.rb +7 -4
  139. data/lib/mongoid/extensions/hash.rb +13 -6
  140. data/lib/mongoid/extensions/integer.rb +7 -4
  141. data/lib/mongoid/extensions/module.rb +1 -1
  142. data/lib/mongoid/extensions/object.rb +8 -6
  143. data/lib/mongoid/extensions/range.rb +41 -10
  144. data/lib/mongoid/extensions/regexp.rb +11 -4
  145. data/lib/mongoid/extensions/set.rb +11 -4
  146. data/lib/mongoid/extensions/string.rb +11 -22
  147. data/lib/mongoid/extensions/symbol.rb +4 -15
  148. data/lib/mongoid/extensions/time.rb +27 -16
  149. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  150. data/lib/mongoid/extensions/true_class.rb +1 -1
  151. data/lib/mongoid/extensions.rb +1 -0
  152. data/lib/mongoid/factory.rb +42 -7
  153. data/lib/mongoid/fields/foreign_key.rb +11 -4
  154. data/lib/mongoid/fields/localized.rb +9 -4
  155. data/lib/mongoid/fields/standard.rb +7 -7
  156. data/lib/mongoid/fields/validators/macro.rb +3 -9
  157. data/lib/mongoid/fields.rb +201 -35
  158. data/lib/mongoid/findable.rb +34 -13
  159. data/lib/mongoid/indexable/specification.rb +2 -2
  160. data/lib/mongoid/indexable/validators/options.rb +6 -2
  161. data/lib/mongoid/interceptable.rb +73 -13
  162. data/lib/mongoid/matchable.rb +1 -1
  163. data/lib/mongoid/matcher.rb +12 -7
  164. data/lib/mongoid/persistable/creatable.rb +18 -9
  165. data/lib/mongoid/persistable/deletable.rb +1 -1
  166. data/lib/mongoid/persistable/destroyable.rb +1 -1
  167. data/lib/mongoid/persistable/savable.rb +2 -2
  168. data/lib/mongoid/persistable/unsettable.rb +1 -1
  169. data/lib/mongoid/persistable/updatable.rb +19 -12
  170. data/lib/mongoid/persistable/upsertable.rb +2 -2
  171. data/lib/mongoid/persistable.rb +3 -3
  172. data/lib/mongoid/persistence_context.rb +63 -10
  173. data/lib/mongoid/query_cache.rb +8 -260
  174. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  175. data/lib/mongoid/reloadable.rb +7 -3
  176. data/lib/mongoid/scopable.rb +26 -22
  177. data/lib/mongoid/selectable.rb +1 -2
  178. data/lib/mongoid/serializable.rb +10 -6
  179. data/lib/mongoid/stateful.rb +35 -9
  180. data/lib/mongoid/tasks/database.rb +0 -2
  181. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  182. data/lib/mongoid/threaded.rb +12 -12
  183. data/lib/mongoid/timestamps/created.rb +1 -1
  184. data/lib/mongoid/timestamps/updated.rb +2 -2
  185. data/lib/mongoid/touchable.rb +2 -3
  186. data/lib/mongoid/traversable.rb +8 -4
  187. data/lib/mongoid/validatable/localizable.rb +1 -1
  188. data/lib/mongoid/validatable/macros.rb +0 -2
  189. data/lib/mongoid/validatable/presence.rb +2 -2
  190. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  191. data/lib/mongoid/validatable.rb +6 -6
  192. data/lib/mongoid/version.rb +1 -1
  193. data/lib/mongoid/warnings.rb +28 -0
  194. data/lib/mongoid.rb +2 -0
  195. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +11 -5
  196. data/spec/config/mongoid.yml +16 -0
  197. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  198. data/spec/integration/app_spec.rb +28 -26
  199. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  200. data/spec/integration/associations/embedded_dirty_spec.rb +28 -0
  201. data/spec/integration/associations/embedded_spec.rb +15 -0
  202. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  203. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  204. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  205. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  206. data/spec/integration/associations/has_one_spec.rb +97 -1
  207. data/spec/integration/associations/scope_option_spec.rb +1 -1
  208. data/spec/integration/callbacks_models.rb +95 -1
  209. data/spec/integration/callbacks_spec.rb +226 -4
  210. data/spec/integration/criteria/range_spec.rb +95 -1
  211. data/spec/integration/discriminator_key_spec.rb +115 -76
  212. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  213. data/spec/integration/i18n_fallbacks_spec.rb +1 -17
  214. data/spec/integration/matcher_examples_spec.rb +20 -13
  215. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  216. data/spec/integration/matcher_operator_spec.rb +3 -5
  217. data/spec/integration/persistence/range_field_spec.rb +350 -0
  218. data/spec/lite_spec_helper.rb +1 -1
  219. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  220. data/spec/mongoid/association/depending_spec.rb +9 -9
  221. data/spec/mongoid/association/eager_spec.rb +2 -1
  222. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  223. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  224. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  225. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  226. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +219 -8
  227. data/spec/mongoid/association/embedded/embeds_many_models.rb +157 -0
  228. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  229. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  230. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  231. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  232. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  233. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  234. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  235. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  236. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  237. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  238. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +67 -4
  239. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  240. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  241. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  242. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +8 -8
  243. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +82 -13
  244. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  245. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  246. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  247. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  248. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  249. data/spec/mongoid/association/syncable_spec.rb +14 -0
  250. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  251. data/spec/mongoid/atomic_spec.rb +22 -0
  252. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  253. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  254. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  255. data/spec/mongoid/attributes_spec.rb +524 -27
  256. data/spec/mongoid/cacheable_spec.rb +3 -3
  257. data/spec/mongoid/changeable_spec.rb +130 -13
  258. data/spec/mongoid/clients/factory_spec.rb +34 -42
  259. data/spec/mongoid/clients/options_spec.rb +1 -0
  260. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  261. data/spec/mongoid/clients_spec.rb +57 -2
  262. data/spec/mongoid/config/environment_spec.rb +39 -1
  263. data/spec/mongoid/config_spec.rb +104 -13
  264. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  265. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  266. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  267. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  268. data/spec/mongoid/contextual/memory_spec.rb +1336 -69
  269. data/spec/mongoid/contextual/mongo_spec.rb +1105 -174
  270. data/spec/mongoid/contextual/none_spec.rb +38 -0
  271. data/spec/mongoid/copyable_spec.rb +451 -1
  272. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  273. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  274. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  275. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  276. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  277. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  278. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  279. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  280. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  281. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  282. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  283. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  284. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  285. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  286. data/spec/mongoid/criteria/queryable/selectable_spec.rb +289 -124
  287. data/spec/mongoid/criteria/queryable/selector_spec.rb +14 -2
  288. data/spec/mongoid/criteria_projection_spec.rb +0 -1
  289. data/spec/mongoid/criteria_spec.rb +475 -1199
  290. data/spec/mongoid/document_fields_spec.rb +173 -24
  291. data/spec/mongoid/document_spec.rb +32 -41
  292. data/spec/mongoid/equality_spec.rb +12 -12
  293. data/spec/mongoid/errors/document_not_found_spec.rb +76 -0
  294. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  295. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  296. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  297. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  298. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  299. data/spec/mongoid/extensions/array_spec.rb +16 -2
  300. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  301. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  302. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  303. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  304. data/spec/mongoid/extensions/date_spec.rb +71 -1
  305. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  306. data/spec/mongoid/extensions/float_spec.rb +53 -74
  307. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  308. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  309. data/spec/mongoid/extensions/range_spec.rb +255 -54
  310. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  311. data/spec/mongoid/extensions/set_spec.rb +106 -0
  312. data/spec/mongoid/extensions/string_spec.rb +53 -25
  313. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  314. data/spec/mongoid/extensions/time_spec.rb +634 -66
  315. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  316. data/spec/mongoid/factory_spec.rb +61 -1
  317. data/spec/mongoid/fields/localized_spec.rb +37 -12
  318. data/spec/mongoid/fields_spec.rb +321 -50
  319. data/spec/mongoid/findable_spec.rb +80 -15
  320. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  321. data/spec/mongoid/indexable_spec.rb +39 -20
  322. data/spec/mongoid/interceptable_spec.rb +584 -5
  323. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  324. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  325. data/spec/mongoid/mongoizable_spec.rb +285 -0
  326. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  327. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  328. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  329. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  330. data/spec/mongoid/persistence_context_spec.rb +50 -1
  331. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  332. data/spec/mongoid/query_cache_spec.rb +0 -154
  333. data/spec/mongoid/reloadable_spec.rb +35 -2
  334. data/spec/mongoid/scopable_spec.rb +54 -16
  335. data/spec/mongoid/shardable_spec.rb +14 -0
  336. data/spec/mongoid/stateful_spec.rb +28 -0
  337. data/spec/mongoid/timestamps_spec.rb +390 -0
  338. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  339. data/spec/mongoid/touchable_spec.rb +116 -0
  340. data/spec/mongoid/touchable_spec_models.rb +12 -8
  341. data/spec/mongoid/traversable_spec.rb +4 -11
  342. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  343. data/spec/mongoid/validatable/uniqueness_spec.rb +59 -31
  344. data/spec/mongoid/warnings_spec.rb +35 -0
  345. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  346. data/spec/rails/mongoid_spec.rb +4 -16
  347. data/spec/shared/lib/mrss/constraints.rb +8 -16
  348. data/spec/shared/lib/mrss/docker_runner.rb +23 -3
  349. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  350. data/spec/shared/lib/mrss/lite_constraints.rb +32 -1
  351. data/spec/shared/share/Dockerfile.erb +34 -48
  352. data/spec/shared/shlib/config.sh +27 -0
  353. data/spec/shared/shlib/server.sh +32 -19
  354. data/spec/shared/shlib/set_env.sh +37 -0
  355. data/spec/support/constraints.rb +24 -0
  356. data/spec/support/macros.rb +55 -0
  357. data/spec/support/models/augmentation.rb +12 -0
  358. data/spec/support/models/band.rb +3 -0
  359. data/spec/support/models/catalog.rb +24 -0
  360. data/spec/support/models/circus.rb +3 -0
  361. data/spec/support/models/code.rb +2 -0
  362. data/spec/support/models/fanatic.rb +8 -0
  363. data/spec/support/models/implant.rb +9 -0
  364. data/spec/support/models/label.rb +2 -0
  365. data/spec/support/models/membership.rb +1 -0
  366. data/spec/support/models/passport.rb +9 -0
  367. data/spec/support/models/person.rb +1 -0
  368. data/spec/support/models/player.rb +2 -0
  369. data/spec/support/models/powerup.rb +12 -0
  370. data/spec/support/models/registry.rb +1 -0
  371. data/spec/support/models/school.rb +14 -0
  372. data/spec/support/models/shield.rb +18 -0
  373. data/spec/support/models/student.rb +14 -0
  374. data/spec/support/models/weapon.rb +12 -0
  375. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  376. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  377. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  378. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  379. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  380. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  381. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  382. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  383. data/spec/support/schema_maps/schema_map_local.json +18 -0
  384. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  385. data/spec/support/spec_config.rb +4 -0
  386. data.tar.gz.sig +0 -0
  387. metadata +682 -619
  388. metadata.gz.sig +0 -0
  389. data/lib/mongoid/errors/eager_load.rb +0 -23
  390. data/lib/mongoid/errors/invalid_value.rb +0 -17
  391. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -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.
@@ -142,7 +147,7 @@ module Mongoid
142
147
  # @example Apply all the non-proc defaults.
143
148
  # model.apply_pre_processed_defaults
144
149
  #
145
- # @return [ Array<String ] The names of the non-proc defaults.
150
+ # @return [ Array<String> ] The names of the non-proc defaults.
146
151
  def apply_pre_processed_defaults
147
152
  pre_processed_defaults.each do |name|
148
153
  apply_default(name)
@@ -154,8 +159,9 @@ module Mongoid
154
159
  # @example Apply all the proc defaults.
155
160
  # model.apply_post_processed_defaults
156
161
  #
157
- # @return [ Array<String ] The names of the proc defaults.
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
@@ -207,7 +214,7 @@ module Mongoid
207
214
  # @example Get the database field name.
208
215
  # model.database_field_name(:authorization)
209
216
  #
210
- # @param [ String, Symbol ] name The name to get.
217
+ # @param [ String | Symbol ] name The name to get.
211
218
  #
212
219
  # @return [ String ] The name of the field as it's stored in the db.
213
220
  def database_field_name(name)
@@ -222,7 +229,7 @@ module Mongoid
222
229
  # @param [ Field ] field The field.
223
230
  # @param [ Object ] value The current value.
224
231
  #
225
- # @return [ true, false ] If we set the field lazily.
232
+ # @return [ true | false ] If we set the field lazily.
226
233
  def lazy_settable?(field, value)
227
234
  !frozen? && value.nil? && field.lazy?
228
235
  end
@@ -234,11 +241,37 @@ module Mongoid
234
241
  # @example Is the document using object ids?
235
242
  # model.using_object_ids?
236
243
  #
237
- # @return [ true, false ] Using object ids.
244
+ # @return [ true | false ] Using object ids.
238
245
  def using_object_ids?
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
@@ -270,21 +303,64 @@ module Mongoid
270
303
  def options
271
304
  @options ||= {}
272
305
  end
273
- end
274
-
275
- module ClassMethods
276
306
 
277
- # Returns an array of names for the attributes available on this object.
307
+ # Traverse down the association tree and search for the field for the
308
+ # given key. To do this, split the key by '.' and for each part (meth) of
309
+ # the key:
278
310
  #
279
- # Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this
280
- # method to automatically wrap params in JSON requests.
311
+ # - If the meth is a field, yield the meth, field, and is_field as true.
312
+ # - If the meth is an association, update the klass to the association's
313
+ # klass, and yield the meth, klass, and is_field as false.
281
314
  #
282
- # @example Get the field names
283
- # Model.attribute_names
315
+ # The next iteration will use klass's fields and associations to continue
316
+ # traversing the tree.
284
317
  #
285
- # @return [ Array<String> ] The field names
286
- def attribute_names
287
- fields.keys
318
+ # @param [ String ] key The key used to search the association tree.
319
+ # @param [ Hash ] fields The fields to begin the search with.
320
+ # @param [ Hash ] associations The associations to begin the search with.
321
+ # @param [ Hash ] aliased_associations The alaised associations to begin
322
+ # the search with.
323
+ # @param [ Proc ] block The block takes in three paramaters, the current
324
+ # meth, the field or the relation, and whether the second parameter is a
325
+ # field or not.
326
+ #
327
+ # @return [ Field ] The field found for the given key at the end of the
328
+ # search. This will return nil if the last thing found is an association
329
+ # or no field was found for the given key.
330
+ #
331
+ # @api private
332
+ def traverse_association_tree(key, fields, associations, aliased_associations)
333
+ klass = nil
334
+ field = nil
335
+ key.split('.').each_with_index do |meth, i|
336
+ fs = i == 0 ? fields : klass&.fields
337
+ rs = i == 0 ? associations : klass&.relations
338
+ as = i == 0 ? aliased_associations : klass&.aliased_associations
339
+
340
+ # Associations can possibly have two "keys", their name and their alias.
341
+ # The fields name is what is used to store it in the klass's relations
342
+ # and field hashes, and the alias is what's used to store that field
343
+ # in the database. The key inputted to this function is the aliased
344
+ # key. We can convert them back to their names by looking in the
345
+ # aliased_associations hash.
346
+ aliased = meth
347
+ if as && a = as.fetch(meth, nil)
348
+ aliased = a.to_s
349
+ end
350
+
351
+ field = nil
352
+ klass = nil
353
+ if fs && f = fs[aliased]
354
+ field = f
355
+ yield(meth, f, true) if block_given?
356
+ elsif rs && rel = rs[aliased]
357
+ klass = rel.klass
358
+ yield(meth, rel, false) if block_given?
359
+ else
360
+ yield(meth, nil, false) if block_given?
361
+ end
362
+ end
363
+ field
288
364
  end
289
365
 
290
366
  # Get the name of the provided field as it is stored in the database.
@@ -292,16 +368,43 @@ module Mongoid
292
368
  # finds aliases for embedded documents and fields, delimited with
293
369
  # period "." character.
294
370
  #
295
- # @example Get the database field name of a field.
296
- # Model.database_field_name(:authorization)
371
+ # Note that this method returns the name of associations as they're
372
+ # stored in the database, whereas the `relations` hash uses their in-code
373
+ # aliases. In order to check for membership in the relations hash, you
374
+ # would first have to look up the string returned from this method in
375
+ # the aliased_associations hash.
376
+ #
377
+ # This method will not expand the alias of a belongs_to association that
378
+ # is not the last item. For example, if we had a School that has_many
379
+ # Students, and the field name passed was (from the Student's perspective):
380
+ #
381
+ # school._id
382
+ #
383
+ # The alias for a belongs_to association is that association's _id field.
384
+ # Therefore, expanding out this association would yield:
385
+ #
386
+ # school_id._id
387
+ #
388
+ # This is not the correct field name, because the intention here was not
389
+ # to get a property of the _id field. The intention was to get a property
390
+ # of the referenced document. Therefore, if a part of the name passed is
391
+ # a belongs_to association that is not the last part of the name, we
392
+ # won't expand its alias, and return:
297
393
  #
298
- # @example Get the database field name of an embedded field.
299
- # Model.database_field_name('customers.addresses.city')
394
+ # school._id
300
395
  #
301
- # @param [ String, Symbol ] name The name to get.
396
+ # If the belongs_to association is the last part of the name, we will
397
+ # pass back the _id field.
398
+ #
399
+ # @param [ String | Symbol ] name The name to get.
400
+ # @param [ Hash ] relations The associations.
401
+ # @param [ Hash ] alaiased_fields The aliased fields.
402
+ # @param [ Hash ] alaiased_associations The aliased associations.
302
403
  #
303
404
  # @return [ String ] The name of the field as stored in the database.
304
- def database_field_name(name)
405
+ #
406
+ # @api private
407
+ def database_field_name(name, relations, aliased_fields, aliased_associations)
305
408
  if Mongoid.broken_alias_handling
306
409
  return nil unless name
307
410
  normalized = name.to_s
@@ -310,31 +413,68 @@ module Mongoid
310
413
  return nil unless name.present?
311
414
  key = name.to_s
312
415
  segment, remaining = key.split('.', 2)
313
- segment = aliased_fields[segment]&.dup || segment
416
+
417
+ # Don't get the alias for the field when a belongs_to association
418
+ # is not the last item. Therefore, get the alias when one of the
419
+ # following is true:
420
+ # 1. This is the last item, i.e. there is no remaining.
421
+ # 2. It is not an association.
422
+ # 3. It is not a belongs association
423
+ if !remaining || !relations.key?(segment) || !relations[segment].is_a?(Association::Referenced::BelongsTo)
424
+ segment = aliased_fields[segment]&.dup || segment
425
+ end
426
+
314
427
  return segment unless remaining
315
428
 
316
429
  relation = relations[aliased_associations[segment] || segment]
317
430
  if relation
318
- "#{segment}.#{relation.klass.database_field_name(remaining)}"
431
+ k = relation.klass
432
+ "#{segment}.#{database_field_name(remaining, k.relations, k.aliased_fields, k.aliased_associations)}"
319
433
  else
320
434
  "#{segment}.#{remaining}"
321
435
  end
322
436
  end
323
437
  end
438
+ end
439
+
440
+ module ClassMethods
441
+
442
+ # Returns an array of names for the attributes available on this object.
443
+ #
444
+ # Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this
445
+ # method to automatically wrap params in JSON requests.
446
+ #
447
+ # @example Get the field names
448
+ # Model.attribute_names
449
+ #
450
+ # @return [ Array<String> ] The field names
451
+ def attribute_names
452
+ fields.keys
453
+ end
454
+
455
+ # Get the name of the provided field as it is stored in the database.
456
+ # Used in determining if the field is aliased or not.
457
+ #
458
+ # @param [ String | Symbol ] name The name to get.
459
+ #
460
+ # @return [ String ] The name of the field as it's stored in the db.
461
+ def database_field_name(name)
462
+ Fields.database_field_name(name, relations, aliased_fields, aliased_associations)
463
+ end
324
464
 
325
465
  # Defines all the fields that are accessible on the Document
326
466
  # For each field that is defined, a getter and setter will be
327
467
  # added as an instance method to the Document.
328
468
  #
329
469
  # @example Define a field.
330
- # field :score, :type => Integer, :default => 0
470
+ # field :score, type: Integer, default: 0
331
471
  #
332
472
  # @param [ Symbol ] name The name of the field.
333
473
  # @param [ Hash ] options The options to pass to the field.
334
474
  #
335
- # @option options [ Class ] :type The type of the field.
475
+ # @option options [ Class | Symbol | String ] :type The type of the field.
336
476
  # @option options [ String ] :label The label for the field.
337
- # @option options [ Object, Proc ] :default The field's default
477
+ # @option options [ Object | Proc ] :default The field's default.
338
478
  #
339
479
  # @return [ Field ] The generated field
340
480
  def field(name, options = {})
@@ -367,11 +507,28 @@ module Mongoid
367
507
  # @example Does this class use object ids?
368
508
  # person.using_object_ids?
369
509
  #
370
- # @return [ true, false ] If the class uses BSON::ObjectIds for the id.
510
+ # @return [ true | false ] If the class uses BSON::ObjectIds for the id.
371
511
  def using_object_ids?
372
512
  fields["_id"].object_id_field?
373
513
  end
374
514
 
515
+ # Traverse down the association tree and search for the field for the
516
+ # given key.
517
+ #
518
+ # @param [ String ] key The key used to search the association tree.
519
+ # @param [ Proc ] block The block takes in three paramaters, the current
520
+ # meth, the field or the relation, and whether the second parameter is a
521
+ # field or not.
522
+ #
523
+ # @return [ Field ] The field found for the given key at the end of the
524
+ # search. This will return nil if the last thing found is an association
525
+ # or no field was found for the given key.
526
+ #
527
+ # @api private
528
+ def traverse_association_tree(key, &block)
529
+ Fields.traverse_association_tree(key, fields, relations, aliased_associations, &block)
530
+ end
531
+
375
532
  protected
376
533
 
377
534
  # Add the defaults to the model. This breaks them up between ones that
@@ -479,9 +636,7 @@ module Mongoid
479
636
  if lazy_settable?(field, raw)
480
637
  write_attribute(name, field.eval_default(self))
481
638
  else
482
- value = field.demongoize(raw)
483
- attribute_will_change!(name) if value.resizable?
484
- value
639
+ process_raw_attribute(name.to_s, raw, field)
485
640
  end
486
641
  end
487
642
  end
@@ -573,10 +728,8 @@ module Mongoid
573
728
  generated_methods.module_eval do
574
729
  re_define_method("#{meth}_translations=") do |value|
575
730
  attribute_will_change!(name)
576
- if value
577
- value.update_values do |_value|
578
- field.type.mongoize(_value)
579
- end
731
+ value&.transform_values! do |_value|
732
+ field.type.mongoize(_value)
580
733
  end
581
734
  attributes[name] = value
582
735
  end
@@ -613,6 +766,19 @@ module Mongoid
613
766
  opts = options.merge(klass: self)
614
767
  type_mapping = TYPE_MAPPINGS[options[:type]]
615
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
616
782
  return Fields::Localized.new(name, opts) if options[:localize]
617
783
  return Fields::ForeignKey.new(name, opts) if options[:identity]
618
784
  Fields::Standard.new(name, opts)
@@ -38,12 +38,16 @@ module Mongoid
38
38
  :max,
39
39
  :min,
40
40
  :none,
41
+ :pick,
41
42
  :pluck,
42
43
  :read,
43
44
  :sum,
45
+ :take,
46
+ :take!,
47
+ :tally,
44
48
  :text_search,
45
49
  :update,
46
- :update_all
50
+ :update_all,
47
51
 
48
52
  # Returns a count of records in the database.
49
53
  # If you want to specify conditions use where.
@@ -72,7 +76,7 @@ module Mongoid
72
76
  # @example Are there no saved documents for this model?
73
77
  # Person.empty?
74
78
  #
75
- # @return [ true, false ] If the collection is empty.
79
+ # @return [ true | false ] If the collection is empty.
76
80
  def empty?
77
81
  count == 0
78
82
  end
@@ -83,7 +87,7 @@ module Mongoid
83
87
  # @example Do any documents exist for the conditions?
84
88
  # Person.exists?
85
89
  #
86
- # @return [ true, false ] If any documents exist for the conditions.
90
+ # @return [ true | false ] If any documents exist for the conditions.
87
91
  def exists?
88
92
  with_default_scope.exists?
89
93
  end
@@ -118,18 +122,32 @@ module Mongoid
118
122
  # strings will be transparently converted to +BSON::ObjectId+ instances
119
123
  # during query construction.
120
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
+ #
121
132
  # The +find+ method takes into account the default scope defined on the
122
133
  # model class, if any.
123
134
  #
124
- # @param [ Object | Array<Object> ] args The _id values to find or an
125
- # array thereof.
135
+ # @note Each argument can be an individual id, an array of ids or
136
+ # a nested array. Each array will be flattened.
137
+ #
138
+ # @param [ Object | Array<Object> ] *args The _id value(s) to find.
126
139
  #
127
140
  # @return [ Document | Array<Document> | nil ] A document or matching documents.
128
141
  #
129
142
  # @raise Errors::DocumentNotFound If not all documents are found and
130
143
  # the +raise_not_found_error+ Mongoid configuration option is truthy.
131
- def find(*args)
132
- with_default_scope.find(*args)
144
+ def find(*args, &block)
145
+ empty_or_proc = args.empty? || (args.length == 1 && args.first.is_a?(Proc))
146
+ if block_given? && empty_or_proc
147
+ with_default_scope.find(*args, &block)
148
+ else
149
+ with_default_scope.find(*args)
150
+ end
133
151
  end
134
152
 
135
153
  # Find the first +Document+ given the conditions.
@@ -145,7 +163,7 @@ module Mongoid
145
163
  # @raise [ Errors::DocumentNotFound ] If no document found
146
164
  # and Mongoid.raise_not_found_error is true.
147
165
  #
148
- # @return [ Document, nil ] A matching document.
166
+ # @return [ Document | nil ] A matching document.
149
167
  def find_by(attrs = {})
150
168
  result = where(attrs).find_first
151
169
  if result.nil? && Mongoid.raise_not_found_error
@@ -166,7 +184,6 @@ module Mongoid
166
184
  # @raise [ Errors::DocumentNotFound ] If no document found.
167
185
  #
168
186
  # @return [ Document ] A matching document.
169
- #
170
187
  def find_by!(attrs = {})
171
188
  result = where(attrs).find_first
172
189
  raise(Errors::DocumentNotFound.new(self, attrs)) unless result
@@ -179,9 +196,11 @@ module Mongoid
179
196
  # @example Find the first document.
180
197
  # Person.first
181
198
  #
199
+ # @param [ Integer ] limit The number of documents to return.
200
+ #
182
201
  # @return [ Document ] The first matching document.
183
- def first
184
- with_default_scope.first
202
+ def first(limit = nil)
203
+ with_default_scope.first(limit)
185
204
  end
186
205
  alias :one :first
187
206
 
@@ -190,9 +209,11 @@ module Mongoid
190
209
  # @example Find the last document.
191
210
  # Person.last
192
211
  #
212
+ # @param [ Integer ] limit The number of documents to return.
213
+ #
193
214
  # @return [ Document ] The last matching document.
194
- def last
195
- with_default_scope.last
215
+ def last(limit = nil)
216
+ with_default_scope.last(limit)
196
217
  end
197
218
  end
198
219
  end
@@ -27,7 +27,7 @@ module Mongoid
27
27
  #
28
28
  # @param [ Specification ] other The spec to compare against.
29
29
  #
30
- # @return [ true, false ] If the specs are equal.
30
+ # @return [ true | false ] If the specs are equal.
31
31
  def ==(other)
32
32
  fields == other.fields && key == other.key
33
33
  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,
@@ -29,7 +28,8 @@ module Mongoid
29
28
  :text_version,
30
29
  :version,
31
30
  :partial_filter_expression,
32
- :collation
31
+ :collation,
32
+ :wildcard_projection,
33
33
  ]
34
34
 
35
35
  VALID_TYPES = [
@@ -98,6 +98,10 @@ module Mongoid
98
98
  unless VALID_TYPES.include?(value)
99
99
  raise Errors::InvalidIndex.new(klass, spec, options)
100
100
  end
101
+
102
+ if value == "geoHaystack"
103
+ Mongoid::Warnings.warn_geo_haystack_deprecated
104
+ end
101
105
  end
102
106
  end
103
107
  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
 
@@ -47,7 +53,7 @@ module Mongoid
47
53
  #
48
54
  # @param [ Symbol ] kind The type of callback.
49
55
  #
50
- # @return [ true, false ] If the callback can be executed.
56
+ # @return [ true | false ] If the callback can be executed.
51
57
  def callback_executable?(kind)
52
58
  respond_to?("_#{kind}_callbacks")
53
59
  end
@@ -60,7 +66,7 @@ module Mongoid
60
66
  #
61
67
  # @param [ Symbol ] kind The callback kind.
62
68
  #
63
- # @return [ true, false ] If the document is in a callback state.
69
+ # @return [ true | false ] If the document is in a callback state.
64
70
  def in_callback_state?(kind)
65
71
  [ :create, :destroy ].include?(kind) || new_record? || flagged_for_destroy? || changed?
66
72
  end
@@ -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
@@ -135,7 +195,7 @@ module Mongoid
135
195
  # @example Was a before callback halted?
136
196
  # document.before_callback_halted?
137
197
  #
138
- # @return [ true, false ] If a before callback was halted.
198
+ # @return [ true | false ] If a before callback was halted.
139
199
  def before_callback_halted?
140
200
  !!@before_callback_halted
141
201
  end
@@ -175,7 +235,7 @@ module Mongoid
175
235
  # @param [ Symbol ] kind The type of callback.
176
236
  # @param [ Document ] child The child document.
177
237
  #
178
- # @return [ true, false ] If the child should fire the callback.
238
+ # @return [ true | false ] If the child should fire the callback.
179
239
  def cascadable_child?(kind, child, association)
180
240
  return false if kind == :initialize || kind == :find || kind == :touch
181
241
  return false if kind == :validate && association.validate?
@@ -15,7 +15,7 @@ module Mongoid
15
15
  #
16
16
  # @param [ Hash ] selector The MongoDB selector.
17
17
  #
18
- # @return [ true, false ] True if matches, false if not.
18
+ # @return [ true | false ] True if matches, false if not.
19
19
  def _matches?(selector)
20
20
  Matcher::Expression.matches?(self, selector)
21
21
  end