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
@@ -45,7 +45,7 @@ module Mongoid
45
45
  # @example Get the global database override.
46
46
  # Threaded.database_override
47
47
  #
48
- # @return [ String, Symbol ] The override.
48
+ # @return [ String | Symbol ] The override.
49
49
  def database_override
50
50
  Thread.current[DATABASE_OVERRIDE_KEY]
51
51
  end
@@ -55,9 +55,9 @@ module Mongoid
55
55
  # @example Set the global database override.
56
56
  # Threaded.database_override = :testing
57
57
  #
58
- # @param [ String, Symbol ] name The global override name.
58
+ # @param [ String | Symbol ] name The global override name.
59
59
  #
60
- # @return [ String, Symbol ] The override.
60
+ # @return [ String | Symbol ] The override.
61
61
  def database_override=(name)
62
62
  Thread.current[DATABASE_OVERRIDE_KEY] = name
63
63
  end
@@ -167,7 +167,7 @@ module Mongoid
167
167
  # @example Get the global client override.
168
168
  # Threaded.client_override
169
169
  #
170
- # @return [ String, Symbol ] The override.
170
+ # @return [ String | Symbol ] The override.
171
171
  def client_override
172
172
  Thread.current[CLIENT_OVERRIDE_KEY]
173
173
  end
@@ -177,9 +177,9 @@ module Mongoid
177
177
  # @example Set the global client override.
178
178
  # Threaded.client_override = :testing
179
179
  #
180
- # @param [ String, Symbol ] name The global override name.
180
+ # @param [ String | Symbol ] name The global override name.
181
181
  #
182
- # @return [ String, Symbol ] The override.
182
+ # @return [ String | Symbol ] The override.
183
183
  def client_override=(name)
184
184
  Thread.current[CLIENT_OVERRIDE_KEY] = name
185
185
  end
@@ -255,7 +255,7 @@ module Mongoid
255
255
  #
256
256
  # @param [ Document ] document The document to check.
257
257
  #
258
- # @return [ true, false ] If the document is autosaved.
258
+ # @return [ true | false ] If the document is autosaved.
259
259
  def autosaved?(document)
260
260
  autosaves_for(document.class).include?(document._id)
261
261
  end
@@ -267,7 +267,7 @@ module Mongoid
267
267
  #
268
268
  # @param [ Document ] document The document to check.
269
269
  #
270
- # @return [ true, false ] If the document is validated.
270
+ # @return [ true | false ] If the document is validated.
271
271
  def validated?(document)
272
272
  validations_for(document.class).include?(document._id)
273
273
  end
@@ -330,7 +330,7 @@ module Mongoid
330
330
  # @example Get the session for this thread.
331
331
  # Threaded.get_session
332
332
  #
333
- # @return [ Mongo::Session, nil ] The session cached on this thread or nil.
333
+ # @return [ Mongo::Session | nil ] The session cached on this thread or nil.
334
334
  def get_session
335
335
  Thread.current[:session]
336
336
  end
@@ -23,7 +23,7 @@ module Mongoid
23
23
  # person.set_created_at
24
24
  def set_created_at
25
25
  if !timeless? && !created_at
26
- time = Time.now.utc
26
+ time = Time.configured.now
27
27
  self.updated_at = time if is_a?(Updated) && !updated_at_changed?
28
28
  self.created_at = time
29
29
  end
@@ -24,7 +24,7 @@ module Mongoid
24
24
  # person.set_updated_at
25
25
  def set_updated_at
26
26
  if able_to_set_updated_at?
27
- self.updated_at = Time.now.utc unless updated_at_changed?
27
+ self.updated_at = Time.configured.now unless updated_at_changed?
28
28
  end
29
29
 
30
30
  clear_timeless_option
@@ -35,7 +35,7 @@ module Mongoid
35
35
  # @example Can the timestamp be set?
36
36
  # document.able_to_set_updated_at?
37
37
  #
38
- # @return [ true, false ] If the timestamp can be set.
38
+ # @return [ true | false ] If the timestamp can be set.
39
39
  def able_to_set_updated_at?
40
40
  !frozen? && !timeless? && (new_record? || changed?)
41
41
  end
@@ -19,10 +19,10 @@ module Mongoid
19
19
  #
20
20
  # @param [ Symbol ] field The name of an additional field to update.
21
21
  #
22
- # @return [ true/false ] false if record is new_record otherwise true.
22
+ # @return [ true/false ] false if document is new_record otherwise true.
23
23
  def touch(field = nil)
