mongoid 7.4.3 → 8.0.7

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 (383) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +25 -0
  5. data/lib/config/locales/en.yml +52 -28
  6. data/lib/mongoid/association/accessors.rb +38 -9
  7. data/lib/mongoid/association/bindable.rb +50 -2
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/constrainable.rb +0 -1
  10. data/lib/mongoid/association/eager_loadable.rb +29 -7
  11. data/lib/mongoid/association/embedded/batchable.rb +33 -10
  12. data/lib/mongoid/association/embedded/cyclic.rb +1 -1
  13. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  14. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -2
  15. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  16. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  17. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  18. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +65 -41
  19. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  20. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  21. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +23 -4
  22. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  23. data/lib/mongoid/association/macros.rb +28 -1
  24. data/lib/mongoid/association/many.rb +11 -7
  25. data/lib/mongoid/association/nested/many.rb +5 -4
  26. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  27. data/lib/mongoid/association/nested/one.rb +5 -5
  28. data/lib/mongoid/association/one.rb +2 -2
  29. data/lib/mongoid/association/options.rb +9 -9
  30. data/lib/mongoid/association/proxy.rb +14 -3
  31. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  32. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  33. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  34. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  35. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  36. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  37. data/lib/mongoid/association/referenced/eager.rb +2 -2
  38. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
  39. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  40. data/lib/mongoid/association/referenced/has_many/enumerable.rb +20 -24
  41. data/lib/mongoid/association/referenced/has_many/proxy.rb +26 -16
  42. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  43. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  44. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  45. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  46. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  47. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  48. data/lib/mongoid/association/reflections.rb +2 -2
  49. data/lib/mongoid/association/relatable.rb +44 -10
  50. data/lib/mongoid/association.rb +5 -5
  51. data/lib/mongoid/atomic/modifiers.rb +2 -2
  52. data/lib/mongoid/atomic.rb +7 -0
  53. data/lib/mongoid/attributes/dynamic.rb +3 -3
  54. data/lib/mongoid/attributes/nested.rb +5 -5
  55. data/lib/mongoid/attributes/processing.rb +37 -6
  56. data/lib/mongoid/attributes/projector.rb +1 -1
  57. data/lib/mongoid/attributes/readonly.rb +2 -2
  58. data/lib/mongoid/attributes.rb +43 -40
  59. data/lib/mongoid/cacheable.rb +2 -2
  60. data/lib/mongoid/changeable.rb +43 -10
  61. data/lib/mongoid/clients/options.rb +5 -1
  62. data/lib/mongoid/clients/sessions.rb +2 -14
  63. data/lib/mongoid/clients/validators/storage.rb +3 -3
  64. data/lib/mongoid/config/options.rb +3 -0
  65. data/lib/mongoid/config/validators/client.rb +6 -6
  66. data/lib/mongoid/config.rb +62 -17
  67. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  68. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  69. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  70. data/lib/mongoid/contextual/atomic.rb +1 -1
  71. data/lib/mongoid/contextual/geo_near.rb +7 -7
  72. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  73. data/lib/mongoid/contextual/memory.rb +180 -21
  74. data/lib/mongoid/contextual/mongo.rb +260 -217
  75. data/lib/mongoid/contextual/none.rb +67 -5
  76. data/lib/mongoid/contextual/queryable.rb +1 -1
  77. data/lib/mongoid/contextual.rb +2 -2
  78. data/lib/mongoid/copyable.rb +32 -8
  79. data/lib/mongoid/criteria/findable.rb +7 -4
  80. data/lib/mongoid/criteria/includable.rb +24 -20
  81. data/lib/mongoid/criteria/marshalable.rb +10 -2
  82. data/lib/mongoid/criteria/permission.rb +1 -1
  83. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  84. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -14
  85. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  86. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  87. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  88. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  89. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -15
  90. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -9
  91. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  92. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  93. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  94. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  95. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
  96. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
  97. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  98. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  99. data/lib/mongoid/criteria/queryable/key.rb +3 -3
  100. data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
  101. data/lib/mongoid/criteria/queryable/optional.rb +5 -11
  102. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  103. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  104. data/lib/mongoid/criteria/queryable/selectable.rb +31 -37
  105. data/lib/mongoid/criteria/queryable/selector.rb +93 -8
  106. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  107. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  108. data/lib/mongoid/criteria/queryable.rb +12 -7
  109. data/lib/mongoid/criteria/scopable.rb +2 -2
  110. data/lib/mongoid/criteria/translator.rb +45 -0
  111. data/lib/mongoid/criteria.rb +16 -35
  112. data/lib/mongoid/deprecable.rb +37 -0
  113. data/lib/mongoid/deprecation.rb +25 -0
  114. data/lib/mongoid/document.rb +135 -34
  115. data/lib/mongoid/equality.rb +8 -8
  116. data/lib/mongoid/errors/document_not_found.rb +33 -12
  117. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  118. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  119. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  120. data/lib/mongoid/errors/invalid_field.rb +6 -2
  121. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  122. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  123. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  124. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  125. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  126. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  127. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  128. data/lib/mongoid/errors/no_client_database.rb +1 -1
  129. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  130. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  131. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  132. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  133. data/lib/mongoid/errors.rb +2 -2
  134. data/lib/mongoid/extensions/array.rb +9 -7
  135. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  136. data/lib/mongoid/extensions/binary.rb +42 -0
  137. data/lib/mongoid/extensions/boolean.rb +8 -2
  138. data/lib/mongoid/extensions/date.rb +26 -20
  139. data/lib/mongoid/extensions/date_time.rb +1 -1
  140. data/lib/mongoid/extensions/false_class.rb +1 -1
  141. data/lib/mongoid/extensions/float.rb +7 -4
  142. data/lib/mongoid/extensions/hash.rb +37 -8
  143. data/lib/mongoid/extensions/integer.rb +7 -4
  144. data/lib/mongoid/extensions/module.rb +1 -1
  145. data/lib/mongoid/extensions/object.rb +8 -6
  146. data/lib/mongoid/extensions/range.rb +41 -10
  147. data/lib/mongoid/extensions/regexp.rb +11 -4
  148. data/lib/mongoid/extensions/set.rb +11 -4
  149. data/lib/mongoid/extensions/string.rb +11 -22
  150. data/lib/mongoid/extensions/symbol.rb +4 -15
  151. data/lib/mongoid/extensions/time.rb +27 -16
  152. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  153. data/lib/mongoid/extensions/true_class.rb +1 -1
  154. data/lib/mongoid/extensions.rb +1 -0
  155. data/lib/mongoid/factory.rb +55 -7
  156. data/lib/mongoid/fields/foreign_key.rb +11 -4
  157. data/lib/mongoid/fields/localized.rb +9 -4
  158. data/lib/mongoid/fields/standard.rb +7 -7
  159. data/lib/mongoid/fields/validators/macro.rb +3 -9
  160. data/lib/mongoid/fields.rb +233 -40
  161. data/lib/mongoid/findable.rb +34 -13
  162. data/lib/mongoid/indexable/specification.rb +2 -2
  163. data/lib/mongoid/indexable/validators/options.rb +6 -2
  164. data/lib/mongoid/interceptable.rb +185 -16
  165. data/lib/mongoid/matchable.rb +1 -1
  166. data/lib/mongoid/matcher.rb +33 -13
  167. data/lib/mongoid/persistable/creatable.rb +18 -9
  168. data/lib/mongoid/persistable/deletable.rb +1 -1
  169. data/lib/mongoid/persistable/destroyable.rb +1 -1
  170. data/lib/mongoid/persistable/savable.rb +2 -2
  171. data/lib/mongoid/persistable/unsettable.rb +1 -1
  172. data/lib/mongoid/persistable/updatable.rb +19 -12
  173. data/lib/mongoid/persistable/upsertable.rb +1 -1
  174. data/lib/mongoid/persistable.rb +3 -3
  175. data/lib/mongoid/persistence_context.rb +63 -10
  176. data/lib/mongoid/query_cache.rb +8 -260
  177. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  178. data/lib/mongoid/reloadable.rb +10 -8
  179. data/lib/mongoid/scopable.rb +26 -22
  180. data/lib/mongoid/selectable.rb +1 -2
  181. data/lib/mongoid/serializable.rb +10 -6
  182. data/lib/mongoid/shardable.rb +35 -11
  183. data/lib/mongoid/stateful.rb +35 -9
  184. data/lib/mongoid/tasks/database.rb +0 -2
  185. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  186. data/lib/mongoid/threaded.rb +42 -12
  187. data/lib/mongoid/timestamps/created.rb +1 -1
  188. data/lib/mongoid/timestamps/updated.rb +2 -2
  189. data/lib/mongoid/touchable.rb +2 -3
  190. data/lib/mongoid/traversable.rb +5 -4
  191. data/lib/mongoid/validatable/localizable.rb +1 -1
  192. data/lib/mongoid/validatable/macros.rb +0 -2
  193. data/lib/mongoid/validatable/presence.rb +2 -2
  194. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  195. data/lib/mongoid/validatable.rb +6 -6
  196. data/lib/mongoid/version.rb +1 -1
  197. data/lib/mongoid/warnings.rb +28 -0
  198. data/lib/mongoid.rb +2 -0
  199. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -3
  200. data/spec/config/mongoid.yml +16 -0
  201. data/spec/integration/app_spec.rb +8 -12
  202. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  203. data/spec/integration/associations/embedded_spec.rb +15 -0
  204. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  205. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  206. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  207. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  208. data/spec/integration/associations/has_one_spec.rb +97 -1
  209. data/spec/integration/associations/scope_option_spec.rb +1 -1
  210. data/spec/integration/callbacks_models.rb +95 -1
  211. data/spec/integration/callbacks_spec.rb +246 -4
  212. data/spec/integration/criteria/range_spec.rb +95 -1
  213. data/spec/integration/discriminator_key_spec.rb +115 -76
  214. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  215. data/spec/integration/i18n_fallbacks_spec.rb +1 -17
  216. data/spec/integration/matcher_examples_spec.rb +20 -13
  217. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  218. data/spec/integration/matcher_operator_spec.rb +3 -5
  219. data/spec/integration/persistence/range_field_spec.rb +350 -0
  220. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  221. data/spec/mongoid/association/depending_spec.rb +9 -9
  222. data/spec/mongoid/association/eager_spec.rb +2 -1
  223. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  224. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  225. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  226. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  227. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +235 -40
  228. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  229. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  230. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  231. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  232. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  233. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  234. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  235. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  236. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  237. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  238. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  239. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +202 -201
  240. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  241. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  242. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  243. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +8 -8
  244. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +160 -119
  245. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  246. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  247. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  248. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  249. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  250. data/spec/mongoid/association/syncable_spec.rb +14 -0
  251. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  252. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  253. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  254. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  255. data/spec/mongoid/attributes_spec.rb +551 -27
  256. data/spec/mongoid/cacheable_spec.rb +3 -3
  257. data/spec/mongoid/changeable_spec.rb +130 -13
  258. data/spec/mongoid/clients/factory_spec.rb +23 -30
  259. data/spec/mongoid/clients/options_spec.rb +1 -0
  260. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  261. data/spec/mongoid/clients_spec.rb +57 -2
  262. data/spec/mongoid/config_spec.rb +78 -18
  263. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  264. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  265. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  266. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  267. data/spec/mongoid/contextual/memory_spec.rb +1336 -69
  268. data/spec/mongoid/contextual/mongo_spec.rb +1253 -247
  269. data/spec/mongoid/contextual/none_spec.rb +38 -0
  270. data/spec/mongoid/copyable_spec.rb +451 -1
  271. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  272. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  273. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  274. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  275. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  276. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  277. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  278. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  279. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  280. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  281. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +0 -59
  282. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  283. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  284. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  285. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
  286. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  287. data/spec/mongoid/criteria/queryable/selectable_spec.rb +289 -124
  288. data/spec/mongoid/criteria/queryable/selector_spec.rb +89 -4
  289. data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
  290. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  291. data/spec/mongoid/criteria_projection_spec.rb +0 -1
  292. data/spec/mongoid/criteria_spec.rb +475 -1199
  293. data/spec/mongoid/document_fields_spec.rb +173 -24
  294. data/spec/mongoid/document_spec.rb +32 -41
  295. data/spec/mongoid/errors/document_not_found_spec.rb +76 -0
  296. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  297. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  298. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  299. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  300. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  301. data/spec/mongoid/extensions/array_spec.rb +16 -2
  302. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  303. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  304. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  305. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  306. data/spec/mongoid/extensions/date_spec.rb +71 -1
  307. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  308. data/spec/mongoid/extensions/float_spec.rb +53 -74
  309. data/spec/mongoid/extensions/hash_spec.rb +33 -3
  310. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  311. data/spec/mongoid/extensions/range_spec.rb +255 -54
  312. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  313. data/spec/mongoid/extensions/set_spec.rb +106 -0
  314. data/spec/mongoid/extensions/string_spec.rb +53 -25
  315. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  316. data/spec/mongoid/extensions/time_spec.rb +634 -66
  317. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  318. data/spec/mongoid/factory_spec.rb +61 -1
  319. data/spec/mongoid/fields/localized_spec.rb +37 -12
  320. data/spec/mongoid/fields_spec.rb +364 -50
  321. data/spec/mongoid/findable_spec.rb +80 -15
  322. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  323. data/spec/mongoid/indexable_spec.rb +39 -20
  324. data/spec/mongoid/interceptable_spec.rb +807 -27
  325. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  326. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  327. data/spec/mongoid/mongoizable_spec.rb +285 -0
  328. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  329. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  330. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  331. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  332. data/spec/mongoid/persistence_context_spec.rb +50 -1
  333. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  334. data/spec/mongoid/query_cache_spec.rb +0 -154
  335. data/spec/mongoid/reloadable_spec.rb +59 -2
  336. data/spec/mongoid/scopable_spec.rb +54 -16
  337. data/spec/mongoid/shardable_models.rb +14 -0
  338. data/spec/mongoid/shardable_spec.rb +157 -51
  339. data/spec/mongoid/stateful_spec.rb +28 -0
  340. data/spec/mongoid/timestamps_spec.rb +390 -0
  341. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  342. data/spec/mongoid/touchable_spec.rb +116 -0
  343. data/spec/mongoid/touchable_spec_models.rb +12 -8
  344. data/spec/mongoid/traversable_spec.rb +4 -11
  345. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  346. data/spec/mongoid/validatable/uniqueness_spec.rb +59 -31
  347. data/spec/mongoid/warnings_spec.rb +35 -0
  348. data/spec/mongoid_spec.rb +1 -1
  349. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  350. data/spec/rails/mongoid_spec.rb +4 -16
  351. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  352. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  353. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  354. data/spec/shared/lib/mrss/utils.rb +28 -6
  355. data/spec/shared/share/Dockerfile.erb +36 -40
  356. data/spec/shared/shlib/server.sh +32 -8
  357. data/spec/shared/shlib/set_env.sh +4 -4
  358. data/spec/support/constraints.rb +24 -0
  359. data/spec/support/macros.rb +46 -0
  360. data/spec/support/models/augmentation.rb +12 -0
  361. data/spec/support/models/band.rb +3 -0
  362. data/spec/support/models/catalog.rb +24 -0
  363. data/spec/support/models/circus.rb +3 -0
  364. data/spec/support/models/code.rb +2 -0
  365. data/spec/support/models/fanatic.rb +8 -0
  366. data/spec/support/models/implant.rb +9 -0
  367. data/spec/support/models/label.rb +2 -0
  368. data/spec/support/models/passport.rb +9 -0
  369. data/spec/support/models/person.rb +2 -0
  370. data/spec/support/models/player.rb +2 -0
  371. data/spec/support/models/powerup.rb +12 -0
  372. data/spec/support/models/purse.rb +9 -0
  373. data/spec/support/models/registry.rb +1 -0
  374. data/spec/support/models/school.rb +14 -0
  375. data/spec/support/models/shield.rb +18 -0
  376. data/spec/support/models/student.rb +14 -0
  377. data/spec/support/models/weapon.rb +12 -0
  378. data.tar.gz.sig +4 -1
  379. metadata +682 -635
  380. metadata.gz.sig +0 -0
  381. data/lib/mongoid/errors/eager_load.rb +0 -23
  382. data/lib/mongoid/errors/invalid_value.rb +0 -17
  383. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative "../has_and_belongs_to_many_models"
