mongoid 7.5.4 → 8.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (442) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -3
  3. data/README.md +6 -6
  4. data/Rakefile +44 -46
  5. data/lib/config/locales/en.yml +92 -43
  6. data/lib/mongoid/association/accessors.rb +44 -11
  7. data/lib/mongoid/association/bindable.rb +50 -2
  8. data/lib/mongoid/association/builders.rb +5 -3
  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 +34 -11
  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/buildable.rb +2 -2
  15. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +4 -3
  16. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  17. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  18. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +4 -3
  19. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +85 -46
  20. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  21. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +19 -5
  22. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +24 -5
  23. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  24. data/lib/mongoid/association/macros.rb +8 -1
  25. data/lib/mongoid/association/many.rb +11 -7
  26. data/lib/mongoid/association/nested/many.rb +5 -4
  27. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  28. data/lib/mongoid/association/nested/one.rb +45 -7
  29. data/lib/mongoid/association/one.rb +2 -2
  30. data/lib/mongoid/association/options.rb +9 -9
  31. data/lib/mongoid/association/proxy.rb +15 -4
  32. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  33. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  34. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  35. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  36. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  37. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  38. data/lib/mongoid/association/referenced/eager.rb +2 -2
  39. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
  40. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  41. data/lib/mongoid/association/referenced/has_many/enumerable.rb +22 -30
  42. data/lib/mongoid/association/referenced/has_many/proxy.rb +40 -21
  43. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  44. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  45. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  46. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  47. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  48. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  49. data/lib/mongoid/association/reflections.rb +4 -4
  50. data/lib/mongoid/association/relatable.rb +44 -10
  51. data/lib/mongoid/association.rb +5 -5
  52. data/lib/mongoid/atomic/modifiers.rb +2 -2
  53. data/lib/mongoid/atomic.rb +16 -7
  54. data/lib/mongoid/attributes/dynamic.rb +4 -4
  55. data/lib/mongoid/attributes/nested.rb +6 -6
  56. data/lib/mongoid/attributes/processing.rb +37 -6
  57. data/lib/mongoid/attributes/projector.rb +2 -2
  58. data/lib/mongoid/attributes/readonly.rb +3 -3
  59. data/lib/mongoid/attributes.rb +51 -42
  60. data/lib/mongoid/changeable.rb +147 -14
  61. data/lib/mongoid/clients/options.rb +5 -1
  62. data/lib/mongoid/clients/sessions.rb +2 -14
  63. data/lib/mongoid/clients/storage_options.rb +2 -5
  64. data/lib/mongoid/clients/validators/storage.rb +3 -15
  65. data/lib/mongoid/collection_configurable.rb +58 -0
  66. data/lib/mongoid/composable.rb +2 -0
  67. data/lib/mongoid/config/defaults.rb +60 -0
  68. data/lib/mongoid/config/options.rb +3 -0
  69. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  70. data/lib/mongoid/config/validators/client.rb +6 -6
  71. data/lib/mongoid/config/validators.rb +1 -0
  72. data/lib/mongoid/config.rb +153 -18
  73. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  74. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  75. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  76. data/lib/mongoid/contextual/atomic.rb +1 -1
  77. data/lib/mongoid/contextual/geo_near.rb +7 -7
  78. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  79. data/lib/mongoid/contextual/memory.rb +285 -58
  80. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  81. data/lib/mongoid/contextual/mongo.rb +540 -346
  82. data/lib/mongoid/contextual/none.rb +193 -20
  83. data/lib/mongoid/contextual/queryable.rb +1 -1
  84. data/lib/mongoid/contextual.rb +14 -2
  85. data/lib/mongoid/copyable.rb +32 -8
  86. data/lib/mongoid/criteria/findable.rb +8 -5
  87. data/lib/mongoid/criteria/includable.rb +27 -22
  88. data/lib/mongoid/criteria/marshalable.rb +10 -2
  89. data/lib/mongoid/criteria/permission.rb +1 -1
  90. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  91. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -16
  92. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  93. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  94. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  95. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  96. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -17
  97. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -9
  98. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  99. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  100. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  101. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  102. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
  103. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
  104. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  105. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  106. data/lib/mongoid/criteria/queryable/key.rb +4 -4
  107. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  108. data/lib/mongoid/criteria/queryable/optional.rb +11 -17
  109. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  110. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  111. data/lib/mongoid/criteria/queryable/selectable.rb +47 -38
  112. data/lib/mongoid/criteria/queryable/selector.rb +92 -7
  113. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  114. data/lib/mongoid/criteria/queryable.rb +12 -7
  115. data/lib/mongoid/criteria/scopable.rb +2 -2
  116. data/lib/mongoid/criteria/translator.rb +45 -0
  117. data/lib/mongoid/criteria.rb +20 -40
  118. data/lib/mongoid/deprecable.rb +37 -0
  119. data/lib/mongoid/deprecation.rb +25 -0
  120. data/lib/mongoid/document.rb +127 -35
  121. data/lib/mongoid/equality.rb +8 -8
  122. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  123. data/lib/mongoid/errors/document_not_found.rb +10 -6
  124. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  125. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  126. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  127. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  128. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  129. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  130. data/lib/mongoid/errors/invalid_field.rb +6 -2
  131. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  132. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  133. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  134. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  135. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  136. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  137. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  138. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  139. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  140. data/lib/mongoid/errors/no_client_database.rb +1 -1
  141. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  142. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  143. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  144. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  145. data/lib/mongoid/errors.rb +6 -3
  146. data/lib/mongoid/extensions/array.rb +9 -7
  147. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  148. data/lib/mongoid/extensions/binary.rb +42 -0
  149. data/lib/mongoid/extensions/boolean.rb +8 -2
  150. data/lib/mongoid/extensions/date.rb +26 -20
  151. data/lib/mongoid/extensions/date_time.rb +1 -1
  152. data/lib/mongoid/extensions/false_class.rb +1 -1
  153. data/lib/mongoid/extensions/float.rb +7 -4
  154. data/lib/mongoid/extensions/hash.rb +38 -9
  155. data/lib/mongoid/extensions/integer.rb +7 -4
  156. data/lib/mongoid/extensions/module.rb +1 -1
  157. data/lib/mongoid/extensions/object.rb +10 -8
  158. data/lib/mongoid/extensions/range.rb +41 -10
  159. data/lib/mongoid/extensions/regexp.rb +11 -4
  160. data/lib/mongoid/extensions/set.rb +11 -4
  161. data/lib/mongoid/extensions/string.rb +11 -22
  162. data/lib/mongoid/extensions/symbol.rb +4 -15
  163. data/lib/mongoid/extensions/time.rb +29 -16
  164. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  165. data/lib/mongoid/extensions/true_class.rb +1 -1
  166. data/lib/mongoid/extensions.rb +1 -0
  167. data/lib/mongoid/factory.rb +55 -7
  168. data/lib/mongoid/fields/foreign_key.rb +11 -4
  169. data/lib/mongoid/fields/localized.rb +19 -4
  170. data/lib/mongoid/fields/standard.rb +17 -7
  171. data/lib/mongoid/fields/validators/macro.rb +3 -9
  172. data/lib/mongoid/fields.rb +142 -28
  173. data/lib/mongoid/findable.rb +54 -24
  174. data/lib/mongoid/indexable/specification.rb +2 -2
  175. data/lib/mongoid/indexable/validators/options.rb +6 -2
  176. data/lib/mongoid/interceptable.rb +186 -16
  177. data/lib/mongoid/matchable.rb +1 -1
  178. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  179. data/lib/mongoid/matcher/type.rb +1 -1
  180. data/lib/mongoid/matcher.rb +33 -13
  181. data/lib/mongoid/persistable/creatable.rb +19 -9
  182. data/lib/mongoid/persistable/deletable.rb +2 -2
  183. data/lib/mongoid/persistable/destroyable.rb +1 -1
  184. data/lib/mongoid/persistable/savable.rb +14 -2
  185. data/lib/mongoid/persistable/unsettable.rb +2 -2
  186. data/lib/mongoid/persistable/updatable.rb +69 -12
  187. data/lib/mongoid/persistable/upsertable.rb +21 -2
  188. data/lib/mongoid/persistable.rb +6 -3
  189. data/lib/mongoid/persistence_context.rb +6 -4
  190. data/lib/mongoid/query_cache.rb +13 -261
  191. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  192. data/lib/mongoid/railties/database.rake +7 -2
  193. data/lib/mongoid/reloadable.rb +10 -8
  194. data/lib/mongoid/scopable.rb +15 -13
  195. data/lib/mongoid/selectable.rb +1 -2
  196. data/lib/mongoid/serializable.rb +10 -6
  197. data/lib/mongoid/stateful.rb +57 -10
  198. data/lib/mongoid/tasks/database.rake +12 -0
  199. data/lib/mongoid/tasks/database.rb +20 -2
  200. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  201. data/lib/mongoid/threaded.rb +42 -12
  202. data/lib/mongoid/timestamps/created.rb +1 -1
  203. data/lib/mongoid/timestamps/updated.rb +2 -2
  204. data/lib/mongoid/touchable.rb +3 -4
  205. data/lib/mongoid/traversable.rb +5 -4
  206. data/lib/mongoid/utils.rb +22 -0
  207. data/lib/mongoid/validatable/associated.rb +96 -18
  208. data/lib/mongoid/validatable/localizable.rb +1 -1
  209. data/lib/mongoid/validatable/macros.rb +5 -7
  210. data/lib/mongoid/validatable/presence.rb +2 -2
  211. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  212. data/lib/mongoid/validatable.rb +17 -6
  213. data/lib/mongoid/version.rb +1 -1
  214. data/lib/mongoid/warnings.rb +19 -4
  215. data/lib/mongoid.rb +17 -3
  216. data/spec/config/mongoid.yml +16 -0
  217. data/spec/integration/app_spec.rb +13 -16
  218. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  219. data/spec/integration/associations/embedded_spec.rb +15 -0
  220. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  221. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  222. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  223. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +61 -0
  224. data/spec/integration/associations/has_one_spec.rb +97 -1
  225. data/spec/integration/associations/scope_option_spec.rb +1 -1
  226. data/spec/integration/callbacks_models.rb +132 -1
  227. data/spec/integration/callbacks_spec.rb +381 -4
  228. data/spec/integration/criteria/range_spec.rb +95 -1
  229. data/spec/integration/discriminator_key_spec.rb +118 -80
  230. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  231. data/spec/integration/i18n_fallbacks_spec.rb +3 -32
  232. data/spec/integration/matcher_examples_spec.rb +20 -13
  233. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  234. data/spec/integration/matcher_operator_spec.rb +3 -5
  235. data/spec/integration/persistence/range_field_spec.rb +350 -0
  236. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  237. data/spec/mongoid/association/depending_spec.rb +9 -9
  238. data/spec/mongoid/association/eager_spec.rb +2 -1
  239. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  240. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  241. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +96 -9
  242. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  243. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +290 -65
  244. data/spec/mongoid/association/embedded/embeds_many_models.rb +37 -0
  245. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +16 -0
  246. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  247. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  248. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  249. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  250. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  251. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  252. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  253. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  254. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  255. data/spec/mongoid/association/referenced/belongs_to_spec.rb +4 -20
  256. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +186 -229
  257. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  258. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  259. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  260. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  261. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +215 -177
  262. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  263. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  264. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  265. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  266. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  267. data/spec/mongoid/association/syncable_spec.rb +15 -1
  268. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  269. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  270. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  271. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  272. data/spec/mongoid/attributes_spec.rb +526 -33
  273. data/spec/mongoid/changeable_spec.rb +429 -37
  274. data/spec/mongoid/clients/factory_spec.rb +23 -30
  275. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  276. data/spec/mongoid/clients_spec.rb +149 -15
  277. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  278. data/spec/mongoid/config/defaults_spec.rb +160 -0
  279. data/spec/mongoid/config_spec.rb +214 -31
  280. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  281. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  282. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  283. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  284. data/spec/mongoid/contextual/memory_spec.rb +850 -88
  285. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  286. data/spec/mongoid/contextual/mongo_spec.rb +2256 -1005
  287. data/spec/mongoid/contextual/none_spec.rb +60 -21
  288. data/spec/mongoid/copyable_spec.rb +453 -11
  289. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  290. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  291. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  292. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  293. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  294. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  295. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  296. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  297. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  298. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  299. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  300. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  301. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  302. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  303. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
  304. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  305. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +469 -0
  306. data/spec/mongoid/criteria/queryable/selectable_spec.rb +78 -86
  307. data/spec/mongoid/criteria/queryable/selector_spec.rb +15 -3
  308. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  309. data/spec/mongoid/criteria_projection_spec.rb +1 -5
  310. data/spec/mongoid/criteria_spec.rb +469 -1205
  311. data/spec/mongoid/document_fields_spec.rb +173 -24
  312. data/spec/mongoid/document_spec.rb +32 -41
  313. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  314. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  315. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  316. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  317. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  318. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  319. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  320. data/spec/mongoid/extensions/array_spec.rb +16 -2
  321. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  322. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  323. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  324. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  325. data/spec/mongoid/extensions/date_spec.rb +71 -1
  326. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  327. data/spec/mongoid/extensions/float_spec.rb +53 -74
  328. data/spec/mongoid/extensions/hash_spec.rb +33 -3
  329. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  330. data/spec/mongoid/extensions/range_spec.rb +255 -54
  331. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  332. data/spec/mongoid/extensions/set_spec.rb +106 -0
  333. data/spec/mongoid/extensions/string_spec.rb +53 -25
  334. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  335. data/spec/mongoid/extensions/time_spec.rb +639 -106
  336. data/spec/mongoid/extensions/time_with_zone_spec.rb +24 -83
  337. data/spec/mongoid/factory_spec.rb +61 -1
  338. data/spec/mongoid/fields/localized_spec.rb +80 -37
  339. data/spec/mongoid/fields_spec.rb +503 -87
  340. data/spec/mongoid/findable_spec.rb +450 -58
  341. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  342. data/spec/mongoid/indexable_spec.rb +55 -30
  343. data/spec/mongoid/interceptable_spec.rb +824 -22
  344. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  345. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  346. data/spec/mongoid/mongoizable_spec.rb +285 -0
  347. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  348. data/spec/mongoid/persistable/deletable_spec.rb +28 -8
  349. data/spec/mongoid/persistable/destroyable_spec.rb +28 -8
  350. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  351. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  352. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  353. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  354. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  355. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  356. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  357. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  358. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  359. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  360. data/spec/mongoid/persistable/upsertable_spec.rb +89 -1
  361. data/spec/mongoid/persistence_context_spec.rb +31 -57
  362. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  363. data/spec/mongoid/query_cache_spec.rb +56 -215
  364. data/spec/mongoid/reloadable_spec.rb +83 -6
  365. data/spec/mongoid/scopable_spec.rb +91 -1
  366. data/spec/mongoid/serializable_spec.rb +25 -39
  367. data/spec/mongoid/shardable_spec.rb +4 -4
  368. data/spec/mongoid/stateful_spec.rb +150 -8
  369. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  370. data/spec/mongoid/tasks/database_spec.rb +127 -0
  371. data/spec/mongoid/timestamps_spec.rb +392 -4
  372. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  373. data/spec/mongoid/touchable_spec.rb +390 -2
  374. data/spec/mongoid/touchable_spec_models.rb +14 -8
  375. data/spec/mongoid/traversable_spec.rb +13 -35
  376. data/spec/mongoid/validatable/associated_spec.rb +13 -30
  377. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  378. data/spec/mongoid/validatable/uniqueness_spec.rb +58 -31
  379. data/spec/mongoid/warnings_spec.rb +35 -0
  380. data/spec/mongoid_spec.rb +34 -16
  381. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  382. data/spec/rails/mongoid_spec.rb +4 -16
  383. data/spec/spec_helper.rb +5 -0
  384. data/spec/support/constraints.rb +24 -0
  385. data/spec/support/immutable_ids.rb +118 -0
  386. data/spec/support/macros.rb +78 -0
  387. data/spec/support/models/artist.rb +0 -1
  388. data/spec/support/models/augmentation.rb +12 -0
  389. data/spec/support/models/band.rb +5 -0
  390. data/spec/support/models/book.rb +1 -0
  391. data/spec/support/models/building.rb +2 -0
  392. data/spec/support/models/catalog.rb +24 -0
  393. data/spec/support/models/circus.rb +3 -0
  394. data/spec/support/models/cover.rb +10 -0
  395. data/spec/support/models/fanatic.rb +8 -0
  396. data/spec/support/models/implant.rb +9 -0
  397. data/spec/support/models/label.rb +2 -0
  398. data/spec/support/models/lat_lng.rb +6 -0
  399. data/spec/support/models/name.rb +10 -0
  400. data/spec/support/models/passport.rb +9 -0
  401. data/spec/support/models/person.rb +2 -0
  402. data/spec/support/models/player.rb +2 -0
  403. data/spec/support/models/powerup.rb +12 -0
  404. data/spec/support/models/product.rb +1 -0
  405. data/spec/support/models/purse.rb +9 -0
  406. data/spec/support/models/registry.rb +1 -0
  407. data/spec/support/models/school.rb +14 -0
  408. data/spec/support/models/shield.rb +18 -0
  409. data/spec/support/models/student.rb +14 -0
  410. data/spec/support/models/weapon.rb +12 -0
  411. metadata +101 -96
  412. checksums.yaml.gz.sig +0 -0
  413. data/lib/mongoid/errors/eager_load.rb +0 -23
  414. data/lib/mongoid/errors/invalid_value.rb +0 -17
  415. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  416. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  417. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  418. data/spec/shared/LICENSE +0 -20
  419. data/spec/shared/bin/get-mongodb-download-url +0 -17
  420. data/spec/shared/bin/s3-copy +0 -45
  421. data/spec/shared/bin/s3-upload +0 -69
  422. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  423. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  424. data/spec/shared/lib/mrss/constraints.rb +0 -378
  425. data/spec/shared/lib/mrss/docker_runner.rb +0 -291
  426. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  427. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  428. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  429. data/spec/shared/lib/mrss/server_version_registry.rb +0 -120
  430. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  431. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  432. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  433. data/spec/shared/lib/mrss/utils.rb +0 -15
  434. data/spec/shared/share/Dockerfile.erb +0 -325
  435. data/spec/shared/share/haproxy-1.conf +0 -16
  436. data/spec/shared/share/haproxy-2.conf +0 -17
  437. data/spec/shared/shlib/config.sh +0 -27
  438. data/spec/shared/shlib/distro.sh +0 -74
  439. data/spec/shared/shlib/server.sh +0 -392
  440. data/spec/shared/shlib/set_env.sh +0 -169
  441. data.tar.gz.sig +0 -0
  442. metadata.gz.sig +0 -3