24
24
  return false if _root.new_record?
25
- current = Time.now
25
+ current = Time.configured.now
26
26
  field = database_field_name(field)
27
27
  write_attribute(:updated_at, current) if respond_to?("updated_at=")
28
28
  write_attribute(field, current) if field
@@ -60,7 +60,6 @@ module Mongoid
60
60
 
61
61
  # Callbacks are invoked on the composition root first and on the
62
62
  # leaf-most embedded document last.
63
- # TODO add tests, see MONGOID-5015.
64
63
  run_callbacks(:touch)
65
64
  true
66
65
  end
@@ -203,7 +203,7 @@ module Mongoid
203
203
  # @example Check if the document is a subclass
204
204
  # Square.new.hereditary?
205
205
  #
206
- # @return [ true, false ] True if hereditary, false if not.
206
+ # @return [ true | false ] True if hereditary, false if not.
207
207
  def hereditary?
208
208
  self.class.hereditary?
209
209
  end
@@ -233,6 +233,7 @@ module Mongoid
233
233
  def remove_child(child)
234
234
  name = child.association_name
235
235
  if child.embedded_one?
236
+ self.attributes.delete(child._association.store_as)
236
237
  remove_ivar(name)
237
238
  else
238
239
  relation = send(name)
@@ -282,7 +283,7 @@ module Mongoid
282
283
  # @example Is the document the root?
283
284
  # document._root?
284
285
  #
285
- # @return [ true, false ] If the document is the root.
286
+ # @return [ true | false ] If the document is the root.
286
287
  def _root?
287
288
  _parent ? false : true
288
289
  end
@@ -294,7 +295,7 @@ module Mongoid
294
295
  # @example Check if the document is a subclass.
295
296
  # Square.hereditary?
296
297
  #
297
- # @return [ true, false ] True if hereditary, false if not.
298
+ # @return [ true | false ] True if hereditary, false if not.
298
299
  def hereditary?
299
300
  !!(Mongoid::Document > superclass)
300
301
  end
@@ -12,7 +12,7 @@ module Mongoid
12
12
  # validator.validate_each(model, :name, "value")
13
13
  #
14
14
  # @param [ Document ] document The document.
15
- # @param [ Symbol, String ] attribute The attribute to validate.
15
+ # @param [ Symbol | String ] attribute The attribute to validate.
16
16
  # @param [ Object ] value The attribute value.
17
17
  def validate_each(document, attribute, value)
18
18
  field = document.fields[document.database_field_name(attribute)]
@@ -19,7 +19,6 @@ module Mongoid
19
19
  # end
20
20
  #
21
21
  # @param [ Array ] args The arguments to pass to the validator.
22
- #
23
22
  def validates_associated(*args)
24
23
  validates_with(AssociatedValidator, _merge_attributes(args))
25
24
  end
@@ -37,7 +36,6 @@ module Mongoid
37
36
  # end
38
37
  #
39
38
  # @param [ Array ] args The arguments to pass to the validator.
40
- #
41
39
  def validates_uniqueness_of(*args)
42
40
  validates_with(UniquenessValidator, _merge_attributes(args))
43
41
  end
@@ -56,7 +56,7 @@ module Mongoid
56
56
  # @param [ Symbol ] attr The attribute.
57
57
  # @param [ Object ] value The value.
58
58
  #
59
- # @return [ true, false ] If the doc is missing.
59
+ # @return [ true | false ] If the doc is missing.
60
60
  def relation_or_fk_missing?(doc, attr, value)
61
61
  return true if value.blank? && doc.send(attr).blank?
62
62
  association = doc.relations[attr.to_s]
@@ -72,7 +72,7 @@ module Mongoid
72
72
  #
73
73
  # @param [ Object ] value The value.
74
74
  #
75
- # @return [ true, false ] If the value is not present.
75
+ # @return [ true | false ] If the value is not present.
76
76
  def not_present?(value)
77
77
  value.blank? && value != false
78
78
  end
@@ -16,7 +16,7 @@ module Mongoid
16
16
  # end
17
17
  #
18
18
  # It is also possible to limit the uniqueness constraint to a set of
19
- # records matching certain conditions:
19
+ # documents matching certain conditions:
20
20
  # class Person
21
21
  # include Mongoid::Document
22
22
  # field :title
@@ -74,7 +74,7 @@ module Mongoid
74
74
  # @example Is the validation case sensitive?