4
5
 
5
6
  describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
6
7
 
@@ -2086,283 +2087,229 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2086
2087
  end
2087
2088
  end
2088
2089
 
2089
- describe "#delete" do
2090
+ %i[ delete delete_one ].each do |method|
2091
+ describe "\##{method}" do
2092
+ let(:person) { Person.create! }
2093
+ let(:preference_one) { Preference.create!(name: "Testing") }
2094
+ let(:preference_two) { Preference.create!(name: "Test") }
2090
2095
 
2091
- let(:person) do
2092
- Person.create!
2093
- end
2094
-
2095
- let(:preference_one) do
2096
- Preference.create!(name: "Testing")
2097
- end
2098
-
2099
- let(:preference_two) do
2100
- Preference.create!(name: "Test")
2101
- end
2102
-
2103
- before do
2104
- person.preferences << [ preference_one, preference_two ]
2105
- end
2106
-
2107
- context "when the document exists" do
2108
-
2109
- let!(:deleted) do
2110
- person.preferences.delete(preference_one)
2111
- end
2112
-
2113
- it "removes the document from the relation" do
2114
- expect(person.preferences).to eq([ preference_two ])
2115
- end
2116
-
2117
- it "returns the document" do
2118
- expect(deleted).to eq(preference_one)
2119
- end
2120
-
2121
- it "removes the document key from the foreign key" do
2122
- expect(person.preference_ids).to eq([ preference_two.id ])
2123
- end
2124
-
2125
- it "removes the inverse reference" do
2126
- expect(deleted.reload.people).to be_empty
2127
- end
2128
-
2129
- it "removes the base id from the inverse keys" do
2130
- expect(deleted.reload.person_ids).to be_empty
2096
+ before do
2097
+ person.preferences << [ preference_one, preference_two ]
2131
2098
  end