@@ -1862,51 +1862,56 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
1862
1862
  end
1863
1863
  end
1864
1864
 
1865
- describe "#delete" do
1865
+ %i[ delete delete_one ].each do |method|
1866
+ describe "\##{method}" do
1867
+ let(:address_one) { Address.new(street: "first") }
1868
+ let(:address_two) { Address.new(street: "second") }
1866
1869
 
1867
- let(:person) do
1868
- Person.new
1869
- end
1870
-
1871
- let(:address_one) do
1872
- Address.new(street: "first")
1873
- end
1870
+ before do
1871
+ person.addresses << [ address_one, address_two ]
1872
+ end
1874
1873
 
1875
- let(:address_two) do
1876
- Address.new(street: "second")
1877
- end
1874
+ shared_examples_for 'deleting from the collection' do
1875
+ context 'when the document exists in the relation' do
1876
+ let!(:deleted) do
1877
+ person.addresses.send(method, address_one)
1878
+ end
1878
1879
 
1879
- before do
1880
- person.addresses << [ address_one, address_two ]
1881
- end
1880
+ it 'deletes the document' do
1881
+ expect(person.addresses).to eq([ address_two ])
1882
+ expect(person.reload.addresses).to eq([ address_two ]) if person.persisted?
1883
+ end
1882
1884
 
