mongoid 7.5.0 → 8.0.2

Sign up to get free protection for your applications and to get access to all the features.
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