2132
2099
 
2133
- context "and person and preferences are reloaded" do
2134
-
2135
- before do
2136
- person.reload
2137
- preference_one.reload
2138
- preference_two.reload
2100
+ context 'when the document exists' do
2101
+ let!(:deleted) do
2102
+ person.preferences.send(method, preference_one)
2139
2103
  end
2140
2104
 
2141
- it "nullifies the deleted preference" do
2105
+ it 'removes the document from the relation' do
2142
2106
  expect(person.preferences).to eq([ preference_two ])
2143
2107
  end
2144
2108
 
2145
- it "retains the ids for one preference" do
2146
- expect(person.preference_ids).to eq([ preference_two.id ])
2109
+ it 'returns the document' do
2110
+ expect(deleted).to eq(preference_one)
2147
2111
  end
2148
- end
2149
- end
2150
-
2151
- context "when the document does not exist" do
2152
-
2153
- let!(:deleted) do
2154
- person.preferences.delete(Preference.new)
2155
- end
2156
-
2157
- it "returns nil" do
2158
- expect(deleted).to be_nil
2159
- end
2160
2112
 
2161
- it "does not modify the relation" do
2162
- expect(person.preferences).to eq([ preference_one, preference_two ])
2163
- end
2164
-
2165
- it "does not modify the keys" do
2166
- expect(person.preference_ids).to eq([ preference_one.id, preference_two.id ])
2167
- end
2168
- end
2169
-
2170
- context "when :dependent => :nullify is set" do
2171
-
2172
- context "when :inverse_of is set" do
2173
-
2174
- let(:event) do
2175
- Event.create!
2113
+ it 'removes the document key from the foreign key' do
2114
+ expect(person.preference_ids).to eq([ preference_two.id ])
2176
2115
  end
