mongoid 7.5.1 → 8.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (429) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +3 -3
  4. data/README.md +6 -6
  5. data/Rakefile +25 -0
  6. data/lib/config/locales/en.yml +92 -43
  7. data/lib/mongoid/association/accessors.rb +40 -11
  8. data/lib/mongoid/association/bindable.rb +50 -2
  9. data/lib/mongoid/association/builders.rb +5 -3
  10. data/lib/mongoid/association/constrainable.rb +0 -1
  11. data/lib/mongoid/association/eager_loadable.rb +29 -7
  12. data/lib/mongoid/association/embedded/batchable.rb +54 -14
  13. data/lib/mongoid/association/embedded/cyclic.rb +1 -1
  14. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  15. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  16. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +4 -3
  17. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  18. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  19. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +4 -3
  20. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +85 -46
  21. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  22. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +19 -5
  23. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +24 -5
  24. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  25. data/lib/mongoid/association/macros.rb +8 -1
  26. data/lib/mongoid/association/many.rb +11 -7
  27. data/lib/mongoid/association/nested/many.rb +5 -4
  28. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  29. data/lib/mongoid/association/nested/one.rb +45 -7
  30. data/lib/mongoid/association/one.rb +2 -2
  31. data/lib/mongoid/association/options.rb +9 -9
  32. data/lib/mongoid/association/proxy.rb +15 -4
  33. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  34. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  35. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  36. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  37. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  38. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  39. data/lib/mongoid/association/referenced/eager.rb +2 -2
  40. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
  41. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  42. data/lib/mongoid/association/referenced/has_many/enumerable.rb +22 -30
  43. data/lib/mongoid/association/referenced/has_many/proxy.rb +40 -21
  44. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  45. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  46. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  47. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  48. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  49. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  50. data/lib/mongoid/association/reflections.rb +4 -4
  51. data/lib/mongoid/association/relatable.rb +44 -10
  52. data/lib/mongoid/association.rb +5 -5
  53. data/lib/mongoid/atomic/modifiers.rb +2 -2
  54. data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
  55. data/lib/mongoid/atomic.rb +7 -0
  56. data/lib/mongoid/attributes/dynamic.rb +4 -4
  57. data/lib/mongoid/attributes/nested.rb +6 -6
  58. data/lib/mongoid/attributes/processing.rb +37 -6
  59. data/lib/mongoid/attributes/projector.rb +2 -2
  60. data/lib/mongoid/attributes/readonly.rb +3 -3
  61. data/lib/mongoid/attributes.rb +51 -42
  62. data/lib/mongoid/cacheable.rb +2 -2
  63. data/lib/mongoid/changeable.rb +147 -14
  64. data/lib/mongoid/clients/options.rb +5 -1
  65. data/lib/mongoid/clients/sessions.rb +2 -14
  66. data/lib/mongoid/clients/storage_options.rb +2 -5
  67. data/lib/mongoid/clients/validators/storage.rb +3 -15
  68. data/lib/mongoid/collection_configurable.rb +58 -0
  69. data/lib/mongoid/composable.rb +2 -0
  70. data/lib/mongoid/config/defaults.rb +60 -0
  71. data/lib/mongoid/config/options.rb +3 -0
  72. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  73. data/lib/mongoid/config/validators/client.rb +6 -6
  74. data/lib/mongoid/config/validators.rb +1 -0
  75. data/lib/mongoid/config.rb +158 -17
  76. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  77. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  78. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  79. data/lib/mongoid/contextual/atomic.rb +1 -1
  80. data/lib/mongoid/contextual/geo_near.rb +7 -7
  81. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  82. data/lib/mongoid/contextual/memory.rb +285 -58
  83. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  84. data/lib/mongoid/contextual/mongo.rb +544 -333
  85. data/lib/mongoid/contextual/none.rb +193 -20
  86. data/lib/mongoid/contextual/queryable.rb +1 -1
  87. data/lib/mongoid/contextual.rb +14 -2
  88. data/lib/mongoid/copyable.rb +32 -8
  89. data/lib/mongoid/criteria/findable.rb +8 -5
  90. data/lib/mongoid/criteria/includable.rb +27 -22
  91. data/lib/mongoid/criteria/marshalable.rb +10 -2
  92. data/lib/mongoid/criteria/permission.rb +1 -1
  93. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  94. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -16
  95. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  96. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  97. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  98. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  99. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -17
  100. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -9
  101. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  102. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  103. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  104. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  105. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
  106. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
  107. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  108. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  109. data/lib/mongoid/criteria/queryable/key.rb +4 -4
  110. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  111. data/lib/mongoid/criteria/queryable/optional.rb +11 -17
  112. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  113. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  114. data/lib/mongoid/criteria/queryable/selectable.rb +47 -38
  115. data/lib/mongoid/criteria/queryable/selector.rb +93 -8
  116. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  117. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  118. data/lib/mongoid/criteria/queryable.rb +12 -7
  119. data/lib/mongoid/criteria/scopable.rb +2 -2
  120. data/lib/mongoid/criteria/translator.rb +45 -0
  121. data/lib/mongoid/criteria.rb +20 -40
  122. data/lib/mongoid/deprecable.rb +37 -0
  123. data/lib/mongoid/deprecation.rb +25 -0
  124. data/lib/mongoid/document.rb +135 -36
  125. data/lib/mongoid/equality.rb +8 -8
  126. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  127. data/lib/mongoid/errors/document_not_found.rb +10 -6
  128. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  129. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  130. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  131. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  132. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  133. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  134. data/lib/mongoid/errors/invalid_field.rb +6 -2
  135. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  136. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  137. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  138. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  139. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  140. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  141. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  142. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  143. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  144. data/lib/mongoid/errors/no_client_database.rb +1 -1
  145. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  146. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  147. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  148. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  149. data/lib/mongoid/errors.rb +6 -3
  150. data/lib/mongoid/extensions/array.rb +9 -7
  151. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  152. data/lib/mongoid/extensions/binary.rb +42 -0
  153. data/lib/mongoid/extensions/boolean.rb +8 -2
  154. data/lib/mongoid/extensions/date.rb +26 -20
  155. data/lib/mongoid/extensions/date_time.rb +1 -1
  156. data/lib/mongoid/extensions/false_class.rb +1 -1
  157. data/lib/mongoid/extensions/float.rb +7 -4
  158. data/lib/mongoid/extensions/hash.rb +37 -8
  159. data/lib/mongoid/extensions/integer.rb +7 -4
  160. data/lib/mongoid/extensions/module.rb +1 -1
  161. data/lib/mongoid/extensions/object.rb +10 -8
  162. data/lib/mongoid/extensions/range.rb +41 -10
  163. data/lib/mongoid/extensions/regexp.rb +11 -4
  164. data/lib/mongoid/extensions/set.rb +11 -4
  165. data/lib/mongoid/extensions/string.rb +11 -22
  166. data/lib/mongoid/extensions/symbol.rb +4 -15
  167. data/lib/mongoid/extensions/time.rb +29 -16
  168. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  169. data/lib/mongoid/extensions/true_class.rb +1 -1
  170. data/lib/mongoid/extensions.rb +1 -0
  171. data/lib/mongoid/factory.rb +55 -7
  172. data/lib/mongoid/fields/foreign_key.rb +11 -4
  173. data/lib/mongoid/fields/localized.rb +19 -4
  174. data/lib/mongoid/fields/standard.rb +17 -7
  175. data/lib/mongoid/fields/validators/macro.rb +3 -9
  176. data/lib/mongoid/fields.rb +129 -20
  177. data/lib/mongoid/findable.rb +54 -24
  178. data/lib/mongoid/indexable/specification.rb +2 -2
  179. data/lib/mongoid/indexable/validators/options.rb +6 -2
  180. data/lib/mongoid/interceptable.rb +186 -16
  181. data/lib/mongoid/matchable.rb +1 -1
  182. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  183. data/lib/mongoid/matcher/type.rb +1 -1
  184. data/lib/mongoid/matcher.rb +33 -13
  185. data/lib/mongoid/persistable/creatable.rb +19 -9
  186. data/lib/mongoid/persistable/deletable.rb +2 -2
  187. data/lib/mongoid/persistable/destroyable.rb +1 -1
  188. data/lib/mongoid/persistable/savable.rb +14 -2
  189. data/lib/mongoid/persistable/unsettable.rb +2 -2
  190. data/lib/mongoid/persistable/updatable.rb +69 -12
  191. data/lib/mongoid/persistable/upsertable.rb +21 -2
  192. data/lib/mongoid/persistable.rb +6 -3
  193. data/lib/mongoid/persistence_context.rb +63 -10
  194. data/lib/mongoid/query_cache.rb +13 -261
  195. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  196. data/lib/mongoid/railties/database.rake +7 -2
  197. data/lib/mongoid/reloadable.rb +10 -8
  198. data/lib/mongoid/scopable.rb +15 -13
  199. data/lib/mongoid/selectable.rb +1 -2
  200. data/lib/mongoid/serializable.rb +10 -6
  201. data/lib/mongoid/shardable.rb +35 -11
  202. data/lib/mongoid/stateful.rb +57 -10
  203. data/lib/mongoid/tasks/database.rake +12 -0
  204. data/lib/mongoid/tasks/database.rb +20 -2
  205. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  206. data/lib/mongoid/threaded.rb +42 -12
  207. data/lib/mongoid/timestamps/created.rb +1 -1
  208. data/lib/mongoid/timestamps/updated.rb +2 -2
  209. data/lib/mongoid/touchable.rb +2 -3
  210. data/lib/mongoid/traversable.rb +5 -4
  211. data/lib/mongoid/utils.rb +22 -0
  212. data/lib/mongoid/validatable/localizable.rb +1 -1
  213. data/lib/mongoid/validatable/macros.rb +5 -7
  214. data/lib/mongoid/validatable/presence.rb +2 -2
  215. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  216. data/lib/mongoid/validatable.rb +9 -6
  217. data/lib/mongoid/version.rb +1 -1
  218. data/lib/mongoid/warnings.rb +19 -4
  219. data/lib/mongoid.rb +17 -3
  220. data/spec/config/mongoid.yml +16 -0
  221. data/spec/integration/app_spec.rb +10 -14
  222. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  223. data/spec/integration/associations/embedded_spec.rb +15 -0
  224. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  225. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  226. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  227. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  228. data/spec/integration/associations/has_one_spec.rb +97 -1
  229. data/spec/integration/associations/scope_option_spec.rb +1 -1
  230. data/spec/integration/callbacks_models.rb +132 -1
  231. data/spec/integration/callbacks_spec.rb +381 -4
  232. data/spec/integration/criteria/range_spec.rb +95 -1
  233. data/spec/integration/discriminator_key_spec.rb +118 -80
  234. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  235. data/spec/integration/i18n_fallbacks_spec.rb +3 -32
  236. data/spec/integration/matcher_examples_spec.rb +20 -13
  237. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  238. data/spec/integration/matcher_operator_spec.rb +3 -5
  239. data/spec/integration/persistence/range_field_spec.rb +350 -0
  240. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  241. data/spec/mongoid/association/depending_spec.rb +9 -9
  242. data/spec/mongoid/association/eager_spec.rb +2 -1
  243. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  244. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  245. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +96 -9
  246. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  247. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +311 -65
  248. data/spec/mongoid/association/embedded/embeds_many_models.rb +158 -0
  249. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  250. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  251. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  252. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  253. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  254. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  255. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  256. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  257. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  258. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  259. data/spec/mongoid/association/referenced/belongs_to_spec.rb +4 -20
  260. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +215 -228
  261. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  262. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  263. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  264. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  265. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +235 -177
  266. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  267. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  268. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  269. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  270. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  271. data/spec/mongoid/association/syncable_spec.rb +15 -1
  272. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  273. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  274. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  275. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  276. data/spec/mongoid/attributes_spec.rb +554 -33
  277. data/spec/mongoid/cacheable_spec.rb +3 -3
  278. data/spec/mongoid/changeable_spec.rb +429 -37
  279. data/spec/mongoid/clients/factory_spec.rb +23 -30
  280. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  281. data/spec/mongoid/clients_spec.rb +179 -15
  282. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  283. data/spec/mongoid/config/defaults_spec.rb +160 -0
  284. data/spec/mongoid/config_spec.rb +220 -30
  285. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  286. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  287. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  288. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  289. data/spec/mongoid/contextual/memory_spec.rb +850 -88
  290. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  291. data/spec/mongoid/contextual/mongo_spec.rb +2307 -1105
  292. data/spec/mongoid/contextual/none_spec.rb +60 -21
  293. data/spec/mongoid/copyable_spec.rb +453 -11
  294. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  295. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  296. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  297. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  298. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  299. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  300. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  301. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  302. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  303. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  304. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  305. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  306. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  307. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  308. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
  309. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  310. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +469 -0
  311. data/spec/mongoid/criteria/queryable/selectable_spec.rb +78 -86
  312. data/spec/mongoid/criteria/queryable/selector_spec.rb +90 -5
  313. data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
  314. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  315. data/spec/mongoid/criteria_projection_spec.rb +1 -5
  316. data/spec/mongoid/criteria_spec.rb +469 -1205
  317. data/spec/mongoid/document_fields_spec.rb +173 -24
  318. data/spec/mongoid/document_spec.rb +32 -41
  319. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  320. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  321. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  322. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  323. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  324. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  325. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  326. data/spec/mongoid/extensions/array_spec.rb +16 -2
  327. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  328. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  329. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  330. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  331. data/spec/mongoid/extensions/date_spec.rb +71 -1
  332. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  333. data/spec/mongoid/extensions/float_spec.rb +53 -74
  334. data/spec/mongoid/extensions/hash_spec.rb +33 -3
  335. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  336. data/spec/mongoid/extensions/range_spec.rb +255 -54
  337. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  338. data/spec/mongoid/extensions/set_spec.rb +106 -0
  339. data/spec/mongoid/extensions/string_spec.rb +53 -25
  340. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  341. data/spec/mongoid/extensions/time_spec.rb +639 -106
  342. data/spec/mongoid/extensions/time_with_zone_spec.rb +24 -83
  343. data/spec/mongoid/factory_spec.rb +61 -1
  344. data/spec/mongoid/fields/localized_spec.rb +80 -37
  345. data/spec/mongoid/fields_spec.rb +500 -84
  346. data/spec/mongoid/findable_spec.rb +450 -58
  347. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  348. data/spec/mongoid/indexable_spec.rb +55 -30
  349. data/spec/mongoid/interceptable_spec.rb +824 -22
  350. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  351. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  352. data/spec/mongoid/mongoizable_spec.rb +285 -0
  353. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  354. data/spec/mongoid/persistable/deletable_spec.rb +28 -8
  355. data/spec/mongoid/persistable/destroyable_spec.rb +28 -8
  356. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  357. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  358. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  359. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  360. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  361. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  362. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  363. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  364. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  365. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  366. data/spec/mongoid/persistable/upsertable_spec.rb +89 -1
  367. data/spec/mongoid/persistence_context_spec.rb +57 -58
  368. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  369. data/spec/mongoid/query_cache_spec.rb +56 -215
  370. data/spec/mongoid/reloadable_spec.rb +83 -6
  371. data/spec/mongoid/scopable_spec.rb +91 -1
  372. data/spec/mongoid/serializable_spec.rb +9 -30
  373. data/spec/mongoid/shardable_models.rb +14 -0
  374. data/spec/mongoid/shardable_spec.rb +157 -51
  375. data/spec/mongoid/stateful_spec.rb +150 -8
  376. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  377. data/spec/mongoid/tasks/database_spec.rb +127 -0
  378. data/spec/mongoid/timestamps_spec.rb +392 -4
  379. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  380. data/spec/mongoid/touchable_spec.rb +390 -2
  381. data/spec/mongoid/touchable_spec_models.rb +14 -8
  382. data/spec/mongoid/traversable_spec.rb +13 -35
  383. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  384. data/spec/mongoid/validatable/uniqueness_spec.rb +58 -31
  385. data/spec/mongoid/warnings_spec.rb +35 -0
  386. data/spec/mongoid_spec.rb +34 -10
  387. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  388. data/spec/rails/mongoid_spec.rb +4 -16
  389. data/spec/shared/lib/mrss/docker_runner.rb +8 -0
  390. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  391. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  392. data/spec/shared/lib/mrss/utils.rb +28 -6
  393. data/spec/shared/share/Dockerfile.erb +36 -40
  394. data/spec/shared/shlib/server.sh +32 -8
  395. data/spec/shared/shlib/set_env.sh +4 -4
  396. data/spec/spec_helper.rb +5 -0
  397. data/spec/support/constraints.rb +24 -0
  398. data/spec/support/immutable_ids.rb +118 -0
  399. data/spec/support/macros.rb +78 -0
  400. data/spec/support/models/artist.rb +0 -1
  401. data/spec/support/models/augmentation.rb +12 -0
  402. data/spec/support/models/band.rb +4 -0
  403. data/spec/support/models/book.rb +1 -0
  404. data/spec/support/models/building.rb +2 -0
  405. data/spec/support/models/catalog.rb +24 -0
  406. data/spec/support/models/circus.rb +3 -0
  407. data/spec/support/models/cover.rb +10 -0
  408. data/spec/support/models/fanatic.rb +8 -0
  409. data/spec/support/models/implant.rb +9 -0
  410. data/spec/support/models/label.rb +2 -0
  411. data/spec/support/models/passport.rb +9 -0
  412. data/spec/support/models/person.rb +2 -0
  413. data/spec/support/models/player.rb +2 -0
  414. data/spec/support/models/powerup.rb +12 -0
  415. data/spec/support/models/product.rb +1 -0
  416. data/spec/support/models/purse.rb +9 -0
  417. data/spec/support/models/registry.rb +1 -0
  418. data/spec/support/models/school.rb +14 -0
  419. data/spec/support/models/shield.rb +18 -0
  420. data/spec/support/models/student.rb +14 -0
  421. data/spec/support/models/weapon.rb +12 -0
  422. data.tar.gz.sig +0 -0
  423. metadata +722 -640
  424. metadata.gz.sig +0 -0
  425. data/lib/mongoid/errors/eager_load.rb +0 -23
  426. data/lib/mongoid/errors/invalid_value.rb +0 -17
  427. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  428. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  429. 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 '../embeds_many_models.rb'