1883
- context "when the document exists in the relation" do
1885
+ it 'deletes the document from the unscoped' do
1886
+ expect(person.addresses.send(:_unscoped)).to eq([ address_two ])
1887
+ end
1884
1888
 
1885
- let!(:deleted) do
1886
- person.addresses.delete(address_one)
1887
- end
1889
+ it 'reindexes the relation' do
1890
+ expect(address_two._index).to eq(0)
1891
+ end
1888
1892
 
1889
- it "deletes the document" do
1890
- expect(person.addresses).to eq([ address_two ])
1891
- end
1893
+ it 'returns the document' do
1894
+ expect(deleted).to eq(address_one)
1895
+ end
1896
+ end
1892
1897
 
1893
- it "deletes the document from the unscoped" do
1894
- expect(person.addresses.send(:_unscoped)).to eq([ address_two ])
1898
+ context 'when the document does not exist' do
1899
+ it 'returns nil' do
1900
+ expect(person.addresses.send(method, Address.new)).to be_nil
1901
+ end
1902
+ end
1895
1903
  end
1896
1904
 
1897
- it "reindexes the relation" do
1898
- expect(address_two._index).to eq(0)
1899
- end
1905
+ context 'when the root document is unpersisted' do
1906
+ let(:person) { Person.new }
1900
1907
 