2177
2116
 
2178
- before do
2179
- person.administrated_events << [ event ]
2117
+ it 'removes the inverse reference' do
2118
+ expect(deleted.reload.people).to be_empty
2180
2119
  end
2181
2120
 
2182
- it "deletes the document" do
2183
- expect(event.delete).to be true
2121
+ it 'removes the base id from the inverse keys' do
2122
+ expect(deleted.reload.person_ids).to be_empty
2184
2123
  end
2185
- end
2186
- end
2187
-
2188
- context "when the relationships are self referencing" do
2189
2124
 
2190
- let(:tag_one) do
2191
- Tag.create!(text: "one")
2192
- end
2125
+ context 'and person and preferences are reloaded' do
2126
+ before do
2127
+ person.reload
2128
+ preference_one.reload
2129
+ preference_two.reload
2130
+ end
2193
2131
 
2194
- let(:tag_two) do
2195
- Tag.create!(text: "two")
2196
- end
2132
+ it 'nullifies the deleted preference' do
2133
+ expect(person.preferences).to eq([ preference_two ])
2134
+ end
2197
2135
 
2198
- before do
2199
- tag_one.related << tag_two
2136
+ it 'retains the ids for one preference' do
2137
+ expect(person.preference_ids).to eq([ preference_two.id ])
2138
+ end
2139
+ end
2200
2140
  end