4
5
 
5
6
  describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
6
7
 
@@ -1861,51 +1862,56 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
1861
1862
  end
1862
1863
  end
1863
1864
 
1864
- 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") }
1865
1869
 
1866
- let(:person) do
1867
- Person.new
1868
- end
1869
-
1870
- let(:address_one) do
1871
- Address.new(street: "first")
1872
- end
1870
+ before do
1871
+ person.addresses << [ address_one, address_two ]
1872
+ end
1873
1873
 
1874
- let(:address_two) do
1875
- Address.new(street: "second")
1876
- 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
1877
1879
 
1878
- before do
1879
- person.addresses << [ address_one, address_two ]
1880
- 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
1881
1884
 
1882
- 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
1883
1888
 
1884
- let!(:deleted) do
1885
- person.addresses.delete(address_one)
1886
- end
1889
+ it 'reindexes the relation' do
1890
+ expect(address_two._index).to eq(0)
1891
+ end
1887
1892
 
1888
- it "deletes the document" do
1889
- expect(person.addresses).to eq([ address_two ])
1890
- end
1893
+ it 'returns the document' do
1894
+ expect(deleted).to eq(address_one)
1895
+ end
1896
+ end
1891
1897
 
1892
- it "deletes the document from the unscoped" do
1893
- 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
1894
1903
  end
