mongoid 7.5.0 → 8.0.2

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 (358) 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 +47 -30
  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 +2 -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 -28
  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/changeable.rb +42 -7
  59. data/lib/mongoid/clients/options.rb +5 -1
  60. data/lib/mongoid/clients/sessions.rb +2 -14
  61. data/lib/mongoid/clients/validators/storage.rb +3 -3
  62. data/lib/mongoid/config/validators/client.rb +6 -6
  63. data/lib/mongoid/config.rb +27 -17
  64. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  65. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  66. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  67. data/lib/mongoid/contextual/atomic.rb +1 -1
  68. data/lib/mongoid/contextual/geo_near.rb +7 -7
  69. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  70. data/lib/mongoid/contextual/memory.rb +59 -32
  71. data/lib/mongoid/contextual/mongo.rb +184 -256
  72. data/lib/mongoid/contextual/none.rb +34 -16
  73. data/lib/mongoid/contextual/queryable.rb +1 -1
  74. data/lib/mongoid/contextual.rb +2 -2
  75. data/lib/mongoid/copyable.rb +32 -8
  76. data/lib/mongoid/criteria/findable.rb +7 -4
  77. data/lib/mongoid/criteria/includable.rb +24 -20
  78. data/lib/mongoid/criteria/marshalable.rb +10 -2
  79. data/lib/mongoid/criteria/permission.rb +1 -1
  80. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  81. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -15
  82. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  83. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  84. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  85. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  86. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -16
  87. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  88. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  89. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  90. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  91. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  92. data/lib/mongoid/criteria/queryable/extensions/string.rb +3 -3
  93. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -2
  94. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  95. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  96. data/lib/mongoid/criteria/queryable/key.rb +3 -3
  97. data/lib/mongoid/criteria/queryable/optional.rb +5 -11
  98. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  99. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  100. data/lib/mongoid/criteria/queryable/selectable.rb +5 -27
  101. data/lib/mongoid/criteria/queryable/selector.rb +92 -7
  102. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  103. data/lib/mongoid/criteria/queryable.rb +12 -7
  104. data/lib/mongoid/criteria/scopable.rb +2 -2
  105. data/lib/mongoid/criteria.rb +15 -37
  106. data/lib/mongoid/deprecable.rb +36 -0
  107. data/lib/mongoid/deprecation.rb +25 -0
  108. data/lib/mongoid/document.rb +98 -36
  109. data/lib/mongoid/equality.rb +12 -12
  110. data/lib/mongoid/errors/document_not_found.rb +10 -6
  111. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  112. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  113. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  114. data/lib/mongoid/errors/invalid_field.rb +6 -2
  115. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  116. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  117. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  118. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  119. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  120. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  121. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  122. data/lib/mongoid/errors/no_client_database.rb +1 -1
  123. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  124. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  125. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  126. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  127. data/lib/mongoid/errors.rb +2 -2
  128. data/lib/mongoid/extensions/array.rb +9 -7
  129. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  130. data/lib/mongoid/extensions/binary.rb +42 -0
  131. data/lib/mongoid/extensions/boolean.rb +8 -2
  132. data/lib/mongoid/extensions/date.rb +26 -20
  133. data/lib/mongoid/extensions/date_time.rb +1 -1
  134. data/lib/mongoid/extensions/false_class.rb +1 -1
  135. data/lib/mongoid/extensions/float.rb +4 -5
  136. data/lib/mongoid/extensions/hash.rb +13 -6
  137. data/lib/mongoid/extensions/integer.rb +4 -5
  138. data/lib/mongoid/extensions/module.rb +1 -1
  139. data/lib/mongoid/extensions/object.rb +8 -6
  140. data/lib/mongoid/extensions/range.rb +41 -10
  141. data/lib/mongoid/extensions/regexp.rb +11 -4
  142. data/lib/mongoid/extensions/set.rb +11 -4
  143. data/lib/mongoid/extensions/string.rb +11 -22
  144. data/lib/mongoid/extensions/symbol.rb +4 -15
  145. data/lib/mongoid/extensions/time.rb +27 -16
  146. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  147. data/lib/mongoid/extensions/true_class.rb +1 -1
  148. data/lib/mongoid/extensions.rb +1 -0
  149. data/lib/mongoid/factory.rb +42 -7
  150. data/lib/mongoid/fields/foreign_key.rb +11 -4
  151. data/lib/mongoid/fields/localized.rb +2 -2
  152. data/lib/mongoid/fields/standard.rb +7 -7
  153. data/lib/mongoid/fields/validators/macro.rb +3 -9
  154. data/lib/mongoid/fields.rb +57 -15
  155. data/lib/mongoid/findable.rb +28 -22
  156. data/lib/mongoid/indexable/specification.rb +2 -2
  157. data/lib/mongoid/indexable/validators/options.rb +6 -2
  158. data/lib/mongoid/interceptable.rb +73 -13
  159. data/lib/mongoid/matchable.rb +1 -1
  160. data/lib/mongoid/matcher.rb +12 -7
  161. data/lib/mongoid/persistable/creatable.rb +18 -9
  162. data/lib/mongoid/persistable/deletable.rb +1 -1
  163. data/lib/mongoid/persistable/destroyable.rb +1 -1
  164. data/lib/mongoid/persistable/savable.rb +2 -2
  165. data/lib/mongoid/persistable/unsettable.rb +1 -1
  166. data/lib/mongoid/persistable/updatable.rb +19 -12
  167. data/lib/mongoid/persistable/upsertable.rb +1 -1
  168. data/lib/mongoid/persistable.rb +3 -3
  169. data/lib/mongoid/persistence_context.rb +22 -5
  170. data/lib/mongoid/query_cache.rb +8 -260
  171. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  172. data/lib/mongoid/reloadable.rb +7 -3
  173. data/lib/mongoid/scopable.rb +17 -15
  174. data/lib/mongoid/selectable.rb +1 -2
  175. data/lib/mongoid/serializable.rb +10 -6
  176. data/lib/mongoid/stateful.rb +35 -9
  177. data/lib/mongoid/tasks/database.rb +0 -2
  178. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  179. data/lib/mongoid/threaded.rb +9 -9
  180. data/lib/mongoid/timestamps/created.rb +1 -1
  181. data/lib/mongoid/timestamps/updated.rb +2 -2
  182. data/lib/mongoid/touchable.rb +2 -3
  183. data/lib/mongoid/traversable.rb +4 -3
  184. data/lib/mongoid/validatable/localizable.rb +1 -1
  185. data/lib/mongoid/validatable/macros.rb +0 -2
  186. data/lib/mongoid/validatable/presence.rb +2 -2
  187. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  188. data/lib/mongoid/validatable.rb +6 -6
  189. data/lib/mongoid/version.rb +1 -1
  190. data/lib/mongoid/warnings.rb +3 -4
  191. data/lib/mongoid.rb +1 -0
  192. data/spec/config/mongoid.yml +16 -0
  193. data/spec/integration/app_spec.rb +8 -12
  194. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  195. data/spec/integration/associations/embedded_spec.rb +15 -0
  196. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  197. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  198. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  199. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  200. data/spec/integration/associations/has_one_spec.rb +97 -1
  201. data/spec/integration/associations/scope_option_spec.rb +1 -1
  202. data/spec/integration/callbacks_models.rb +95 -1
  203. data/spec/integration/callbacks_spec.rb +226 -4
  204. data/spec/integration/criteria/range_spec.rb +95 -1
  205. data/spec/integration/discriminator_key_spec.rb +115 -76
  206. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  207. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  208. data/spec/integration/matcher_examples_spec.rb +20 -13
  209. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  210. data/spec/integration/matcher_operator_spec.rb +3 -5
  211. data/spec/integration/persistence/range_field_spec.rb +350 -0
  212. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  213. data/spec/mongoid/association/depending_spec.rb +9 -9
  214. data/spec/mongoid/association/eager_spec.rb +2 -1
  215. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  216. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  217. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  218. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  219. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +219 -8
  220. data/spec/mongoid/association/embedded/embeds_many_models.rb +157 -0
  221. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  222. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  223. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  224. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  225. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  226. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  227. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  228. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  229. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  230. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  231. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +67 -4
  232. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  233. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  234. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  235. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  236. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +82 -13
  237. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  238. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  239. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  240. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  241. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  242. data/spec/mongoid/association/syncable_spec.rb +14 -0
  243. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  244. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  245. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  246. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  247. data/spec/mongoid/attributes_spec.rb +524 -27
  248. data/spec/mongoid/changeable_spec.rb +130 -13
  249. data/spec/mongoid/clients/factory_spec.rb +23 -30
  250. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  251. data/spec/mongoid/clients_spec.rb +32 -2
  252. data/spec/mongoid/config_spec.rb +58 -13
  253. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  254. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  255. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  256. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  257. data/spec/mongoid/contextual/memory_spec.rb +521 -14
  258. data/spec/mongoid/contextual/mongo_spec.rb +564 -394
  259. data/spec/mongoid/contextual/none_spec.rb +11 -19
  260. data/spec/mongoid/copyable_spec.rb +451 -1
  261. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  262. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  263. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  264. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  265. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  266. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  267. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  268. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  269. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  270. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  271. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  272. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  273. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  274. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  275. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  276. data/spec/mongoid/criteria/queryable/selector_spec.rb +14 -2
  277. data/spec/mongoid/criteria_spec.rb +469 -1201
  278. data/spec/mongoid/document_fields_spec.rb +173 -24
  279. data/spec/mongoid/document_spec.rb +32 -41
  280. data/spec/mongoid/equality_spec.rb +12 -12
  281. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  282. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  283. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  284. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  285. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  286. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  287. data/spec/mongoid/extensions/array_spec.rb +16 -2
  288. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  289. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  290. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  291. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  292. data/spec/mongoid/extensions/date_spec.rb +71 -1
  293. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  294. data/spec/mongoid/extensions/float_spec.rb +48 -76
  295. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  296. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  297. data/spec/mongoid/extensions/range_spec.rb +255 -54
  298. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  299. data/spec/mongoid/extensions/set_spec.rb +106 -0
  300. data/spec/mongoid/extensions/string_spec.rb +53 -25
  301. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  302. data/spec/mongoid/extensions/time_spec.rb +634 -66
  303. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  304. data/spec/mongoid/factory_spec.rb +61 -1
  305. data/spec/mongoid/fields_spec.rb +321 -50
  306. data/spec/mongoid/findable_spec.rb +64 -29
  307. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  308. data/spec/mongoid/indexable_spec.rb +39 -20
  309. data/spec/mongoid/interceptable_spec.rb +584 -5
  310. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  311. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  312. data/spec/mongoid/mongoizable_spec.rb +285 -0
  313. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  314. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  315. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  316. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  317. data/spec/mongoid/persistence_context_spec.rb +50 -1
  318. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  319. data/spec/mongoid/query_cache_spec.rb +0 -154
  320. data/spec/mongoid/reloadable_spec.rb +35 -2
  321. data/spec/mongoid/scopable_spec.rb +54 -16
  322. data/spec/mongoid/shardable_spec.rb +14 -0
  323. data/spec/mongoid/stateful_spec.rb +28 -0
  324. data/spec/mongoid/timestamps_spec.rb +390 -0
  325. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  326. data/spec/mongoid/touchable_spec.rb +116 -0
  327. data/spec/mongoid/touchable_spec_models.rb +12 -8
  328. data/spec/mongoid/traversable_spec.rb +4 -11
  329. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  330. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  331. data/spec/mongoid/warnings_spec.rb +35 -0
  332. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  333. data/spec/rails/mongoid_spec.rb +4 -16
  334. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  335. data/spec/support/constraints.rb +24 -0
  336. data/spec/support/macros.rb +30 -0
  337. data/spec/support/models/augmentation.rb +12 -0
  338. data/spec/support/models/band.rb +3 -0
  339. data/spec/support/models/catalog.rb +24 -0
  340. data/spec/support/models/circus.rb +3 -0
  341. data/spec/support/models/fanatic.rb +8 -0
  342. data/spec/support/models/implant.rb +9 -0
  343. data/spec/support/models/label.rb +2 -0
  344. data/spec/support/models/passport.rb +9 -0
  345. data/spec/support/models/person.rb +1 -0
  346. data/spec/support/models/player.rb +2 -0
  347. data/spec/support/models/powerup.rb +12 -0
  348. data/spec/support/models/registry.rb +1 -0
  349. data/spec/support/models/school.rb +14 -0
  350. data/spec/support/models/shield.rb +18 -0
  351. data/spec/support/models/student.rb +14 -0
  352. data/spec/support/models/weapon.rb +12 -0
  353. data.tar.gz.sig +0 -0
  354. metadata +49 -13
  355. metadata.gz.sig +0 -0
  356. data/lib/mongoid/errors/eager_load.rb +0 -23
  357. data/lib/mongoid/errors/invalid_value.rb +0 -17
  358. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32597c6d6b536f273850be1989db0d876026d2bffda067d7923f173c3966faa6