2201
2141
 
2202
- context "when deleting without reloading" do
2203
-
2142
+ context 'when the document does not exist' do
2204
2143
  let!(:deleted) do
2205
- tag_one.related.delete(tag_two)
2206
- end
2207
-
2208
- it "deletes the document from the relation" do
2209
- expect(tag_one.related).to be_empty
2144
+ person.preferences.send(method, Preference.new)
2210
2145
  end
2211
2146
 
2212
- it "deletes the foreign key from the relation" do
2213
- expect(tag_one.related_ids).to be_empty
2147
+ it 'returns nil' do
2148
+ expect(deleted).to be_nil
2214
2149
  end
2215
2150
 
2216
- it "removes the reference from the inverse" do
2217
- expect(deleted.related).to be_empty
2151
+ it 'does not modify the relation' do
2152
+ expect(person.preferences).to eq([ preference_one, preference_two ])
2218
2153
  end
2219
2154
 
2220
- it "removes the foreign keys from the inverse" do
2221
- expect(deleted.related_ids).to be_empty
2155
+ it 'does not modify the keys' do
2156
+ expect(person.preference_ids).to eq([ preference_one.id, preference_two.id ])
2222
2157
  end
2223
2158
  end
2224
2159
 
2225
- context "when deleting with reloading" do
2226
-
2227
- context "when deleting from the front side" do
2228
-
2229
- let(:reloaded) do
2230
- tag_one.reload
2231
- end
2160
+ context 'when :dependent => :nullify is set' do
2161
+ context 'when :inverse_of is set' do
2162
+ let(:event) { Event.create! }
2232
2163
 
2233
- let!(:deleted) do
2234
- reloaded.related.delete(tag_two)
2235
- end
2236
-
2237
- it "deletes the document from the relation" do
2238
- expect(reloaded.related).to be_empty
2164
+ before do
2165
+ person.administrated_events << [ event ]
2239
2166
  end
2240
2167
 
2241
- it "deletes the foreign key from the relation" do
2242
- expect(reloaded.related_ids).to be_empty
2168
+ it 'deletes the document' do
2169
+ expect(event.delete).to be true
2243
2170
  end
2171
+ end
2172
+ end
2244
2173
 
2245
- it "removes the reference from the inverse" do
2246
- expect(deleted.related).to be_empty
2247
- end
2174
+ context 'when the relationships are self referencing' do
2175
+ let(:tag_one) { Tag.create!(text: "one") }
2176
+ let(:tag_two) { Tag.create!(text: "two") }
2248
2177
 