75
75
  # validator.case_sensitive?
76
76
  #
77
- # @return [ true, false ] If the validation is case sensitive.
77
+ # @return [ true | false ] If the validation is case sensitive.
78
78
  def case_sensitive?
79
79
  !(options[:case_sensitive] == false)
80
80
  end
@@ -86,7 +86,7 @@ module Mongoid
86
86
  # @example Create the criteria.
87
87
  # validator.create_criteria(User, user, :name, "syd")
88
88
  #
89
- # @param [ Class, Proxy ] base The base to execute the criteria from.
89
+ # @param [ Class | Proxy ] base The base to execute the criteria from.
90
90
  # @param [ Document ] document The document to validate.
91
91
  # @param [ Symbol ] attribute The name of the attribute.
92
92
  # @param [ Object ] value The value of the object.
@@ -149,7 +149,7 @@ module Mongoid
149
149
  #
150
150
  # @param [ Object ] value The value to filter.
151
151
  #
152
- # @return [ Object, Regexp ] The value, filtered or not.
152
+ # @return [ Object | Regexp ] The value, filtered or not.
153
153
  def filter(value)
154
154
  !case_sensitive? && value ? /\A#{Regexp.escape(value.to_s)}\z/i : value
155
155
  end
@@ -182,7 +182,7 @@ module Mongoid
182
182
  #
183
183
  # @param [ Document ] document The embedded document.
184
184
  #
185
- # @return [ true, false ] If the validation should be skipped.
185
+ # @return [ true | false ] If the validation should be skipped.
186
186
  def skip_validation?(document)
187
187
  !document._parent || document.embedded_one?
188
188
  end
@@ -196,7 +196,7 @@ module Mongoid
196
196
  #
197
197
  # @param [ Document ] document The embedded document.
198
198
  #
199
- # @return [ true, false ] If the scope reference has changed.
199
+ # @return [ true | false ] If the scope reference has changed.
200
200
  def scope_value_changed?(document)
201
201
  Array.wrap(options[:scope]).any? do |item|
202
202
  document.send("attribute_changed?", item.to_s)
@@ -242,6 +242,7 @@ module Mongoid
242
242
  relation = document._parent.send(document.association_name)
243
243
  criteria = create_criteria(relation, document, attribute, value)
244
244
  criteria = criteria.merge(options[:conditions].call) if options[:conditions]
245
+ criteria = criteria.limit(2)
245
246
  add_error(document, attribute, value) if criteria.count > 1
246
247
  end
247
248
 
@@ -277,7 +278,7 @@ module Mongoid
277
278
  # @param [ Document ] document The document getting validated.
278
279
  # @param [ Symbol ] attribute The attribute to validate.
279
280
  #
280
- # @return [ true, false ] If we need to validate.
281
+ # @return [ true | false ] If we need to validate.
281
282
  def validation_required?(document, attribute)
282
283
  document.new_record? ||
283
284
  document.send("attribute_changed?", attribute.to_s) ||
@@ -294,7 +295,7 @@ module Mongoid
294
295
  # @param [ Document ] document The document getting validated.
295
296
  # @param [ Symbol ] attribute The attribute to validate.
296
297
  #
297
- # @return [ true, false ] If the attribute is localized.
298
+ # @return [ true | false ] If the attribute is localized.
298
299
  def localized?(document, attribute)
299
300
  document.fields[document.database_field_name(attribute)].try(:localized?)
300
301
  end
@@ -44,7 +44,7 @@ module Mongoid
44
44
  #
45
45
  # @param [ Hash ] options The options to check.
46
46
  #
47
- # @return [ true, false ] If we are validating.
47
+ # @return [ true | false ] If we are validating.
48
48
  def performing_validations?(options = {})
49
49
  options[:validate].nil? ? true : options[:validate]
50
50
  end
@@ -83,7 +83,7 @@ module Mongoid
83
83
  #
84
84
  # @param [ Symbol ] context The optional validation context.
85
85
  #
86
- # @return [ true, false ] True if valid, false if not.
86
+ # @return [ true | false ] True if valid, false if not.
87
87
  def valid?(context = nil)
88
88
  super context ? context : (new_record? ? :create : :update)
89
89
  end
@@ -93,7 +93,7 @@ module Mongoid
93
93
  # @example Is the document validated?
94
94
  # document.validated?
95
95
  #