4
- data.tar.gz: 97fffa62c90ae5c20e7dcf00eb151b557c26ab5ae676c45b5651efa5143cf34c
3
+ metadata.gz: 9c2c1f57188d73b1d7f6d965b01a05cd97ddab316855221e6b23f70858e820af
4
+ data.tar.gz: 0ad8309b683b8031796d3e3d99c36840481b7b2cc8aa773e32c4d1b050380671
5
5
  SHA512:
6
- metadata.gz: dbe0c003a7e058f5ab6ac5592170ef1a26e02bf9be729b889c55a3a70af4e0c8b6e52f7157cc9b40879545689972769bae5deabf6814ce1ebeb97fdf1a128212
7
- data.tar.gz: d696cd95560d51b34318e7f25467450dde8461383dd17830f1177363cbf006c863b1268a2b79616e563343a3fd0e388c9d3bde67821b698b4cf0035bbfc9b719
6
+ metadata.gz: 00ca56917eafe55f9b4ef394569ac8a64023c67906fdd65522d74a95046a7cacab42ca11baea2917e80f803cadc9c7d484e170227fcdf48a14a8656e96639fdb
7
+ data.tar.gz: 159b5215f615ca52777a81127e8312767d4e66adbb77e047d01769ed90281ef4959de4bda42e5ce2eadd9803e4a3d11f5d3d50c8da467241f3dd16bd90f69226
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -19,9 +19,9 @@ Compatibility
19
19
 