2249
- it "removes the foreign keys from the inverse" do
2250
- expect(deleted.related_ids).to be_empty
2251
- end
2178
+ before do
2179
+ tag_one.related << tag_two
2252
2180
  end
2253
2181
 
2254
- context "when deleting from the inverse side" do
2182
+ context 'when deleting without reloading' do
2183
+ let!(:deleted) { tag_one.related.send(method, tag_two) }
2255
2184
 
2256
- let(:reloaded) do
2257
- tag_two.reload
2185
+ it 'deletes the document from the relation' do
2186
+ expect(tag_one.related).to be_empty
2258
2187
  end
2259
2188
 
2260
- let!(:deleted) do
2261
- reloaded.related.delete(tag_one)
2262
- end
2263
-
2264
- it "deletes the document from the relation" do
2265
- expect(reloaded.related).to be_empty
2189
+ it 'deletes the foreign key from the relation' do
2190
+ expect(tag_one.related_ids).to be_empty
2266
2191
  end
2267
2192
 
2268
- it "deletes the foreign key from the relation" do
2269
- expect(reloaded.related_ids).to be_empty
2193
+ it 'removes the reference from the inverse' do
2194
+ expect(deleted.related).to be_empty
2270
2195
  end
2271
2196
 
2272
- it "removes the foreign keys from the inverse" do
2197
+ it 'removes the foreign keys from the inverse' do
2273
2198
  expect(deleted.related_ids).to be_empty
2274
2199
  end
2275
2200
  end
2276
- end
2277
- end
2278
2201
 
2279
- context "when the association has callbacks" do
2202
+ context 'when deleting with reloading' do
2203
+ context "when deleting from the front side" do
2204
+ let(:reloaded) { tag_one.reload }
2205
+ let!(:deleted) { reloaded.related.send(method, tag_two) }
2280
2206
 
2281
- let(:post) do
2282
- Post.new
2283
- end
2207
+ it 'deletes the document from the relation' do
2208
+ expect(reloaded.related).to be_empty
2209
+ end
2284
2210
 
2285
- let(:tag) do
2286
- Tag.new
2287
- end
2211
+ it 'deletes the foreign key from the relation' do
2212
+ expect(reloaded.related_ids).to be_empty
2213
+ end
2288
2214
 
2289
- before do
2290
- post.tags << tag
2291
- end
2215
+ it 'removes the reference from the inverse' do
2216
+ expect(deleted.related).to be_empty
2217
+ end
2292
2218
 
2293
- context "when the callback is a before_remove" do
2219
+ it 'removes the foreign keys from the inverse' do
2220
+ expect(deleted.related_ids).to be_empty
2221
+ end
2222
+ end
2294
2223
 
2295
- context "when there are no errors" do
2224
+ context 'when deleting from the inverse side' do
2225
+ let(:reloaded) { tag_two.reload }
2226
+ let!(:deleted) { reloaded.related.send(method, tag_one) }
2296
2227
 
2297
- before do
2298
- post.tags.delete tag
2299
- end
2228
+ it 'deletes the document from the relation' do
2229
+ expect(reloaded.related).to be_empty
2230
+ end
2300
2231
 
2301
- it "executes the callback" do
2302
- expect(post.before_remove_called).to be true
2303
- end
2232
+ it 'deletes the foreign key from the relation' do
2233
+ expect(reloaded.related_ids).to be_empty
2234
+ end
2304
2235
 
2305
- it "removes the document from the relation" do
2306
- expect(post.tags).to be_empty
2236
+ it 'removes the foreign keys from the inverse' do
2237
+ expect(deleted.related_ids).to be_empty
2238
+ end
2307
2239
  end
2308
2240
  end
2241
+ end
2309
2242
 
2310
- context "when errors are raised" do
2311
-
2312
- before do
2313
- expect(post).to receive(:before_remove_tag).and_raise
2314
- begin; post.tags.delete(tag); rescue; end
2315
- end
2243
+ context 'when the association has callbacks' do
2244
+ let(:post) { Post.new }
2245
+ let(:tag) { Tag.new }
2316
2246
 
2317
- it "does not remove the document from the relation" do
2318
- expect(post.tags).to eq([ tag ])
2319
- end
2247
+ before do
2248
+ post.tags << tag
2320
2249
  end
2321
- end
2322
2250
 
2323
- context "when the callback is an after_remove" do
2251
+ context 'when the callback is a before_remove' do
2252
+ context 'when there are no errors' do
2253
+ before do
2254
+ post.tags.send(method, tag)
2255
+ end
2324
2256
 
2325
- context "when no errors are raised" do
2257
+ it 'executes the callback' do
2258
+ expect(post.before_remove_called).to be true
2259
+ end
2326
2260
 
2327
- before do
2328
- post.tags.delete(tag)
2261
+ it 'removes the document from the relation' do
2262
+ expect(post.tags).to be_empty
2263
+ end
2329
2264
  end