96
- # @return [ true, false ] Has the document already been validated?
96
+ # @return [ true | false ] Has the document already been validated?
97
97
  def validated?
98
98
  Threaded.validated?(self)
99
99
  end
@@ -103,7 +103,7 @@ module Mongoid
103
103
  # @example Are we validating with a query?
104
104
  # document.validating_with_query?
105
105
  #
106
- # @return [ true, false ] If we are validating with a query.
106
+ # @return [ true | false ] If we are validating with a query.
107
107
  def validating_with_query?
108
108
  self.class.validating_with_query?
109
109
  end
@@ -129,7 +129,7 @@ module Mongoid
129
129
  # @example Validate with a specific validator.
130
130
  # validates_with MyValidator, on: :create
131
131
  #
132
- # @param [ Class<Array>, Hash ] args The validator classes and options.
132
+ # @param [ Class<Array> | Hash ] args The validator classes and options.
133
133
  #
134
134
  # @note See ActiveModel::Validations::With for full options. This is
135
135
  # overridden to add autosave functionality when presence validation is
@@ -151,7 +151,7 @@ module Mongoid
151
151
  # @example Are we validating with a query?
152
152
  # Model.validating_with_query?
153
153
  #
154
- # @return [ true, false ] If we are validating with a query.
154
+ # @return [ true | false ] If we are validating with a query.
155
155
  def validating_with_query?
156
156
  Threaded.executing?("#{name}-validate-with-query")
157
157
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mongoid
4
- VERSION = "7.5.0"
4
+ VERSION = "8.0.2"
5
5
  end
@@ -21,9 +21,8 @@ module Mongoid
21
21
  end
22
22
  end
23
23
 
24
- warning :id_sort_deprecated, 'The :id_sort option has been deprecated. Use Mongo#take to get a document without a sort on _id.'
25
- warning :criteria_cache_deprecated, 'The criteria cache has been deprecated and will be removed in Mongoid 8. Please enable the Mongoid QueryCache to have caching functionality.'
26
- warning :map_field_deprecated, 'The field argument to the Mongo#map method has been deprecated, please pass in a block instead. Support will be dropped in Mongoid 8.'
24
+ warning :geo_haystack_deprecated, 'The geoHaystack type is deprecated.'
25
+ warning :as_json_compact_deprecated, '#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.'
26
+ warning :symbol_type_deprecated, 'The BSON Symbol type is deprecated by MongoDB. Please use String or StringifiedSymbol field types instead of the Symbol field type'
27
27
  end
28
28
  end
29
-
data/lib/mongoid.rb CHANGED
@@ -16,6 +16,7 @@ require "mongo"
16
16
  require 'mongo/active_support'
17
17
 
18
18
  require "mongoid/version"
19
+ require "mongoid/deprecable"
19
20
  require "mongoid/config"
20
21
  require "mongoid/persistence_context"
21
22
  require "mongoid/loggable"
@@ -40,6 +40,22 @@ test:
40
40
  app_name: 'testing'
41
41
  background_indexing: false
42
42
  join_contexts: false
43
+ driver_options:
44
+ broken_view_options: false
45
+ # Don't set validate_update_replace here, as it is used to check if the
46
+ # default driver options are kept in Mongoid.
47
+ test_nil:
48
+ clients:
49
+ default:
50
+ database: mongoid_test
51
+ hosts:
52
+ <% SpecConfig.instance.addresses.each do |address| %>
53
+ - <%= address %>
54
+ <% end %>
55
+ driver_options:
56
+ broken_view_options:
57
+ validate_update_replace: false
58
+
43
59
  test_with_max_staleness:
44
60
  clients:
45
61
  default:
@@ -163,6 +163,14 @@ describe 'Mongoid application tests' do
163
163
  before do
164
164
  Dir.chdir(APP_PATH) do
165
165
  remove_bundler_req
166
+
167
+ if BSON::Environment.jruby?
168
+ # Remove existing Gemfile.lock - see
169
+ # https://github.com/rubygems/rubygems/issues/3231
170
+ require 'fileutils'
171
+ FileUtils.rm_f('Gemfile.lock')
172
+ end
173
+
166
174
  check_call(%w(bundle install), env: env)
167
175
  write_mongoid_yml
168
176
  end
@@ -287,18 +295,6 @@ describe 'Mongoid application tests' do
287
295
  f << lines.join
288
296
  end
289
297
  end