1895
1904
 
1896
- it "reindexes the relation" do
1897
- expect(address_two._index).to eq(0)
1898
- end
1905
+ context 'when the root document is unpersisted' do
1906
+ let(:person) { Person.new }
1899
1907
 
1900
- it "returns the document" do
1901
- expect(deleted).to eq(address_one)
1908
+ it_behaves_like 'deleting from the collection'
1902
1909
  end
1903
- end
1904
1910
 
1905
- context "when the document does not exist" do
1911
+ context 'when the root document is persisted' do
1912
+ let(:person) { Person.create }
1906
1913
 
1907
- it "returns nil" do
1908
- expect(person.addresses.delete(Address.new)).to be_nil
1914
+ it_behaves_like 'deleting from the collection'
1909
1915
  end
1910
1916
  end
1911
1917
  end
@@ -2209,6 +2215,79 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2209
2215
  end
2210
2216
  end
2211
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
2212
2291
  end
2213
2292
  end
2214
2293
 
@@ -2231,9 +2310,37 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2231
2310
  person.addresses.create!(street: "Bond St")
2232
2311
  end
2233
2312
 
2313
+ let(:address) { person.addresses.first }
2314
+
2234
2315
  it "returns true" do
2235
2316
  expect(person.addresses.exists?).to be true