2330
2265
 
2331
- it "executes the callback" do
2332
- expect(post.after_remove_called).to be true
2333
- end
2266
+ context "when errors are raised" do
2267
+ before do
2268
+ expect(post).to receive(:before_remove_tag).and_raise
2269
+ begin; post.tags.send(method, tag); rescue; end
2270
+ end
2334
2271
 
2335
- it "removes the document from the relation" do
2336
- expect(post.tags).to be_empty
2272
+ it 'does not remove the document from the relation' do
2273
+ expect(post.tags).to eq([ tag ])
2274
+ end
2337
2275
  end
2338
2276
  end
2339
2277
 
2340
- context "when errors are raised" do
2278
+ context 'when the callback is an after_remove' do
2279
+ context 'when no errors are raised' do
2280
+ before do
2281
+ post.tags.send(method, tag)
2282
+ end
2341
2283
 
2342
- before do
2343
- expect(post).to receive(:after_remove_tag).and_raise
2344
- begin; post.tags.delete(tag); rescue; end
2284
+ it 'executes the callback' do
2285
+ expect(post.after_remove_called).to be true
2286
+ end
2287
+
2288
+ it 'removes the document from the relation' do
2289
+ expect(post.tags).to be_empty
2290
+ end
2345
2291
  end
2346
2292
 
2347
- it "removes the document from the relation" do
2348
- expect(post.tags).to be_empty
2293
+ context 'when errors are raised' do
2294
+ before do
2295
+ expect(post).to receive(:after_remove_tag).and_raise
2296
+ begin; post.tags.send(method, tag); rescue; end
2297
+ end
2298
+
2299
+ it 'removes the document from the relation' do
2300
+ expect(post.tags).to be_empty
2301
+ end
2349
2302
  end
2350
2303
  end
2351
2304
  end
2352
2305
  end
2353
2306
  end
2354
2307
 
2355
- [ :delete_all, :destroy_all ].each do |method|
2356
-
2357
- describe "##{method}" do
2358
-
2359
- context "when the relation is not polymorphic" do
2360
-
2361
- context "when conditions are provided" do
2362
-
2363
- let(:person) do
2364
- Person.create!
2365
- end
2308
+ %i[ delete_all destroy_all ].each do |method|
2309
+ describe "\##{method}" do
2310
+ context 'when the relation is not polymorphic' do
2311
+ context 'when conditions are provided' do
2312
+ let(:person) { Person.create! }
2366
2313
 
2367
2314
  let!(:preference_one) do
2368
2315
  person.preferences.create!(name: "Testing")
@@ -2515,7 +2462,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2515
2462
  it "raises an error" do