290
-
291
- if rails_version == '5.1'
292
- secrets = {
293
- 'development' => {
294
- 'secret_key_base' => 'abracadabra',
295
- 'my_secret_token' => 'very_secret',
296
- },
297
- }
298
- File.open('config/secrets.yml', 'w') do |f|
299
- f << YAML.dump(secrets)
300
- end
301
- end
302
298
  end
303
299
 
304
300
  def remove_bundler_req
@@ -12,4 +12,22 @@ describe 'belongs_to associations' do
12
12
  expect(child).to be_valid
13
13
  end
14
14
  end
15
+
16
+ context 'when an anonymous class defines a belongs_to association' do
17
+ let(:klass) do
18
+ Class.new do
19
+ include Mongoid::Document
20
+ belongs_to :movie
21
+ end
22
+ end
23
+
24
+ it 'loads the association correctly' do
25
+ expect { klass }.to_not raise_error
26
+ expect { klass.new.movie }.to_not raise_error
27
+ instance = klass.new
28
+ movie = Movie.new
29
+ instance.movie = movie
30
+ expect(instance.movie).to eq movie
31
+ end
32
+ end
15
33
  end
@@ -265,4 +265,19 @@ describe 'embedded associations' do
265
265
  end
266
266
  end
267
267
  end
268
+
269
+ context "when summing properties on an embedded child" do
270
+ let(:user) { EmmUser.new }
271
+ before do
272
+ user.orders.build(amount: 200)
273
+ expect(user.orders.sum(:amount)).to eq(200)
274
+
275
+ user.orders.delete_all
276
+ user.orders.build(amount: 500)
277
+ end
278
+
279
+ it "the cache is cleared after deletion" do
280
+ expect(user.orders.sum(:amount)).to eq(500)
281
+ end
282
+ end
268
283
  end
@@ -172,8 +172,6 @@ describe 'embeds_many associations' do
172
172
  # Mongoid uses the new value of `x` in the $pullAll query,
173
173
  # which doesn't match the document that is in the database,
174
174
  # resulting in the empty array assignment not taking effect.
175
- pending 'MONGOID-5037'
176
-
177
175
  canvas.shapes.first.x = 1
178
176
  canvas.shapes = []
179
177
  canvas.save!
@@ -203,4 +201,19 @@ describe 'embeds_many associations' do
203
201
  end
204
202
  end
205
203
  end
204
+
205
+ context 'when an anonymous class defines an embeds_many association' do
206
+ let(:klass) do
207
+ Class.new do
208
+ include Mongoid::Document
209
+ embeds_many :addresses
210
+ end
211
+ end
212
+
213
+ it 'loads the association correctly' do
214
+ expect { klass }.to_not raise_error
215
+ expect { klass.new.addresses }.to_not raise_error
216
+ expect(klass.new.addresses.build).to be_a Address
217
+ end
218
+ end
206
219
  end
@@ -20,4 +20,22 @@ describe 'embeds_one associations' do
20
20
  end
21
21
  end
22
22
  end
23
+
24
+ context 'when an anonymous class defines an embeds_one association' do
25
+ let(:klass) do
26
+ Class.new do
27
+ include Mongoid::Document
28
+ embeds_one :address
29
+ end
30
+ end
31
+
32
+ it 'loads the association correctly' do
33
+ expect { klass }.to_not raise_error
34
+ expect { klass.new.address }.to_not raise_error
35
+ instance = klass.new
36
+ address = Address.new
37
+ instance.address = address
38
+ expect(instance.address).to eq address
39
+ end
40
+ end
23
41
  end
@@ -27,6 +27,15 @@ describe 'Association foreign key configuration' do
27
27
  expect(email.company.id).to eq(company.id)
28
28
  end
29
29
 
30
+ it "has the correct criteria" do
31
+ company = ForeignKeySpec::Company.create!(c: "3")
32
+ email = ForeignKeySpec::Email.create!(company: company)
33
+
34
+ criteria = ForeignKeySpec::Email.where(company: company)
35
+
36
+ expect(criteria.selector).to eq({ "c_ref" => "3" })
37
+ end
38
+
30
39
  context 'with default scope' do
31
40
  context 'using default scope' do