2236
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
2237
2344
  end
2238
2345
 
2239
2346
  context "when no documents exist in the database" do
@@ -2245,6 +2352,13 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2245
2352
  it "returns false" do
2246
2353
  expect(person.addresses.exists?).to be false
2247
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
2248
2362
  end
2249
2363
  end
2250
2364
 
@@ -2278,32 +2392,22 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2278
2392
  context "when the id does not match" do
2279
2393
 
2280
2394
  context "when config set to raise error" do
2281
-
2282
- before do
2283
- Mongoid.raise_not_found_error = true
2284
- end
2395
+ config_override :raise_not_found_error, true
2285
2396
 
2286
2397
  it "raises an error" do
2287
2398
  expect {
2288
2399
  person.addresses.find(BSON::ObjectId.new)
2289
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2400
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Address with id\(s\)/)
2290
2401
  end
2291
2402
  end
2292
2403
 
2293
2404
  context "when config set not to raise error" do
2405
+ config_override :raise_not_found_error, false
2294
2406
 
2295
2407
  let(:address) do
2296
2408
  person.addresses.find(BSON::ObjectId.new)
2297
2409
  end
2298
2410
 
2299
- before do
2300
- Mongoid.raise_not_found_error = false
2301
- end
2302
-
2303
- after do
2304
- Mongoid.raise_not_found_error = true
2305
- end
2306
-
2307
2411
  it "returns nil" do