20
20
  Mongoid supports and is tested against:
21
21
 
22
- - MRI 2.5 - 3.1
23
- - JRuby 9.2
24
- - MongoDB server 2.6 - 6.0
22
+ - MRI 2.6 - 3.1
23
+ - JRuby 9.3
24
+ - MongoDB server 3.6 - 6.0
25
25
 
26
26
  Issues
27
27
  ------
@@ -1,4 +1,8 @@
1
1
  en:
2
+ errors:
3
+ messages:
4
+ taken: "has already been taken"
5
+
2
6
  mongoid:
3
7
  errors:
4
8
  messages:
@@ -61,7 +65,7 @@ en:
61
65
  and the following ids were not found: %{missing}."
62
66
  resolution: "Search for an id that is in the database or set
63
67
  the Mongoid.raise_not_found_error configuration option to false,
64
- which will cause a nil to be returned instead of raising this error when
68
+ which will cause nil to be returned instead of raising this error when
65
69
  searching for a single id, or only the matched documents when searching
66
70
  for multiples."
67
71
  document_with_attributes_not_found:
@@ -71,15 +75,17 @@ en:
71
75
  will be raised."
72
76
  resolution: "Search for attributes that are in the database or set
73
77
  the Mongoid.raise_not_found_error configuration option to false,