1901
- it "returns the document" do
1902
- expect(deleted).to eq(address_one)
1908
+ it_behaves_like 'deleting from the collection'
1903
1909
  end
1904
- end
1905
1910
 
1906
- context "when the document does not exist" do
1911
+ context 'when the root document is persisted' do
1912
+ let(:person) { Person.create }
1907
1913
 
1908
- it "returns nil" do
1909
- expect(person.addresses.delete(Address.new)).to be_nil
1914
+ it_behaves_like 'deleting from the collection'
1910
1915
  end
1911
1916
  end
1912
1917
  end
@@ -2210,6 +2215,79 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2210
2215
  end
2211
2216
  end
2212
2217
  end
2218
+
2219
+ context "when modifying the document beforehand" do
2220
+ let(:parent) { EmmParent.new }
2221
+
2222
+ before do
2223
+
2224
+ parent.blocks << EmmBlock.new(name: 'test', children: [size: 1, order: 1])
2225
+ parent.save!
2226
+
2227
+ parent.blocks[0].children[0].assign_attributes(size: 2)
2228
+
2229
+ parent.blocks.destroy_all(:name => 'test')
2230
+ end
2231
+
2232
+ it "deletes the correct document in the database" do
2233
+ expect(parent.reload.blocks.length).to eq(0)
2234
+ end
2235
+ end
2236
+
2237
+ context "when nil _id" do
2238
+ let(:parent) { EmmParent.new }
2239
+
2240
+ before do
2241
+ parent.blocks << EmmBlock.new(_id: nil, name: 'test', children: [size: 1, order: 1])
2242
+ parent.blocks << EmmBlock.new(_id: nil, name: 'test2', children: [size: 1, order: 1])
2243
+ parent.save!
2244
+
2245
+ parent.blocks.destroy_all(:name => 'test')
2246
+ end
2247
+
2248
+ it "deletes only the matching documents in the database" do
2249
+ expect(parent.reload.blocks.length).to eq(1)
2250
+ end
2251
+ end
2252
+
2253
+ # Since without an _id field we must us a $pullAll with the attributes of
2254
+ # the embedded document, if you modify it beforehand, the query will not
2255
+ # be able to find the correct document to pull.
2256
+ context "when modifying the document with nil _id" do
2257
+ let(:parent) { EmmParent.new }
2258
+
2259
+ before do
2260
+ parent.blocks << EmmBlock.new(_id: nil, name: 'test', children: [size: 1, order: 1])
2261
+ parent.blocks << EmmBlock.new(_id: nil, name: 'test2', children: [size: 1, order: 1])
2262
+ parent.save!
2263
+
2264
+ parent.blocks[0].children[0].assign_attributes(size: 2)
2265
+
2266
+ parent.blocks.destroy_all(:name => 'test')
2267
+ end
2268
+
2269
+ it "does not delete the correct documents" do
2270
+ expect(parent.reload.blocks.length).to eq(2)
2271
+ end
2272
+ end
2273
+
2274
+ context "when documents with and without _id" do
2275
+ let(:parent) { EmmParent.new }
2276
+
2277
+ before do
2278
+ parent.blocks << EmmBlock.new(_id: nil, name: 'test', children: [size: 1, order: 1])
2279
+ parent.blocks << EmmBlock.new(name: 'test', children: [size: 1, order: 1])
2280
+ parent.save!
2281
+
2282
+ parent.blocks[1].children[0].assign_attributes(size: 2)
2283
+
2284
+ parent.blocks.destroy_all(:name => 'test')
2285
+ end
2286
+
2287
+ it "does not delete the correct documents" do
2288
+ expect(parent.reload.blocks.length).to eq(0)
2289
+ end
2290
+ end
2213
2291
  end