2308
2412
  expect(address).to be_nil
2309
2413
  end
@@ -2327,32 +2431,22 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
2327
2431
  context "when the ids do not match" do
2328
2432
 
2329
2433
  context "when config set to raise error" do
2330
-
2331
- before do
2332
- Mongoid.raise_not_found_error = true
2333
- end
2434
+ config_override :raise_not_found_error, true
2334
2435
 
2335
2436
  it "raises an error" do
2336
2437
  expect {
2337
2438
  person.addresses.find([ BSON::ObjectId.new ])
2338
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2439
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Address with id\(s\)/)
2339
2440
  end
2340
2441
  end
2341
2442
 
2342
2443
  context "when config set not to raise error" do
2444
+ config_override :raise_not_found_error, false
2343
2445
 
2344
2446
  let(:addresses) do
2345
2447
  person.addresses.find([ BSON::ObjectId.new ])
2346
2448
  end
2347
2449
 
2348
- before do
2349
- Mongoid.raise_not_found_error = false
2350
- end
2351
-
2352
- after do
2353
- Mongoid.raise_not_found_error = true
2354
- end
2355
-
2356
2450
  it "returns an empty array" do
2357
2451
  expect(addresses).to be_empty
2358
2452
  end
@@ -3460,7 +3554,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3460
3554
 