74
- which will cause a nil to be returned instead of raising this error."
75
- eager_load:
76
- message: "Eager loading :%{name} is not supported since it is a
77
- polymorphic belongs_to association."
78
- summary: "Mongoid cannot currently determine the classes it needs to
79
- eager load when the association is polymorphic. The parents reside in
80
- different collections so a simple id lookup is not sufficient enough."
81
- resolution: "Don't attempt to perform this action and have patience,
82
- maybe this will be supported in the future."
78
+ which will cause nil to be returned instead of raising this error."
79
+ document_with_shard_key_not_found:
80
+ message: "Document not found for class %{klass} with id %{missing} and
81
+ shard key %{shard_key}."
82
+ summary: "When calling %{klass}.find with an id and a shard key, each
83
+ parameter must match a document in the database or this error will
84
+ be raised. The search was for the id: %{missing} with
85
+ shard_key: %{shard_key} and it was not found."
86
+ resolution: "Search for an id/shard key that is in the database or set
87
+ the Mongoid.raise_not_found_error configuration option to false,
88
+ which will cause nil to be returned instead of raising this error."
83
89
  empty_config_file:
84
90
  message: "Empty configuration file: %{path}."
85
91
  summary: "Your mongoid.yml configuration file appears to be empty."
@@ -126,6 +132,17 @@ en:
126
132
  allowed."
127
133
  resolution: "Try setting the discriminator key on %{superclass} or one of %{class_name}'s
128
134
  ancestors."
135
+ invalid_dot_dollar_assignment:
136
+ message: "Cannot set the %{attr} attribute on the %{klass} class."
137
+ summary: "Calling the setters for fields that start with a dollar
138
+ sign ($) or contain a dot/period (.) is prohibited. See the
139
+ Mongoid documentation on Field Names with Dots/Periods (.) and
140
+ Dollar Signs ($) for more information."
141
+ resolution: "In order to set fields that start with a dollar
142
+ sign ($) or contain a dot/period (.), the aggregation pipeline can
143
+ be used. MongoDB provides specific operators for working with these
144
+ fields. Refer to the MongoDB documentation here:
145
+ https://www.mongodb.com/docs/manual/core/dot-dollar-considerations/"
129
146
  invalid_elem_match_operator:
130
147
  message: "Invalid $elemMatch operator '%{operator}'."
131
148
  summary: "You misspelled an operator or are using an operator that
@@ -146,7 +163,7 @@ en:
146
163
  resolution: "Valid expression operators are: %{valid_operators}.
147
164
  Ensure you are using one of these operators."
148
165
  invalid_field:
149
- message: "Defining a field named '%{name}' is not allowed."
166
+ message: "Defining a field named '%{field}' is not allowed."
150
167
  summary: "Defining this field would override the method '%{name}',
151
168
  which would cause issues with expectations around the original
152
169
  method and cause extremely hard to debug issues. The original
@@ -181,6 +198,13 @@ en:
181
198
  \_\_end\n\n
182
199
  Refer to:
183
200
  https://docs.mongodb.com/mongoid/current/reference/fields/#custom-field-options"
201
+ invalid_field_type:
202
+ message: "Invalid field type %{type_inspection} for field '%{field}' on model '%{klass}'."
203
+ summary: "Model '%{klass}' defines a field '%{field}' with an unknown type value
204
+ %{type_inspection}."
205
+ resolution: "Please provide a valid type value for the field.
206
+ Refer to:
207
+ https://docs.mongodb.com/mongoid/current/reference/fields/#using-symbols-or-strings-instead-of-classes"
184
208
  invalid_includes:
185
209
  message: "Invalid includes directive: %{klass}.includes(%{args})"
186
210
  summary: "Eager loading in Mongoid only supports providing arguments
@@ -196,7 +220,6 @@ en:
196
220
  Valid options are:\n
197
221
  \_\_background: true|false\n
198
222
  \_\_database: 'database_name'\n
199
- \_\_drop_dups: true|false\n
200
223
  \_\_name: 'index_name'\n
201
224
  \_\_sparse: true|false\n
202
225
  \_\_unique: true|false\n
@@ -215,7 +238,8 @@ en:
215
238
  \_\_language_override\n
216
239
  \_\_default_language\n
217
240
  \_\_collation\n
218
- Valid types are: 1, -1, '2d', '2dsphere', 'geoHaystack', 'text', 'hashed'\n\n
241
+ \_\_wildcard_projection: { 'path.to.field.a': 1, 'path.to.field.b': 0 }\n
242
+ Valid types are: 1, -1, '2d', '2dsphere', 'geoHaystack (deprecated)', 'text', 'hashed'\n\n
219
243
  Example:\n
220
244
  \_\_class Band\n
221
245
  \_\_\_\_include Mongoid::Document\n
@@ -349,10 +373,6 @@ en:
349
373
  from the child side which association to go in."
350
374
  resolution: "Set the values from the parent, or redefine the association
351
375
  with only a single definition in the parent."
352
- invalid_value:
353
- message: "Value of type %{value_class} cannot be written to a field of type %{field_class}"
354
- summary: "Tried to set a value of type %{value_class} to a field of type %{field_class}"
355
- resolution: "Verify if the value to be set correspond to field definition"
356
376
  mixed_relations:
357
377
  message: "Referencing a(n) %{embedded} document from the %{root}
358
378
  document via a non-embedded association is not allowed since the
@@ -409,19 +429,18 @@ en:
409
429
  summary: "Mongoid attempted to find a document of the class %{klass}
410
430
  but none exist."
411
431
  resolution: "Create a document of class %{klass} or use a finder
412
- method that returns nil when no documents are found instead of
413
- raising an exception."
432
+ method that does not raise an exception when no documents are
433
+ found."
414
434
  no_environment:
415
435
  message: "Could not load the configuration since no environment
416
436
  was defined."
417
- summary: "Mongoid attempted to find the appropriate environment
418
- but no Rails.env, Sinatra::Base.environment, RACK_ENV, or
419
- MONGOID_ENV could be found."
420
- resolution: "Make sure some environment is set from the mentioned
421
- options. Mongoid cannot load configuration from the yaml without
422
- knowing which environment it is in, and we have considered
423
- defaulting to development an undesirable side effect of this not
424
- being defined."
437
+ summary: "Mongoid could not determine the environment to use because
438
+ it was not specified in any of the following locations:
439
+ Rails.env, Sinatra::Base.environment,
440
+ ENV[\"RACK_ENV\"], ENV[\"MONGOID_ENV\"]. Without knowing the
441
+ environment, Mongoid cannot load its configuration."
442
+ resolution: "Please ensure an environment is set in one of the
443
+ listed locations. The environment must be explicitly set."
425
444
  no_map_reduce_output:
426
445
  message: "No output location was specified for the map/reduce
427
446
  operation."
@@ -548,11 +567,9 @@ en:
548
567
  server versions 3.6 and higher."
549
568
  resolution: "Verify that all servers in your deployment are at least
550
569
  version 3.6 or don't attempt to use sessions with older server versions."
551
- taken:
552
- "is already taken"
553
570
  too_many_nested_attribute_records:
554
571
  message: "Accepting nested attributes for %{association} is limited
555
- to %{limit} records."
572
+ to %{limit} documents."
556
573
  summary: "More documents were sent to be processed than the allowed
557
574
  limit."
558
575
  resolution: "The limit is set as an option to the macro, for example:
@@ -15,8 +15,8 @@ module Mongoid
15
15
  # @example Build the association.
16
16
  # person.__build__(:addresses, { :_id => 1 }, association)
17
17
  #
18
- # @param [ String, Symbol ] name The name of the association.
19
- # @param [ Hash, BSON::ObjectId ] object The id or attributes to use.
18
+ # @param [ String | Symbol ] name The name of the association.
19
+ # @param [ Hash | BSON::ObjectId ] object The id or attributes to use.
20
20
  # @param [ Association ] association The association metadata.
21
21
  # @param [ Hash ] selected_fields Fields which were retrieved via #only.
22
22
  # If selected_fields is specified, fields not listed in it will not be
@@ -33,7 +33,7 @@ module Mongoid
33
33
  # @example Create the association.
34
34
  # person.create_relation(document, association)
35
35
  #
36
- # @param [ Document, Array<Document> ] object The association target.
36
+ # @param [ Document | Array<Document> ] object The association target.
37
37
  # @param [ Association ] association The association metadata.
38
38
  # @param [ Hash ] selected_fields Fields which were retrieved via #only.
39
39
  # If selected_fields is specified, fields not listed in it will not be
@@ -42,8 +42,23 @@ module Mongoid
42
42
  # @return [ Proxy ] The association.
43
43
  def create_relation(object, association, selected_fields = nil)
44
44
  type = @attributes[association.inverse_type]
45
- target = association.build(self, object, type, selected_fields)
46
- target ? association.create_relation(self, target) : nil
45
+ target = if t = association.build(self, object, type, selected_fields)
46
+ association.create_relation(self, t)
47
+ else
48
+ nil
49
+ end
50
+
51
+ # Only need to do this on embedded associations. The pending callbacks
52
+ # are only added when materializing the documents, which only happens
53
+ # on embedded associations. There is no call to the database in the
54
+ # construction of a referenced association.
55
+ if association.embedded?
56
+ Array(target).each do |doc|
57
+ doc.try(:run_pending_callbacks)
58
+ end
59
+ end
60
+
61
+ target
47
62
  end
48
63
 
49
64
  # Resets the criteria inside the association proxy. Used by many-to-many
@@ -65,7 +80,7 @@ module Mongoid
65
80
  # @example Set the proxy on the document.
66
81
  # person.set(:addresses, addresses)
67
82
  #
68
- # @param [ String, Symbol ] name The name of the association.
83
+ # @param [ String | Symbol ] name The name of the association.
69
84
  # @param [ Proxy ] relation The association to set.
70
85
  #
71
86
  # @return [ Proxy ] The association.
@@ -86,10 +101,23 @@ module Mongoid
86
101
  # @param [ Symbol ] name The name of the association.
87
102
  # @param [ Association ] association The association metadata.
88
103
  # @param [ Object ] object The object used to build the association.
89
- # @param [ true, false ] reload If the association is to be reloaded.
104
+ # @param [ true | false ] reload If the association is to be reloaded.
90
105
  #
91
106
  # @return [ Proxy ] The association.
92
107
  def get_relation(name, association, object, reload = false)
108
+ field_name = database_field_name(name)
109
+
110
+ # As per the comments under MONGOID-5034, I've decided to only raise on
111
+ # embedded associations for a missing attribute. Rails does not raise
112
+ # for a missing attribute on referenced associations.
113
+ # We also don't want to raise if we're retrieving an association within
114
+ # the codebase. This is often done when retrieving the inverse association
115
+ # during binding or when cascading callbacks. Whenever we retrieve
116
+ # associations within the codebase, we use without_autobuild.
117
+ if !without_autobuild? && association.embedded? && attribute_missing?(field_name)
118
+ raise ActiveModel::MissingAttributeError, "Missing attribute: '#{field_name}'"
119
+ end
120
+
93
121
  if !reload && (value = ivar(name)) != false
94
122
  value
95
123
  else
@@ -197,7 +225,7 @@ module Mongoid
197
225
  # @example Is autobuild disabled?
198
226
  # document.without_autobuild?
199
227
  #
200
- # @return [ true, false ] If autobuild is disabled.
228
+ # @return [ true | false ] If autobuild is disabled.
201
229
  def without_autobuild?
202
230
  Threaded.executing?(:without_autobuild)
203
231
  end
@@ -291,7 +319,7 @@ module Mongoid
291
319
  ids_method = "#{association.name.to_s.singularize}_ids"
292
320
  association.inverse_class.tap do |klass|
293
321
  klass.re_define_method(ids_method) do
294
- send(association.name).only(:_id).map(&:_id)
322
+ send(association.name).pluck(:_id)
295
323
  end
296
324
  end
297
325
  end
@@ -341,6 +369,7 @@ module Mongoid
341
369
  # @return [ Class ] The class being set up.
342
370
  def self.define_ids_setter!(association)
343
371
  ids_method = "#{association.name.to_s.singularize}_ids="
372
+ association.inverse_class.aliased_associations[ids_method.chop] = association.name.to_s
344
373
  association.inverse_class.tap do |klass|
345
374
  klass.re_define_method(ids_method) do |ids|
346
375
  send(association.setter, association.relation_class.find(ids.reject(&:blank?)))
@@ -15,7 +15,7 @@ module Mongoid
15
15
  # Binding.new(base, target, association)
16
16
  #
17
17
  # @param [ Document ] base The base of the binding.
18
- # @param [ Document, Array<Document> ] target The target of the binding.
18
+ # @param [ Document | Array<Document> ] target The target of the binding.
19
19
  # @param [ Association ] association The association metadata.
20
20
  def initialize(base, target, association)
21
21
  @_base, @_target, @_association = base, target, association
@@ -60,6 +60,53 @@ module Mongoid
60
60
  end
61
61
  end
62
62
 
63
+ # Remove the associated document from the inverse's association.
64
+ #
65
+ # @param [ Document ] doc The document to remove.
66
+ def remove_associated(doc)
67
+ if inverse = _association.inverse(doc)
68
+ if _association.many?
69
+ remove_associated_many(doc, inverse)
70
+ elsif _association.in_to?
71
+ remove_associated_in_to(doc, inverse)
72
+ end
73
+ end
74
+ end
75
+
76
+ # Remove the associated document from the inverse's association.
77
+ #
78
+ # This method removes the associated on *_many relationships.
79
+ #
80
+ # @param [ Document ] doc The document to remove.
81
+ # @param [ Symbol ] inverse The name of the inverse.
82
+ def remove_associated_many(doc, inverse)
83
+ # We only want to remove the inverse association when the inverse
84
+ # document is in memory.
85
+ if inv = doc.ivar(inverse)
86
+ # This first condition is needed because when assigning the
87
+ # embeds_many association using the same embeds_many
88
+ # association, we delete from the array we are about to assign.
89
+ if _base != inv && (associated = inv.ivar(_association.name))
90
+ associated.delete(doc)
91
+ end
92
+ end
93
+ end
94
+
95
+ # Remove the associated document from the inverse's association.
96
+ #
97
+ # This method removes associated on belongs_to and embedded_in
98
+ # associations.
99
+ #
100
+ # @param [ Document ] doc The document to remove.
101
+ # @param [ Symbol ] inverse The name of the inverse.
102
+ def remove_associated_in_to(doc, inverse)
103
+ # We only want to remove the inverse association when the inverse
104
+ # document is in memory.
105
+ if associated = doc.ivar(inverse)
106
+ associated.send(_association.setter, nil)
107
+ end
108
+ end
109
+
63
110
  # Set the id of the related document in the foreign key field on the
64
111
  # keyed document.
65
112
  #
@@ -134,6 +181,7 @@ module Mongoid
134
181
  # @param [ Document ] doc The document to bind.
135
182
  def bind_from_relational_parent(doc)
136
183
  check_inverse!(doc)
184
+ remove_associated(doc)
137
185
  bind_foreign_key(doc, record_id(_base))
138
186
  bind_polymorphic_type(doc, _base.class.name)
139
187
  bind_inverse(doc, _base)
@@ -152,7 +200,7 @@ module Mongoid
152
200
  # @example Set the base association.
153
201
  # binding.set_base_association
154
202
  #
155
- # @return [ true, false ] If the association changed.
203
+ # @return [ true | false ] If the association changed.
156
204
  def set_base_association
157
205
  inverse_association = _association.inverse_association(_target)
158
206
  if inverse_association != _association && !inverse_association.nil?
@@ -46,9 +46,10 @@ module Mongoid
46
46
  association.inverse_class.tap do |klass|
47
47
  klass.re_define_method("build_#{association.name}") do |*args|
48
48
  attributes, _options = parse_args(*args)
49
- document = Factory.build(association.relation_class, attributes)
49
+ document = Factory.execute_build(association.relation_class, attributes, execute_callbacks: false)
50
50
  _building do
51
51
  child = send("#{association.name}=", document)
52
+ child.run_pending_callbacks
52
53
  child.run_callbacks(:build)
53
54
  child
54
55
  end
@@ -69,10 +70,11 @@ module Mongoid
69
70
  association.inverse_class.tap do |klass|
70
71
  klass.re_define_method("create_#{association.name}") do |*args|
71
72
  attributes, _options = parse_args(*args)
72
- document = Factory.build(association.relation_class, attributes)
73
+ document = Factory.execute_build(association.relation_class, attributes, execute_callbacks: false)
73
74
  doc = _assigning do
74
75
  send("#{association.name}=", document)
75
76
  end
77
+ doc.run_pending_callbacks
76
78
  doc.save
77
79
  save if new_record? && association.stores_foreign_key?
78
80
  doc
@@ -5,7 +5,6 @@ module Mongoid
5
5
 
6
6
  # Used for converting foreign key values to the correct type based on the
7
7
  # types of ids that the document stores.
8
- #
9
8
  module Constrainable
10
9
 
11
10
  # Convert the supplied object to the appropriate type to set as the
@@ -20,13 +20,35 @@ module Mongoid
20
20
  end
21
21
  end
22
22
 
23
- def preload(relations, docs)
24
- relations.group_by(&:inverse_class_name)
25
- .values
26
- .each do |associations|
27
- associations.group_by(&:relation)
28
- .each do |relation, association|
29
- relation.eager_loader(association, docs).run
23
+ # Load the associations for the given documents. This will be done
24
+ # recursively to load the associations of the given documents'
25
+ # subdocuments.
26
+ #
27
+ # @param [ Array<Association> ] associations The associations to load.
28
+ # @param [ Array<Document> ] document The documents.
29
+ def preload(associations, docs)
30
+ assoc_map = associations.group_by(&:inverse_class_name)
31
+ docs_map = {}
32
+ queue = [ klass.to_s ]
33
+
34
+ while klass = queue.shift
35
+ if as = assoc_map.delete(klass)
36
+ as.each do |assoc|
37
+ queue << assoc.class_name
38
+
39
+ # If this class is nested in the inclusion tree, only load documents
40
+ # for the association above it. If there is no parent association,
41
+ # we will include documents from the documents passed to this method.
42
+ ds = docs
43
+ if assoc.parent_inclusions.length > 0
44
+ ds = assoc.parent_inclusions.map{ |p| docs_map[p].to_a }.flatten
45
+ end
46
+
47
+ res = assoc.relation.eager_loader([assoc], ds).run
48
+
49
+ docs_map[assoc.name] ||= [].to_set
50
+ docs_map[assoc.name].merge(res)
51
+ end
30
52
  end
31
53
  end
32
54
  end
@@ -50,7 +50,7 @@ module Mongoid
50
50
  _unscoped.clear
51
51
  end
52
52
 
53
- # Batch remove the provided documents as a $pullAll.
53
+ # Batch remove the provided documents as a $pullAll or $pull.
54
54
  #
55
55
  # @example Batch remove the documents.
56
56
  # batchable.batch_remove([ doc_one, doc_two ])
@@ -58,13 +58,36 @@ module Mongoid
58
58
  # @param [ Array<Document> ] docs The docs to remove.
59
59
  # @param [ Symbol ] method Delete or destroy.
60
60
  def batch_remove(docs, method = :delete)
61
+ # If the _id is nil, we cannot use $pull and delete by searching for
62
+ # the id. Therefore we have to use pullAll with the documents'
63
+ # attributes.
61
64
  removals = pre_process_batch_remove(docs, method)
65
+ pulls, pull_alls = removals.partition { |o| !o["_id"].nil? }
66
+
67
+ if !_base.persisted?
68
+ post_process_batch_remove(docs, method) unless docs.empty?
69
+ return reindex
70
+ end
71
+
62
72
  if !docs.empty?
63
- collection.find(selector).update_one(
64
- positionally(selector, "$pullAll" => { path => removals }),
73
+ if !pulls.empty?
74
+ collection.find(selector).update_one(
75
+ positionally(selector, "$pull" => { path => { "_id" => { "$in" => pulls.pluck("_id") } } }),
65
76
  session: _session
66
- )
77
+ )
78
+ end
79
+ if !pull_alls.empty?
80
+ collection.find(selector).update_one(
81
+ positionally(selector, "$pullAll" => { path => pull_alls }),
82
+ session: _session
83
+ )
84
+ end
67
85
  post_process_batch_remove(docs, method)
86
+ else
87
+ collection.find(selector).update_one(
88
+ positionally(selector, "$set" => { path => [] }),
89
+ session: _session
90
+ )
68
91
  end
69
92
  reindex
70
93
  end
@@ -80,7 +103,8 @@ module Mongoid
80
103
  def batch_replace(docs)
81
104
  if docs.blank?
82
105
  if _assigning? && !empty?
83
- _base.delayed_atomic_sets.clear
106
+ _base.delayed_atomic_sets.delete(path)
107
+ clear_atomic_path_cache
84
108
  _base.add_atomic_unset(first)
85
109
  target_duplicate = _target.dup
86
110
  pre_process_batch_remove(target_duplicate, :delete)
@@ -89,10 +113,11 @@ module Mongoid
89
113
  batch_remove(_target.dup)
90
114
  end
91
115
  elsif _target != docs
92
- _base.delayed_atomic_sets.clear unless _assigning?
116
+ _base.delayed_atomic_sets.delete(path) unless _assigning?
93
117
  docs = normalize_docs(docs).compact
94
118
  _target.clear and _unscoped.clear
95
- _base.delayed_atomic_unsets.clear
119
+ _base.delayed_atomic_unsets.delete(path)
120
+ clear_atomic_path_cache
96
121
  inserts = execute_batch_set(docs)
97
122
  add_atomic_sets(inserts)
98
123
  end
@@ -171,7 +196,7 @@ module Mongoid
171
196
  # @example Can inserts be performed?
172
197
  # batchable.insertable?
173
198
  #
174
- # @return [ true, false ] If inserts can be performed.
199
+ # @return [ true | false ] If inserts can be performed.
175
200
  def insertable?
176
201
  persistable? && !_assigning? && inserts_valid
177
202
  end
@@ -183,7 +208,7 @@ module Mongoid
183
208
  # @example Are the inserts currently valid.
184
209
  # batchable.inserts_valid
185
210
  #
186
- # @return [ true, false ] If inserts are currently valid.
211
+ # @return [ true | false ] If inserts are currently valid.
187
212
  def inserts_valid
188
213
  @inserts_valid
189
214
  end
@@ -195,9 +220,9 @@ module Mongoid
195
220
  # @example Set the flag.
196
221
  # batchable.inserts_valid = true
197
222
  #
198
- # @param [ true, false ] value The flag.
223
+ # @param [ true | false ] value The flag.
199
224
  #
200
- # @return [ true, false ] The flag.
225
+ # @return [ true | false ] The flag.
201
226
  def inserts_valid=(value)
202
227
  @inserts_valid = value
203
228
  end
@@ -210,7 +235,7 @@ module Mongoid
210
235
  # @example Normalize the docs.
211
236
  # batchable.normalize_docs(docs)
212
237
  #
213
- # @param [ Array<Hash, Document> ] docs The docs to normalize.
238
+ # @param [ Array<Hash | Document> ] docs The docs to normalize.
214
239
  #
215
240
  # @return [ Array<Document> ] The docs.
216
241
  def normalize_docs(docs)
@@ -234,7 +259,22 @@ module Mongoid
234
259
  #
235
260
  # @return [ String ] The atomic path.
236
261
  def path
237
- @path ||= _unscoped.first.atomic_path
262
+ @path ||= if _unscoped.empty?
263
+ Mongoid::Atomic::Paths::Embedded::Many.position_without_document(_base, _association)
264
+ else
265
+ _unscoped.first.atomic_path
266
+ end
267
+ end
268
+
269
+ # Clear the cache for path and atomic_paths. This method is used when
270
+ # the path method is used, and the association has not been set on the
271
+ # document yet, which can cause path and atomic_paths to be calculated
272
+ # incorrectly later.
273
+ #
274
+ # @api private
275
+ def clear_atomic_path_cache
276
+ self.path = nil
277
+ _base.instance_variable_set("@atomic_paths", nil)
238
278
  end
239
279
 
240
280
  # Set the atomic path.
@@ -88,7 +88,7 @@ module Mongoid
88
88
  # @example Determine the child name.
89
89
  # Role.cyclic_child_name
90
90
  #
91
- # @param [ true, false ] many Is the a many association?
91
+ # @param [ true | false ] many Is the a many association?
92
92
  #
93
93
  # @return [ String ] "child_" plus the class name underscored in
94
94
  # singular or plural form.
@@ -19,12 +19,14 @@ module Mongoid
19
19
  # name.person.bind(:continue => true)
20
20
  # name.person = Person.new
21
21
  def bind_one
22
- _base._association = _association.inverse_association(_target) unless _base._association
23
- _base.parentize(_target)
24
22
  binding do
23
+ check_polymorphic_inverses!(_target)
24
+ _base._association = _association.inverse_association(_target) unless _base._association
25
+ _base.parentize(_target)
25
26
  if _base.embedded_many?
26
27
  _target.do_or_do_not(_association.inverse(_target)).push(_base)
27
28
  else
29
+ remove_associated(_target)
28
30
  _target.do_or_do_not(_association.inverse_setter(_target), _base)
29
31
  end
30
32
  end
@@ -45,6 +47,26 @@ module Mongoid
45
47
  end
46
48
  end
47
49
  end
50
+
51
+ private
52
+
53
+ # Check for problems with multiple inverse definitions.
54
+ #
55
+ # @api private
56
+ #
57
+ # @example Check for inverses errors.
58
+ # binding.check_inverses!(doc)
59
+ #
60
+ # @param [ Document ] doc The document to check.
61
+ def check_polymorphic_inverses!(doc)
62
+ if inverses = _association.inverses(doc)
63
+ if inverses.length > 1
64
+ raise Errors::InvalidSetPolymorphicRelation.new(
65
+ _association.name, _base.class.name, _target.class.name
66
+ )
67
+ end
68
+ end
69
+ end
48
70
  end
49
71
  end
50
72
  end
@@ -32,7 +32,7 @@ module Mongoid
32
32
  #
33
33
  # @param [ Document ] replacement A document to replace the target.
34
34
  #
35
- # @return [ Document, nil ] The association or nil.
35
+ # @return [ Document | nil ] The association or nil.
36
36
  def substitute(replacement)
37
37
  unbind_one
38
38
  unless replacement
@@ -74,7 +74,7 @@ module Mongoid
74
74
  # @example Can we persist the association?
75
75
  # relation.persistable?
76
76
  #
77
- # @return [ true, false ] If the association is persistable.
77
+ # @return [ true | false ] If the association is persistable.
78
78
  def persistable?
79
79
  _target.persisted? && !_binding? && !_building?
80
80
  end