2214
2292
  end
2215
2293
 
@@ -2232,9 +2310,37 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2232
2310
  person.addresses.create!(street: "Bond St")
2233
2311
  end
2234
2312
 
2313
+ let(:address) { person.addresses.first }
2314
+
2235
2315
  it "returns true" do
2236
2316
  expect(person.addresses.exists?).to be true
2237
2317
  end
2318
+
2319
+ context 'when given specifying conditions' do
2320
+ context 'when the record exists in the association' do
2321
+ it 'returns true by condition' do
2322
+ expect(person.addresses.exists?(street: 'Bond St')).to be true
2323
+ end
2324
+
2325
+ it 'returns true by id' do
2326
+ expect(person.addresses.exists?(address._id)).to be true
2327
+ end
2328
+
2329
+ it 'returns false when given false' do
2330
+ expect(person.addresses.exists?(false)).to be false
2331
+ end
2332
+
2333
+ it 'returns false when given nil' do
2334
+ expect(person.addresses.exists?(nil)).to be false
2335
+ end
2336
+ end
2337
+
2338
+ context 'when the record does not exist in the association' do
2339
+ it 'returns false' do
2340
+ expect(person.addresses.exists?(street: 'Garfield Ave')).to be false
2341
+ end
2342
+ end
2343
+ end
2238
2344
  end
2239
2345
 
2240
2346
  context "when no documents exist in the database" do
@@ -2246,6 +2352,13 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2246
2352
  it "returns false" do
2247
2353
  expect(person.addresses.exists?).to be false
2248
2354
  end
2355
+
2356
+ context 'when given specifying conditions' do
2357
+ it 'returns false' do
2358
+ expect(person.addresses.exists?(street: 'Hyde Park Dr')).to be false
2359
+ expect(person.addresses.exists?(street: 'Garfield Ave')).to be false
2360
+ end
2361
+ end
2249
2362
  end
2250
2363
  end
2251
2364
 