32
41
  it 'looks up child' do
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'has_and_belongs_to_many associations' do
6
+
7
+ context 'when an anonymous class defines a has_and_belongs_to_many association' do
8
+ let(:klass) do
9
+ Class.new do
10
+ include Mongoid::Document
11
+ has_and_belongs_to_many :movies, inverse_of: nil
12
+ end
13
+ end
14
+
15
+ it 'loads the association correctly' do
16
+ expect { klass }.to_not raise_error
17
+ expect { klass.new.movies }.to_not raise_error
18
+ expect(klass.new.movies.build).to be_a Movie
19
+ end
20
+ end
21
+ end
@@ -94,7 +94,7 @@ describe 'has_one associations' do
94
94
  context 'using send' do
95
95
  it 'delegates to the field' do
96
96
  if reloaded
97
- pending 'MONGOID-4018'
97
+ pending 'MONGOID-5018'
98
98
  end
99
99
 
100
100
  parent.accreditation.send(:format).should == 'fmt'
@@ -173,4 +173,100 @@ describe 'has_one associations' do
173
173
  end
174
174
  end
175
175
  end
176
+
177
+ context "when assigning to a has_one" do
178
+ let(:post) { HomPost.create! }
179
+ let(:comment1) { HomComment.create!(content: "Comment 1") }
180
+
181
+ context "when assigning the same value" do
182
+ let(:comment2) { HomComment.create! }
183
+
184
+ it "persists it correctly" do
185
+ post.comment = comment1
186
+ post.reload
187
+ expect(post.comment).to eq(comment1)
188
+
189
+ post.comment = comment1
190
+ post.reload
191
+ expect(post.comment).to eq(comment1)
192
+ end
193
+ end
194
+
195
+ context "when assigning two values with the same _id" do
196
+ let(:comment2) { HomComment.new(id: comment1.id) }
197
+
198
+ it "raises a duplicate key error" do
199
+ post.comment = comment1
200
+ expect do
201
+ post.comment = comment2
202
+ end.to raise_error(Mongo::Error::OperationFailure, /duplicate key/)
203
+ end
204
+ end
205
+
206
+ context "when duping the object and changing attributes" do
207
+ let(:comment2) { comment1.dup }
208
+
209
+ before do
210
+ comment2.content = "Comment 2"
211
+
212
+ post.comment = comment1
213
+ post.reload
214
+ end
215
+
216
+ it "updates the attributes correctly" do
217
+ post.comment = comment2
218
+ post.reload
219
+
220
+ expect(post.comment).to eq(comment2)
221
+ expect(post.comment.content).to eq(comment2.content)
222
+ end
223
+ end
224
+
225
+ context "when explicitly setting the foreign key" do
226
+ let(:comment2) { HomComment.new(post_id: post.id, content: "2") }
227
+
228
+ it "persists the new comment" do
229
+ post.comment = comment1
230
+ post.reload
231
+
232
+ post.comment = comment2
233
+ post.reload
234
+
235
+ expect(post.comment).to eq(comment2)
236
+ expect(post.comment.content).to eq(comment2.content)
237
+ end
238
+ end
239
+
240
+ context "when reassigning the same value" do
241
+ let(:comment2) { HomComment.create!(content: "Comment 2") }
242
+
243
+ it "persists it correctly" do
244
+ post.comment = comment1
245
+ post.reload
246
+ expect(post.comment).to eq(comment1)
247
+
248
+ post.comment = comment2
249
+ post.reload
250
+ expect(post.comment).to eq(comment2)
251
+
252
+ post.comment = comment1
253
+ post.reload
254
+ expect(post.comment).to eq(nil)
255
+ end
256
+ end
257
+ end
258
+
259
+ context "when overwriting an association" do
260
+ let(:post1) { HomPost.create!(title: "post 1") }
261
+ let(:post2) { HomPost.create!(title: "post 2") }
262
+ let(:comment) { HomComment.create(post: post1) }
263
+
264
+ it "does not overwrite the original value" do
265
+ pending "MONGOID-3999"
266
+ p1 = comment.post
267
+ expect(p1.title).to eq("post 1")
268
+ comment.post = post2
269
+ expect(p1.title).to eq("post 1")
270
+ end
271
+ end
176
272
  end
@@ -49,7 +49,7 @@ describe 'association :scope option' do
49
49
  it 'initially associates the documents in-memory' do
50
50
  expect(trainer1.animal).to eq animal2
51
51
  expect(trainer2.animal).to eq animal3
52
- expect(animal1.trainer).to eq trainer1
52
+ expect(animal1.trainer).to be_nil
53
53
  expect(animal2.trainer).to eq trainer1
54
54
  expect(animal3.trainer).to eq trainer2
55
55
  end