3461
3555
  describe "replacing the entire embedded list" do
3462
3556
 
3463
- 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
3464
3558
 
3465
3559
  let(:person) do
3466
3560
  Person.create!
@@ -3481,7 +3575,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3481
3575
  end
3482
3576
  end
3483
3577
 
3484
- 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
3485
3579
 
3486
3580
  let(:person) do
3487
3581
  Person.create!
@@ -3502,7 +3596,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3502
3596
  end
3503
3597
  end
3504
3598
 
3505
- 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
3506
3600
 
3507
3601
  let(:person) do
3508
3602
  Person.create!
@@ -3526,7 +3620,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3526
3620
 
3527
3621
  describe "appending to the embedded list" do
3528
3622
 
3529
- 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
3530
3624
 
3531
3625
  let(:person) do
3532
3626
  Person.create! phone_numbers: []
@@ -3545,7 +3639,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3545
3639
  end
3546
3640
  end
3547
3641
 
3548
- 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
3549
3643
 
3550
3644
  let(:person) do
3551
3645
  Person.create! phone_numbers: []
@@ -3564,7 +3658,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3564
3658
  end
3565
3659
  end
3566
3660
 
3567
- 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
3568
3662
 
3569
3663
  let(:person) do
3570
3664
  Person.create! phone_numbers: []