@@ -2279,32 +2392,22 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2279
2392
  context "when the id does not match" do
2280
2393
 
2281
2394
  context "when config set to raise error" do
2282
-
2283
- before do
2284
- Mongoid.raise_not_found_error = true
2285
- end
2395
+ config_override :raise_not_found_error, true
2286
2396
 
2287
2397
  it "raises an error" do
2288
2398
  expect {
2289
2399
  person.addresses.find(BSON::ObjectId.new)
2290
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2400
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Address with id\(s\)/)
2291
2401
  end
2292
2402
  end
2293
2403
 
2294
2404
  context "when config set not to raise error" do
2405
+ config_override :raise_not_found_error, false
2295
2406
 
2296
2407
  let(:address) do
2297
2408
  person.addresses.find(BSON::ObjectId.new)
2298
2409
  end
2299
2410
 
2300
- before do
2301
- Mongoid.raise_not_found_error = false
2302
- end
2303
-
2304
- after do
2305
- Mongoid.raise_not_found_error = true
2306
- end
2307
-
2308
2411
  it "returns nil" do
2309
2412
  expect(address).to be_nil
2310
2413
  end
@@ -2328,32 +2431,22 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2328
2431
  context "when the ids do not match" do
2329
2432
 
2330
2433
  context "when config set to raise error" do
2331
-
2332
- before do
2333
- Mongoid.raise_not_found_error = true
2334
- end
2434
+ config_override :raise_not_found_error, true
2335
2435
 
2336
2436
  it "raises an error" do
2337
2437
  expect {
2338
2438
  person.addresses.find([ BSON::ObjectId.new ])
2339
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2439
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Address with id\(s\)/)
2340
2440
  end
2341
2441
  end
2342
2442
 
2343
2443
  context "when config set not to raise error" do
2444
+ config_override :raise_not_found_error, false
2344
2445
 
2345
2446
  let(:addresses) do
2346
2447
  person.addresses.find([ BSON::ObjectId.new ])
2347
2448
  end
2348
2449
 
2349
- before do
2350
- Mongoid.raise_not_found_error = false
2351
- end
2352
-
2353
- after do
2354
- Mongoid.raise_not_found_error = true
2355
- end
2356
-
2357
2450
  it "returns an empty array" do
2358
2451
  expect(addresses).to be_empty
2359
2452
  end
@@ -3461,7 +3554,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3461
3554
 
3462
3555
  describe "replacing the entire embedded list" do
3463
3556
 
3464
- context "when an embeds many relationship contains a nil as the first item" do
3557
+ context "when an embeds many relationship contains nil as the first item" do
3465
3558
 
3466
3559
  let(:person) do
3467
3560
  Person.create!
@@ -3482,7 +3575,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3482
3575
  end
3483
3576
  end
3484
3577
 
3485
- context "when an embeds many relationship contains a nil in the middle of the list" do
3578
+ context "when an embeds many relationship contains nil in the middle of the list" do
3486
3579
 
3487
3580
  let(:person) do
3488
3581
  Person.create!
@@ -3503,7 +3596,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3503
3596
  end
3504
3597
  end
3505
3598
 
3506
- context "when an embeds many relationship contains a nil at the end of the list" do
3599
+ context "when an embeds many relationship contains nil at the end of the list" do
3507
3600
 
3508
3601
  let(:person) do
3509
3602
  Person.create!
@@ -3527,7 +3620,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3527
3620
 
3528
3621
  describe "appending to the embedded list" do
3529
3622
 
3530
- context "when appending a nil to the first position in an embedded list" do
3623
+ context "when appending nil to the first position in an embedded list" do
3531
3624
 
3532
3625
  let(:person) do
3533
3626
  Person.create! phone_numbers: []
@@ -3546,7 +3639,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3546
3639
  end
3547
3640
  end
3548
3641
 
3549
- context "when appending a nil into the middle of an embedded list" do
3642
+ context "when appending nil into the middle of an embedded list" do
3550
3643
 
3551
3644
  let(:person) do
3552
3645
  Person.create! phone_numbers: []
@@ -3565,7 +3658,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3565
3658
  end
3566
3659
  end
3567
3660
 
3568
- context "when appending a nil to the end of an embedded list" do
3661
+ context "when appending nil to the end of an embedded list" do
3569
3662
 
3570
3663
  let(:person) do
3571
3664
  Person.create! phone_numbers: []
@@ -3960,6 +4053,28 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3960
4053
  end
3961
4054
  end
3962
4055
 
4056
+ context "when destroying a document with multiple nil _ids" do
4057
+ let(:congress) { EmmCongress.create! }
4058
+
4059
+ before do
4060
+ congress.legislators << EmmLegislator.new(_id: nil, a: 1)
4061
+ congress.legislators << EmmLegislator.new(_id: nil, a: 2)
4062
+
4063
+ congress.legislators[0].destroy
4064
+ end
4065
+
4066
+ it "deletes the correct document locally" do
4067
+ pending "MONGOID-5394"
4068
+ expect(congress.legislators.length).to eq(1)
4069
+ expect(congress.legislators.first.a).to eq(1)
4070
+ end
4071
+
4072
+ it "only deletes the one document" do
4073
+ pending "MONGOID-5394"
4074
+ expect(congress.reload.legislators.length).to eq(1)
4075
+ end
4076
+ end
4077
+
3963
4078
  context "when adding a document" do
3964
4079
 
3965
4080
  let(:person) do
@@ -4491,7 +4606,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
4491
4606
  before do