2516
2463
  expect {
2517
2464
  preference
2518
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2465
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2519
2466
  end
2520
2467
  end
2521
2468
 
@@ -2530,7 +2477,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2530
2477
  it "raises an error" do
2531
2478
  expect {
2532
2479
  person.preferences.find(BSON::ObjectId.new)
2533
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2480
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2534
2481
  end
2535
2482
  end
2536
2483
 
@@ -2579,7 +2526,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2579
2526
  it "raises an error" do
2580
2527
  expect {
2581
2528
  preferences
2582
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2529
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2583
2530
  end
2584
2531
  end
2585
2532
 
@@ -2594,7 +2541,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2594
2541
  it "raises an error" do
2595
2542
  expect {
2596
2543
  person.preferences.find([ BSON::ObjectId.new ])
2597
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2544
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2598
2545
  end
2599
2546
  end
2600
2547
 
@@ -3778,4 +3725,58 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
3778
3725
  expect(p2.d_ids).to match_array([d2.id])
3779
3726
  end
3780
3727
  end
3728
+
3729
+ context "when accesing own _id from parent's foreign key in default" do
3730
+ let!(:contract) { HabtmmContract.create! }
3731
+ let!(:signature) { contract.signatures.create! }
3732
+
3733
+ it "is nil" do
3734
+ expect(signature.favorite_signature).to be nil
3735
+ end
3736
+ end
3737
+
3738
+ context "when setting an association on a model that uses the class_name option" do
3739
+ let!(:contract) { HabtmmContract.create! }
3740
+ let!(:signature) { HabtmmSignature.create!(contracts: [contract]) }
3741
+
3742
+ it "populates the inverse foreign key" do
3743
+ expect(signature.contracts.first.signature_ids).to eq([signature.id])
3744
+ end
3745
+ end
3746
+
3747
+ context "when there is a foreign key in the aliased associations" do
3748
+ it "has the correct aliases" do
3749
+ expect(Dog.aliased_associations["breed_ids"]).to eq("breeds")
3750
+ expect(Breed.aliased_associations["dog_ids"]).to eq("dogs")
3751
+ end
3752
+ end
3753
+
3754
+ # This test is for MONGOID-5344 which tests that the initial call to
3755
+ # signature_ids refers to the same array as subsequent calls to signature_ids.
3756
+ # Prior to the change in that ticket, this test broke because the array
3757
+ # returned from write_attribute (which is triggered the first time the
3758
+ # foreign key array is referenced, to set the default), refers to a different
3759
+ # array to the one stored in the attributes hash. This happened because,
3760
+ # when retrieving a document from the database, the attributes hash is actually
3761
+ # a BSON::Document, which applies a transformation to the array before
3762
+ # storing it.
3763
+ context "when executing concat on foreign key array from the db" do
3764
+ config_override :legacy_attributes, false
3765
+
3766
+ before do
3767
+ HabtmmContract.create!
3768
+ HabtmmSignature.create!
3769
+ end
3770
+
3771
+ let!(:contract) { HabtmmContract.first }
3772
+ let!(:signature) { HabtmmSignature.first }
3773
+
3774
+ before do
3775
+ contract.signature_ids.concat([signature.id])
3776
+ end
3777
+
3778
+ it "works on the first attempt" do
3779
+ expect(contract.signature_ids).to eq([signature.id])
3780
+ end
3781
+ end
3781
3782
  end
@@ -32,6 +32,8 @@ end
32
32
  class HabtmmSignature
33
33
  include Mongoid::Document
34
34
 
35
+ field :favorite_signature, default: ->{ contracts.first.signature_ids.first if contracts.first }
36
+
35
37
  has_and_belongs_to_many :contracts, class_name: 'HabtmmContract'
36
38
 
37
39
  field :name, type: String
@@ -65,3 +67,26 @@ class HabtmmAnimal
65
67
 
66
68
  has_and_belongs_to_many :trainers, inverse_of: :animals, class_name: 'HabtmmTrainer', scope: -> { where(name: 'Dave') }
67
69
  end
70
+
71
+ class HabtmmSchool
72
+ include Mongoid::Document
73
+ include Mongoid::Timestamps
74
+
75
+ has_and_belongs_to_many :students, class_name: 'HabtmmStudent'
76
+
77
+ field :after_destroy_triggered, default: false
78
+
79
+ accepts_nested_attributes_for :students, allow_destroy: true
80
+ end
81
+
82
+ class HabtmmStudent
83
+ include Mongoid::Document
84
+ include Mongoid::Timestamps
85
+
86
+ has_and_belongs_to_many :schools, class_name: 'HabtmmSchool'
87
+
88
+ after_destroy do |doc|
89
+ schools.first.update_attributes!(after_destroy_triggered: true) unless schools.empty?
90
+ end
91
+ end
92
+
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative "./has_and_belongs_to_many_models"
4
5
 
5
6
  describe Mongoid::Association::Referenced::HasAndBelongsToMany do
6
7
 
@@ -1008,8 +1009,8 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1008
1009
 
1009
1010
  describe '#foreign_key_check' do
1010
1011
 
1011
- it 'returns the foreign_key followed by "_changed?"' do
1012
- expect(association.foreign_key_check).to eq('has_many_right_object_ids_changed?')
1012
+ it 'returns the foreign_key followed by "_previously_changed?"' do
1013
+ expect(association.foreign_key_check).to eq('has_many_right_object_ids_previously_changed?')
1013
1014
  end
1014
1015
  end
1015
1016
 
@@ -1060,6 +1061,13 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1060
1061
  expect(association.inverse_foreign_key).to eq('bar_ref')
1061
1062
  end
1062
1063
  end
1064
+
1065
+ context "when using a model that uses the class_name option" do
1066
+ let(:inverse_foreign_key) { HabtmmSchool.relations[:students].inverse_foreign_key }
1067
+ it "gets the correct inverse foreign key" do
1068
+ expect(inverse_foreign_key).to eq("school_ids")
1069
+ end
1070
+ end
1063
1071
  end
1064
1072
 
1065
1073
  describe '#inverse_foreign_key_setter' do
@@ -1068,4 +1076,29 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1068
1076
  expect(association.inverse_foreign_key_setter).to eq('has_many_left_object_ids=')
1069
1077
  end
1070
1078
  end
1079
+
1080
+ context "when adding an object to the association" do
1081
+ let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
1082
+
1083
+ let(:update_time) do
1084
+ Timecop.freeze(Time.at(Time.now.to_i) + 2)
1085
+ end
1086
+
1087
+ after do
1088
+ Timecop.return
1089
+ end
1090
+
1091
+ let!(:school) { HabtmmSchool.create! }
1092
+ let!(:student) { HabtmmStudent.create! }
1093
+
1094
+ before do
1095
+ update_time
1096
+ school.update(students: [student])
1097
+ end
1098
+
1099
+ it "updates the updated at" do
1100
+ pending "MONGOID-4953"
1101
+ expect(school.updated_at).to eq(update_time)
1102
+ end
1103
+ end
1071
1104
  end