@@ -3959,6 +4053,28 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
3959
4053
  end
3960
4054
  end
3961
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
+
3962
4078
  context "when adding a document" do
3963
4079
 
3964
4080
  let(:person) do
@@ -4490,7 +4606,7 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
4490
4606
  before do
4491
4607
  band.collection.
4492
4608
  find(_id: band.id).
4493
- update_one("$set" => { records: [{ name: "Moderat" }]})
4609
+ update_one("$set" => { records: [{ _id: BSON::ObjectId.new, name: "Moderat" }]})
4494
4610
  end
4495
4611
 
4496
4612
  context "when loading the documents" do
@@ -4649,4 +4765,134 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
4649
4765
  end
4650
4766
  end
4651
4767
  end
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
+
4818
+ context "when using assign_attributes with an already populated array" do
4819
+ let(:post) { EmmPost.create! }
4820
+
4821
+ before do
4822
+ post.assign_attributes(company_tags: [{id: BSON::ObjectId.new, title: 'a'}],
4823
+ user_tags: [{id: BSON::ObjectId.new, title: 'b'}])
4824
+ post.save!
4825
+ post.reload
4826
+ post.assign_attributes(company_tags: [{id: BSON::ObjectId.new, title: 'c'}],
4827
+ user_tags: [])
4828
+ post.save!
4829
+ post.reload
4830
+ end
4831
+
4832
+ it "has the correct embedded documents" do
4833
+ expect(post.company_tags.length).to eq(1)
4834
+ expect(post.company_tags.first.title).to eq("c")
4835
+ end
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
4652
4898
  end
@@ -67,3 +67,161 @@ class EmmOuter
67
67
 
68
68
  field :level, :type => Integer
69
69
  end