4492
4607
  band.collection.
4493
4608
  find(_id: band.id).
4494
- update_one("$set" => { records: [{ name: "Moderat" }]})
4609
+ update_one("$set" => { records: [{ _id: BSON::ObjectId.new, name: "Moderat" }]})
4495
4610
  end
4496
4611
 
4497
4612
  context "when loading the documents" do
@@ -4651,6 +4766,55 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
4651
4766
  end
4652
4767
  end
4653
4768
 
4769
+ context "when trying to persist the empty list" do
4770
+
4771
+ context "in an embeds_many relation" do
4772
+
4773
+ let(:band) { Band.create! }
4774
+
4775
+ before do
4776
+ band.labels = []
4777
+ band.save!
4778
+ end
4779
+
4780
+ let(:reloaded_band) { Band.collection.find(_id: band._id).first }
4781
+
4782
+ it "persists the empty list" do
4783
+ expect(reloaded_band).to have_key(:labels)
4784
+ expect(reloaded_band[:labels]).to eq []
4785
+ end
4786
+ end
4787
+
4788
+ context "in a nested embeds_many relation" do
4789
+
4790
+ let(:survey) { Survey.create!(questions: [Question.new]) }
4791
+
4792
+ before do
4793
+ survey.questions.first.answers = []
4794
+ survey.save!
4795
+ end
4796
+
4797
+ let(:reloaded_survey) { Survey.collection.find(_id: survey._id).first }
4798
+
4799
+ it "persists the empty list" do
4800
+ expect(reloaded_survey).to have_key(:questions)
4801
+ expect(reloaded_survey[:questions][0]).to have_key(:answers)
4802
+ expect(reloaded_survey[:questions][0][:answers]).to eq []
4803
+ end
4804
+ end
4805
+
4806
+ context "when not setting the embeds_many field" do
4807
+
4808
+ let(:band) { Band.create! }
4809
+
4810
+ let(:reloaded_band) { Band.collection.find(_id: band._id).first }
4811
+
4812
+ it "does not persist the empty list" do
4813
+ expect(reloaded_band).to_not have_key(:labels)
4814
+ end
4815
+ end
4816
+ end
4817
+
4654
4818
  context "when using assign_attributes with an already populated array" do
4655
4819
  let(:post) { EmmPost.create! }
4656
4820
 
@@ -4670,4 +4834,65 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
4670
4834
  expect(post.company_tags.first.title).to eq("c")
4671
4835
  end
4672
4836
  end
4837
+
4838
+ context "when the parent fails validation" do
4839
+ let(:school) { EmmSchool.new }
4840
+ let(:student) { school.students.new }
4841
+
4842
+ before do
4843
+ student.save
4844
+ end
4845
+
4846
+ it "does not mark the parent as persisted" do
4847
+ expect(school.persisted?).to be false
4848
+ end
4849
+
4850
+ it "does not mark the child as persisted" do
4851
+ expect(student.persisted?).to be false
4852
+ end
4853
+
4854
+ it "does not persist the parent" do
4855
+ expect(School.count).to eq(0)
4856
+ end
4857
+ end
4858
+
4859
+ context "when doing assign_attributes then assignment" do
4860
+
4861
+ let(:post) do
4862
+ EmmPost.create!(
4863
+ company_tags: [ EmmCompanyTag.new(title: "1"), EmmCompanyTag.new(title: "1") ],
4864
+ user_tags: [ EmmUserTag.new(title: "1"), EmmUserTag.new(title: "1") ]
4865
+ )
4866
+ end
4867
+
4868
+ let(:from_db) { EmmPost.find(post.id) }
4869
+
4870
+ before do
4871
+ post.assign_attributes(
4872
+ company_tags: [ EmmCompanyTag.new(title: '3'), EmmCompanyTag.new(title: '4') ]
4873
+ )
4874
+ post.user_tags = [ EmmUserTag.new(title: '3'), EmmUserTag.new(title: '4') ]
4875
+ post.save!
4876
+ end
4877
+
4878
+ it "persists the associations correctly" do
4879
+ expect(from_db.user_tags.size).to eq(2)
4880
+ expect(from_db.company_tags.size).to eq(2)
4881
+ end
4882
+ end
4883
+
4884
+ context "when assigning hashes" do
4885
+ let(:user) { EmmUser.create! }
4886
+
4887
+ before do
4888
+ user.orders = [ { sku: 1 }, { sku: 2 } ]
4889
+ end
4890
+
4891
+ it "creates the objects correctly" do
4892
+ expect(user.orders.first).to be_a(EmmOrder)
4893
+ expect(user.orders.last).to be_a(EmmOrder)
4894
+
4895
+ expect(user.orders.map(&:sku).sort).to eq([ 1, 2 ])
4896
+ end
4897
+ end
4673
4898
  end
@@ -100,6 +100,7 @@ end
100
100
  class EmmOrder
101
101
  include Mongoid::Document
102
102
 
103
+ field :sku
103
104
  field :amount, type: Integer
104
105
 
105
106
  embedded_in :user, class_name: 'EmmUser'
@@ -188,3 +189,39 @@ class EmmUserTag
188
189
  embedded_in :post, class_name: "EmmPost"
189
190
  end
190
191
 