70
+
71
+ class EmmCustomerAddress
72
+ include Mongoid::Document
73
+
74
+ embedded_in :addressable, polymorphic: true, inverse_of: :work_address
75
+ end
76
+
77
+ class EmmFriend
78
+ include Mongoid::Document
79
+
80
+ embedded_in :befriendable, polymorphic: true
81
+ end
82
+
83
+ class EmmCustomer
84
+ include Mongoid::Document
85
+
86
+ embeds_one :home_address, class_name: 'EmmCustomerAddress', as: :addressable
87
+ embeds_one :work_address, class_name: 'EmmCustomerAddress', as: :addressable
88
+
89
+ embeds_many :close_friends, class_name: 'EmmFriend', as: :befriendable
90
+ embeds_many :acquaintances, class_name: 'EmmFriend', as: :befriendable
91
+ end
92
+
93
+ class EmmUser
94
+ include Mongoid::Document
95
+ include Mongoid::Timestamps
96
+
97
+ embeds_many :orders, class_name: 'EmmOrder'
98
+ end
99
+
100
+ class EmmOrder
101
+ include Mongoid::Document
102
+
103
+ field :sku
104
+ field :amount, type: Integer
105
+
106
+ embedded_in :user, class_name: 'EmmUser'
107
+ end
108
+
109
+ module EmmSpec
110
+ # There is also a top-level Car class defined.
111
+ class Car
112
+ include Mongoid::Document
113
+
114
+ embeds_many :doors
115
+ end
116
+
117
+ class Door
118
+ include Mongoid::Document
119
+
120
+ embedded_in :car
121
+ end
122
+
123
+ class Tank
124
+ include Mongoid::Document
125
+
126
+ embeds_many :guns
127
+ embeds_many :emm_turrets
128
+ # This association references a model that is not in our module,
129
+ # and it does not define class_name hence Mongoid will not be able to
130
+ # figure out the inverse for this association.
131
+ embeds_many :emm_hatches
132
+
133
+ # class_name is intentionally unqualified, references a class in the
134
+ # same module. Rails permits class_name to be unqualified like this.
135
+ embeds_many :launchers, class_name: 'Launcher'
136
+ end
137
+
138
+ class Gun
139
+ include Mongoid::Document
140
+
141
+ embedded_in :tank
142
+ end
143
+
144
+ class Launcher
145
+ include Mongoid::Document
146
+
147
+ # class_name is intentionally unqualified.
148
+ embedded_in :tank, class_name: 'Tank'
149
+ end
150
+ end
151
+
152
+ # This is intentionally on top level.
153
+ class EmmTurret
154
+ include Mongoid::Document
155
+
156
+ embedded_in :tank, class_name: 'EmmSpec::Tank'
157
+ end
158
+
159
+ # This is intentionally on top level.
160
+ class EmmHatch
161
+ include Mongoid::Document
162
+
163
+ # No :class_name option on this association intentionally.
164
+ embedded_in :tank
165
+ end
166
+
167
+ class EmmPost
168
+ include Mongoid::Document
169
+
170
+ embeds_many :company_tags, class_name: "EmmCompanyTag"
171
+ embeds_many :user_tags, class_name: "EmmUserTag"
172
+ end
173
+
174
+
175
+ class EmmCompanyTag
176
+ include Mongoid::Document
177
+
178
+ field :title, type: String
179
+
180
+ embedded_in :post, class_name: "EmmPost"
181
+ end
182
+
183
+
184
+ class EmmUserTag
185
+ include Mongoid::Document
186
+
187
+ field :title, type: String
188
+
189
+ embedded_in :post, class_name: "EmmPost"
190
+ end
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
+
@@ -47,5 +47,17 @@ describe Mongoid::Association::Embedded::EmbedsMany do
47
47
  expect(patient.addresses.first.number).to eq(123)
48
48
  end
49
49
  end
50
+
51
+ context "when excluding the relation" do
52
+ let(:congress) do
53
+ EmmCongress.where(name: 'foo').only(:_id).first
54
+ end
55
+
56
+ it 'raises a MissingAttributeError' do
57
+ expect do
58
+ congress.legislators
59
+ end.to raise_error(ActiveModel::MissingAttributeError)
60
+ end
61
+ end
50
62
  end
51
63
  end