192
+ class EmmSchool
193
+ include Mongoid::Document
194
+
195
+ embeds_many :students, class_name: "EmmStudent"
196
+
197
+ field :name, type: :string
198
+
199
+ validates :name, presence: true
200
+ end
201
+
202
+ class EmmStudent
203
+ include Mongoid::Document
204
+
205
+ embedded_in :school, class_name: "EmmSchool"
206
+ end
207
+
208
+ class EmmParent
209
+ include Mongoid::Document
210
+ embeds_many :blocks, class_name: "EmmBlock"
211
+ end
212
+
213
+ class EmmBlock
214
+ include Mongoid::Document
215
+ field :name, type: String
216
+ embeds_many :children, class_name: "EmmChild"
217
+ end
218
+
219
+ class EmmChild
220
+ include Mongoid::Document
221
+ embedded_in :block, class_name: "EmmBlock"
222
+
223
+ field :size, type: Integer
224
+ field :order, type: Integer
225
+ field :t
226
+ end
227
+
@@ -27,6 +27,10 @@ describe Mongoid::Association::Embedded::EmbedsMany do
27
27
  expect(legislator.attributes.keys).to eq(['_id', 'a'])
28
28
  end
29
29
 
30
+ it 'allows accessing the parent' do
31
+ expect { legislator.congress }.not_to raise_error
32
+ end
33
+
30
34
  context 'when using only with $' do
31
35
  before do
32
36
  Patient.destroy_all
@@ -47,5 +51,17 @@ describe Mongoid::Association::Embedded::EmbedsMany do
47
51
  expect(patient.addresses.first.number).to eq(123)
48
52
  end
49
53
  end
54
+
55
+ context "when excluding the relation" do
56
+ let(:congress) do
57
+ EmmCongress.where(name: 'foo').only(:_id).first
58
+ end
59
+
60
+ it 'raises a MissingAttributeError' do
61
+ expect do
62
+ congress.legislators
63
+ end.to raise_error(ActiveModel::MissingAttributeError)
64
+ end
65
+ end
50
66
  end
51
67
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative 'embeds_many_models'
4
5
 
5
6
  describe Mongoid::Association::Embedded::EmbedsMany do
6
7
 
@@ -861,4 +862,71 @@ describe Mongoid::Association::Embedded::EmbedsMany do
861
862
  expect(association.path(double( :_parent => true))).to be_a(Mongoid::Atomic::Paths::Embedded::Many)
862
863
  end
863
864
  end
865
+
866
+ context "when the document and embedded document's klass is in a submodule" do
867
+
868
+ let(:tank) { EmmSpec::Tank.create! }
869
+ let(:gun) { tank.guns.create! }
870
+
871
+ let(:inverse_assoc) { gun._association.inverse_association }
872
+
873
+ it "has the correct inverses" do
874
+ pending 'MONGOID-5080'
875
+
876
+ inverse_assoc.should be_a(Mongoid::Association::Embedded::EmbeddedIn)
877
+ inverse_assoc.name.should == :tank
878
+ end
879
+
880
+ context "when embedded association is not namespaced but has class_name" do
881
+
882
+ let(:turret) { tank.emm_turrets.create! }
883
+
884
+ let(:inverse_assoc) { turret._association.inverse_association }
885
+
886
+ it "has the correct inverses" do
887
+ inverse_assoc.should be_a(Mongoid::Association::Embedded::EmbeddedIn)
888
+ inverse_assoc.name.should == :tank
889
+ end
890
+ end
891
+
892
+ context "when embedded association is not namespaced and lacks class_name" do
893
+
894
+ let(:hatch) { tank.emm_hatches.create! }
895
+
896
+ let(:inverse_assoc) { hatch._association.inverse_association }
897
+
898
+ it "does not find the inverse" do
899
+ inverse_assoc.should be nil
900
+ end
901
+ end
902
+
903
+ context "when the class names exist on top level and namespaced" do
904
+
905
+ let(:car) { EmmSpec::Car.create! }
906
+ let(:door) { car.doors.create! }
907
+
908
+ let(:inverse_assoc) { door._association.inverse_association }
909
+
910
+ it "has the correct inverses" do
911
+ pending 'MONGOID-5080'
912
+
913
+ inverse_assoc.should be_a(Mongoid::Association::Embedded::EmbeddedIn)
914
+ inverse_assoc.name.should == :car
915
+ end
916
+ end
917
+
918
+ context "when the association has an unqualified class_name in same module" do
919
+
920
+ let(:launcher) { tank.launchers.create! }
921
+
922
+ let(:inverse_assoc) { launcher._association.inverse_association }
923
+
924
+ it "has the correct inverses" do
925
+ pending 'unqualified class_name arguments do not work per MONGOID-5080'
926
+
927
+ inverse_assoc.should be_a(Mongoid::Association::Embedded::EmbeddedIn)
928
+ inverse_assoc.name.should == :tank
929
+ end
930
+ end
931
+ end
864
932
  end
@@ -78,4 +78,29 @@ describe Mongoid::Association::Embedded::EmbedsOne::Buildable do
78
78
  end
79
79
  end
80
80
  end
81
+
82
+ context 'when the object is already associated with another object' do
83
+
84
+ let(:owner1) do
85
+ Owner.create!
86
+ end
87
+
88
+ let(:owner2) do
89
+ Owner.create!
90
+ end
91
+
92
+ let(:scribe) do
93
+ Scribe.new
94
+ end
95
+
96
+ before do
97
+ owner1.scribe = scribe
98
+ owner2.scribe = scribe
99
+ end
100
+
101
+ it 'clears the object of its previous association' do
102
+ expect(owner1.scribe).to be_nil
103
+ expect(owner2.scribe).to eq(scribe)
104
+ end
105
+ end
81
106
  end