mongoid 6.4.8 → 7.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1372) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +30 -30
  4. data/LICENSE +1 -0
  5. data/README.md +34 -20
  6. data/Rakefile +75 -6
  7. data/lib/config/locales/en.yml +149 -66
  8. data/lib/mongoid/association/accessors.rb +402 -0
  9. data/lib/mongoid/association/bindable.rb +179 -0
  10. data/lib/mongoid/association/builders.rb +84 -0
  11. data/lib/mongoid/association/constrainable.rb +43 -0
  12. data/lib/mongoid/association/depending.rb +128 -0
  13. data/lib/mongoid/association/eager_loadable.rb +35 -0
  14. data/lib/mongoid/association/embedded/batchable.rb +375 -0
  15. data/lib/mongoid/association/embedded/cyclic.rb +102 -0
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +52 -0
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +38 -0
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +111 -0
  19. data/lib/mongoid/association/embedded/embedded_in.rb +134 -0
  20. data/lib/mongoid/association/embedded/embeds_many/binding.rb +41 -0
  21. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +45 -0
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +549 -0
  23. data/lib/mongoid/association/embedded/embeds_many.rb +183 -0
  24. data/lib/mongoid/association/embedded/embeds_one/binding.rb +43 -0
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +39 -0
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +145 -0
  27. data/lib/mongoid/association/embedded/embeds_one.rb +150 -0
  28. data/lib/mongoid/association/embedded.rb +6 -0
  29. data/lib/mongoid/association/macros.rb +227 -0
  30. data/lib/mongoid/association/many.rb +198 -0
  31. data/lib/mongoid/association/marshalable.rb +31 -0
  32. data/lib/mongoid/association/nested/many.rb +191 -0
  33. data/lib/mongoid/association/nested/nested_buildable.rb +66 -0
  34. data/lib/mongoid/association/nested/one.rb +116 -0
  35. data/lib/mongoid/association/nested.rb +15 -0
  36. data/lib/mongoid/association/one.rb +53 -0
  37. data/lib/mongoid/association/options.rb +122 -0
  38. data/lib/mongoid/association/proxy.rb +189 -0
  39. data/lib/mongoid/association/referenced/auto_save.rb +73 -0
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +82 -0
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +48 -0
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +73 -0
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +125 -0
  44. data/lib/mongoid/association/referenced/belongs_to.rb +226 -0
  45. data/lib/mongoid/association/referenced/counter_cache.rb +152 -0
  46. data/lib/mongoid/association/referenced/eager.rb +163 -0
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +72 -0
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +53 -0
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +292 -0
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +270 -0
  52. data/lib/mongoid/association/referenced/has_many/binding.rb +36 -0
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +44 -0
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +502 -0
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +545 -0
  57. data/lib/mongoid/association/referenced/has_many.rb +251 -0
  58. data/lib/mongoid/association/referenced/has_one/binding.rb +42 -0
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +74 -0
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +36 -0
  61. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +113 -0
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +111 -0
  63. data/lib/mongoid/association/referenced/has_one.rb +184 -0
  64. data/lib/mongoid/association/referenced/syncable.rb +155 -0
  65. data/lib/mongoid/association/referenced.rb +9 -0
  66. data/lib/mongoid/association/reflections.rb +69 -0
  67. data/lib/mongoid/association/relatable.rb +455 -0
  68. data/lib/mongoid/association.rb +135 -0
  69. data/lib/mongoid/atomic/modifiers.rb +27 -51
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +24 -8
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -8
  72. data/lib/mongoid/atomic/paths/embedded.rb +3 -4
  73. data/lib/mongoid/atomic/paths/root.rb +4 -7
  74. data/lib/mongoid/atomic/paths.rb +2 -1
  75. data/lib/mongoid/atomic.rb +43 -48
  76. data/lib/mongoid/attributes/dynamic.rb +19 -33
  77. data/lib/mongoid/attributes/nested.rb +29 -21
  78. data/lib/mongoid/attributes/processing.rb +11 -26
  79. data/lib/mongoid/attributes/projector.rb +119 -0
  80. data/lib/mongoid/attributes/readonly.rb +5 -10
  81. data/lib/mongoid/attributes.rb +94 -91
  82. data/lib/mongoid/cacheable.rb +7 -10
  83. data/lib/mongoid/changeable.rb +7 -61
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +17 -18
  86. data/lib/mongoid/clients/sessions.rb +22 -10
  87. data/lib/mongoid/clients/storage_options.rb +7 -12
  88. data/lib/mongoid/clients/validators/storage.rb +2 -9
  89. data/lib/mongoid/clients/validators.rb +2 -1
  90. data/lib/mongoid/clients.rb +3 -10
  91. data/lib/mongoid/composable.rb +9 -13
  92. data/lib/mongoid/config/environment.rb +51 -13
  93. data/lib/mongoid/config/options.rb +20 -23
  94. data/lib/mongoid/config/validators/client.rb +2 -17
  95. data/lib/mongoid/config/validators/option.rb +2 -3
  96. data/lib/mongoid/config/validators.rb +2 -1
  97. data/lib/mongoid/config.rb +123 -40
  98. data/lib/mongoid/contextual/aggregable/memory.rb +17 -12
  99. data/lib/mongoid/contextual/aggregable/mongo.rb +25 -26
  100. data/lib/mongoid/contextual/aggregable/none.rb +65 -0
  101. data/lib/mongoid/contextual/aggregable.rb +17 -0
  102. data/lib/mongoid/contextual/atomic.rb +29 -31
  103. data/lib/mongoid/contextual/command.rb +2 -5
  104. data/lib/mongoid/contextual/geo_near.rb +7 -38
  105. data/lib/mongoid/contextual/map_reduce.rb +5 -33
  106. data/lib/mongoid/contextual/memory.rb +167 -70
  107. data/lib/mongoid/contextual/mongo.rb +295 -106
  108. data/lib/mongoid/contextual/none.rb +88 -28
  109. data/lib/mongoid/contextual/queryable.rb +2 -3
  110. data/lib/mongoid/contextual.rb +7 -9
  111. data/lib/mongoid/copyable.rb +20 -14
  112. data/lib/mongoid/criteria/findable.rb +12 -15
  113. data/lib/mongoid/criteria/includable.rb +21 -28
  114. data/lib/mongoid/criteria/inspectable.rb +2 -3
  115. data/lib/mongoid/criteria/marshalable.rb +2 -5
  116. data/lib/mongoid/criteria/modifiable.rb +10 -22
  117. data/lib/mongoid/criteria/options.rb +4 -5
  118. data/lib/mongoid/criteria/permission.rb +2 -1
  119. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -13
  120. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  121. data/lib/mongoid/criteria/queryable/extensions/array.rb +5 -26
  122. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +3 -4
  123. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +3 -4
  124. data/lib/mongoid/criteria/queryable/extensions/date.rb +3 -8
  125. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +5 -11
  126. data/lib/mongoid/criteria/queryable/extensions/hash.rb +4 -25
  127. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -14
  128. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -13
  129. data/lib/mongoid/criteria/queryable/extensions/object.rb +4 -29
  130. data/lib/mongoid/criteria/queryable/extensions/range.rb +41 -17
  131. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +9 -16
  132. data/lib/mongoid/criteria/queryable/extensions/set.rb +3 -4
  133. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -19
  134. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -10
  135. data/lib/mongoid/criteria/queryable/extensions/time.rb +4 -9
  136. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +13 -6
  137. data/lib/mongoid/criteria/queryable/extensions.rb +1 -4
  138. data/lib/mongoid/criteria/queryable/key.rb +101 -27
  139. data/lib/mongoid/criteria/queryable/macroable.rb +3 -4
  140. data/lib/mongoid/criteria/queryable/mergeable.rb +205 -44
  141. data/lib/mongoid/criteria/queryable/optional.rb +5 -48
  142. data/lib/mongoid/criteria/queryable/options.rb +2 -19
  143. data/lib/mongoid/criteria/queryable/pipeline.rb +14 -19
  144. data/lib/mongoid/criteria/queryable/selectable.rb +436 -166
  145. data/lib/mongoid/criteria/queryable/selector.rb +45 -55
  146. data/lib/mongoid/criteria/queryable/smash.rb +2 -11
  147. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  148. data/lib/mongoid/criteria/queryable.rb +7 -9
  149. data/lib/mongoid/criteria/scopable.rb +27 -19
  150. data/lib/mongoid/criteria.rb +90 -75
  151. data/lib/mongoid/document.rb +43 -74
  152. data/lib/mongoid/equality.rb +29 -12
  153. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -5
  154. data/lib/mongoid/errors/callback.rb +2 -3
  155. data/lib/mongoid/errors/criteria_argument_required.rb +18 -0
  156. data/lib/mongoid/errors/delete_restriction.rb +10 -13
  157. data/lib/mongoid/errors/document_not_destroyed.rb +4 -7
  158. data/lib/mongoid/errors/document_not_found.rb +25 -15
  159. data/lib/mongoid/errors/eager_load.rb +6 -5
  160. data/lib/mongoid/errors/empty_config_file.rb +25 -0
  161. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -3
  162. data/lib/mongoid/errors/invalid_collection.rb +2 -1
  163. data/lib/mongoid/errors/invalid_config_file.rb +25 -0
  164. data/lib/mongoid/errors/invalid_config_option.rb +2 -3
  165. data/lib/mongoid/errors/invalid_dependent_strategy.rb +31 -0
  166. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
  167. data/lib/mongoid/errors/invalid_elem_match_operator.rb +32 -0
  168. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +25 -0
  169. data/lib/mongoid/errors/invalid_expression_operator.rb +27 -0
  170. data/lib/mongoid/errors/invalid_field.rb +2 -5
  171. data/lib/mongoid/errors/invalid_field_operator.rb +32 -0
  172. data/lib/mongoid/errors/invalid_field_option.rb +2 -3
  173. data/lib/mongoid/errors/invalid_find.rb +2 -3
  174. data/lib/mongoid/errors/invalid_includes.rb +2 -3
  175. data/lib/mongoid/errors/invalid_index.rb +2 -3
  176. data/lib/mongoid/errors/invalid_options.rb +4 -5
  177. data/lib/mongoid/errors/invalid_path.rb +2 -3
  178. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -5
  179. data/lib/mongoid/errors/invalid_query.rb +40 -0
  180. data/lib/mongoid/errors/invalid_relation.rb +4 -9
  181. data/lib/mongoid/errors/invalid_relation_option.rb +28 -0
  182. data/lib/mongoid/errors/invalid_scope.rb +2 -3
  183. data/lib/mongoid/errors/invalid_session_use.rb +3 -6
  184. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -5
  185. data/lib/mongoid/errors/invalid_storage_options.rb +2 -3
  186. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -3
  187. data/lib/mongoid/errors/invalid_time.rb +2 -3
  188. data/lib/mongoid/errors/invalid_value.rb +2 -1
  189. data/lib/mongoid/errors/inverse_not_found.rb +3 -4
  190. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -3
  191. data/lib/mongoid/errors/mixed_relations.rb +2 -3
  192. data/lib/mongoid/errors/mongoid_error.rb +3 -10
  193. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -4
  194. data/lib/mongoid/errors/no_client_config.rb +4 -5
  195. data/lib/mongoid/errors/no_client_database.rb +2 -3
  196. data/lib/mongoid/errors/no_client_hosts.rb +2 -3
  197. data/lib/mongoid/errors/no_clients_config.rb +2 -3
  198. data/lib/mongoid/errors/no_default_client.rb +3 -4
  199. data/lib/mongoid/errors/no_environment.rb +2 -3
  200. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -3
  201. data/lib/mongoid/errors/no_metadata.rb +2 -3
  202. data/lib/mongoid/errors/no_parent.rb +2 -3
  203. data/lib/mongoid/errors/readonly_attribute.rb +2 -3
  204. data/lib/mongoid/errors/readonly_document.rb +3 -6
  205. data/lib/mongoid/errors/scope_overwrite.rb +2 -1
  206. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -0
  207. data/lib/mongoid/errors/unknown_attribute.rb +2 -3
  208. data/lib/mongoid/errors/unknown_model.rb +24 -0
  209. data/lib/mongoid/errors/unsaved_document.rb +3 -2
  210. data/lib/mongoid/errors/unsupported_javascript.rb +2 -3
  211. data/lib/mongoid/errors/validations.rb +2 -1
  212. data/lib/mongoid/errors.rb +15 -1
  213. data/lib/mongoid/evolvable.rb +4 -5
  214. data/lib/mongoid/extensions/array.rb +33 -42
  215. data/lib/mongoid/extensions/big_decimal.rb +2 -11
  216. data/lib/mongoid/extensions/boolean.rb +3 -5
  217. data/lib/mongoid/extensions/date.rb +13 -12
  218. data/lib/mongoid/extensions/date_time.rb +4 -12
  219. data/lib/mongoid/extensions/decimal128.rb +2 -5
  220. data/lib/mongoid/extensions/false_class.rb +4 -7
  221. data/lib/mongoid/extensions/float.rb +5 -10
  222. data/lib/mongoid/extensions/hash.rb +56 -38
  223. data/lib/mongoid/extensions/integer.rb +5 -12
  224. data/lib/mongoid/extensions/module.rb +2 -3
  225. data/lib/mongoid/extensions/nil_class.rb +2 -5
  226. data/lib/mongoid/extensions/object.rb +21 -48
  227. data/lib/mongoid/extensions/object_id.rb +2 -7
  228. data/lib/mongoid/extensions/range.rb +3 -11
  229. data/lib/mongoid/extensions/regexp.rb +3 -4
  230. data/lib/mongoid/extensions/set.rb +2 -7
  231. data/lib/mongoid/extensions/string.rb +21 -41
  232. data/lib/mongoid/extensions/symbol.rb +2 -7
  233. data/lib/mongoid/extensions/time.rb +12 -9
  234. data/lib/mongoid/extensions/time_with_zone.rb +25 -7
  235. data/lib/mongoid/extensions/true_class.rb +4 -7
  236. data/lib/mongoid/extensions.rb +18 -7
  237. data/lib/mongoid/factory.rb +59 -10
  238. data/lib/mongoid/fields/foreign_key.rb +8 -27
  239. data/lib/mongoid/fields/localized.rb +2 -11
  240. data/lib/mongoid/fields/standard.rb +8 -50
  241. data/lib/mongoid/fields/validators/macro.rb +37 -19
  242. data/lib/mongoid/fields/validators.rb +2 -1
  243. data/lib/mongoid/fields.rb +245 -70
  244. data/lib/mongoid/findable.rb +78 -27
  245. data/lib/mongoid/indexable/specification.rb +3 -16
  246. data/lib/mongoid/indexable/validators/options.rb +2 -7
  247. data/lib/mongoid/indexable.rb +10 -22
  248. data/lib/mongoid/inspectable.rb +4 -11
  249. data/lib/mongoid/interceptable.rb +18 -35
  250. data/lib/mongoid/loggable.rb +13 -16
  251. data/lib/mongoid/matchable.rb +3 -153
  252. data/lib/mongoid/matcher/all.rb +22 -0
  253. data/lib/mongoid/matcher/and.rb +21 -0
  254. data/lib/mongoid/matcher/bits.rb +41 -0
  255. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  256. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  257. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  258. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  259. data/lib/mongoid/matcher/elem_match.rb +36 -0
  260. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  261. data/lib/mongoid/matcher/eq.rb +11 -0
  262. data/lib/mongoid/matcher/eq_impl.rb +67 -0
  263. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +26 -0
  264. data/lib/mongoid/matcher/exists.rb +15 -0
  265. data/lib/mongoid/matcher/expression.rb +35 -0
  266. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  267. data/lib/mongoid/matcher/field_expression.rb +62 -0
  268. data/lib/mongoid/matcher/field_operator.rb +54 -0
  269. data/lib/mongoid/matcher/gt.rb +17 -0
  270. data/lib/mongoid/matcher/gte.rb +17 -0
  271. data/lib/mongoid/matcher/in.rb +25 -0
  272. data/lib/mongoid/matcher/lt.rb +17 -0
  273. data/lib/mongoid/matcher/lte.rb +17 -0
  274. data/lib/mongoid/matcher/mod.rb +17 -0
  275. data/lib/mongoid/matcher/ne.rb +16 -0
  276. data/lib/mongoid/matcher/nin.rb +11 -0
  277. data/lib/mongoid/matcher/nor.rb +25 -0
  278. data/lib/mongoid/matcher/not.rb +29 -0
  279. data/lib/mongoid/matcher/or.rb +21 -0
  280. data/lib/mongoid/matcher/regex.rb +41 -0
  281. data/lib/mongoid/matcher/size.rb +26 -0
  282. data/lib/mongoid/matcher/type.rb +99 -0
  283. data/lib/mongoid/matcher.rb +110 -0
  284. data/lib/mongoid/persistable/creatable.rb +4 -21
  285. data/lib/mongoid/persistable/deletable.rb +11 -26
  286. data/lib/mongoid/persistable/destroyable.rb +11 -10
  287. data/lib/mongoid/persistable/incrementable.rb +7 -8
  288. data/lib/mongoid/persistable/logical.rb +5 -7
  289. data/lib/mongoid/persistable/poppable.rb +3 -6
  290. data/lib/mongoid/persistable/pullable.rb +3 -8
  291. data/lib/mongoid/persistable/pushable.rb +14 -10
  292. data/lib/mongoid/persistable/renamable.rb +10 -8
  293. data/lib/mongoid/persistable/savable.rb +3 -8
  294. data/lib/mongoid/persistable/settable.rb +60 -18
  295. data/lib/mongoid/persistable/unsettable.rb +8 -8
  296. data/lib/mongoid/persistable/updatable.rb +32 -20
  297. data/lib/mongoid/persistable/upsertable.rb +4 -9
  298. data/lib/mongoid/persistable.rb +136 -42
  299. data/lib/mongoid/persistence_context.rb +101 -48
  300. data/lib/mongoid/positional.rb +3 -6
  301. data/lib/mongoid/query_cache.rb +117 -130
  302. data/lib/mongoid/railtie.rb +3 -16
  303. data/lib/mongoid/railties/controller_runtime.rb +3 -1
  304. data/lib/mongoid/railties/database.rake +9 -0
  305. data/lib/mongoid/reloadable.rb +14 -19
  306. data/lib/mongoid/scopable.rb +19 -44
  307. data/lib/mongoid/selectable.rb +8 -17
  308. data/lib/mongoid/serializable.rb +28 -33
  309. data/lib/mongoid/shardable.rb +108 -21
  310. data/lib/mongoid/stateful.rb +3 -10
  311. data/lib/mongoid/stringified_symbol.rb +52 -0
  312. data/lib/mongoid/tasks/database.rake +12 -5
  313. data/lib/mongoid/tasks/database.rb +85 -5
  314. data/lib/mongoid/threaded/lifecycle.rb +2 -21
  315. data/lib/mongoid/threaded.rb +2 -55
  316. data/lib/mongoid/timestamps/created/short.rb +2 -1
  317. data/lib/mongoid/timestamps/created.rb +3 -2
  318. data/lib/mongoid/timestamps/short.rb +2 -1
  319. data/lib/mongoid/timestamps/timeless.rb +6 -9
  320. data/lib/mongoid/timestamps/updated/short.rb +2 -1
  321. data/lib/mongoid/timestamps/updated.rb +3 -4
  322. data/lib/mongoid/timestamps.rb +3 -2
  323. data/lib/mongoid/touchable.rb +132 -0
  324. data/lib/mongoid/traversable.rb +183 -60
  325. data/lib/mongoid/validatable/associated.rb +5 -6
  326. data/lib/mongoid/validatable/format.rb +2 -1
  327. data/lib/mongoid/validatable/length.rb +2 -1
  328. data/lib/mongoid/validatable/localizable.rb +2 -3
  329. data/lib/mongoid/validatable/macros.rb +3 -8
  330. data/lib/mongoid/validatable/presence.rb +10 -15
  331. data/lib/mongoid/validatable/queryable.rb +2 -3
  332. data/lib/mongoid/validatable/uniqueness.rb +25 -38
  333. data/lib/mongoid/validatable.rb +16 -35
  334. data/lib/mongoid/version.rb +3 -2
  335. data/lib/mongoid/warnings.rb +29 -0
  336. data/lib/mongoid.rb +34 -15
  337. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  338. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +53 -29
  339. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  340. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  341. data/lib/rails/generators/mongoid_generator.rb +2 -1
  342. data/lib/rails/mongoid.rb +4 -5
  343. data/spec/README.md +33 -0
  344. data/spec/config/mongoid.yml +14 -3
  345. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  346. data/spec/integration/app_spec.rb +349 -0
  347. data/spec/integration/associations/belongs_to_spec.rb +15 -0
  348. data/spec/integration/associations/embedded_dirty_spec.rb +57 -0
  349. data/spec/integration/associations/embedded_spec.rb +268 -0
  350. data/spec/integration/associations/embeds_many_spec.rb +206 -0
  351. data/spec/integration/associations/embeds_one_spec.rb +23 -0
  352. data/spec/integration/associations/foreign_key_spec.rb +98 -0
  353. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  354. data/spec/integration/associations/has_many_spec.rb +128 -0
  355. data/spec/integration/associations/has_one_spec.rb +176 -0
  356. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  357. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  358. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  359. data/spec/integration/associations/scope_option_spec.rb +101 -0
  360. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  361. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  362. data/spec/integration/callbacks_models.rb +61 -0
  363. data/spec/integration/callbacks_spec.rb +228 -0
  364. data/spec/integration/contextual/empty_spec.rb +141 -0
  365. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  366. data/spec/integration/criteria/date_field_spec.rb +40 -0
  367. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  368. data/spec/integration/criteria/logical_spec.rb +124 -0
  369. data/spec/integration/criteria/range_spec.rb +265 -0
  370. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  371. data/spec/integration/discriminator_key_spec.rb +353 -0
  372. data/spec/integration/discriminator_value_spec.rb +206 -0
  373. data/spec/integration/document_spec.rb +30 -1
  374. data/spec/integration/i18n_fallbacks_spec.rb +103 -0
  375. data/spec/integration/matcher_examples_spec.rb +758 -0
  376. data/spec/integration/matcher_operator_data/all.yml +140 -0
  377. data/spec/integration/matcher_operator_data/and.yml +93 -0
  378. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  379. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  380. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  381. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  382. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  383. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  384. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  385. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  386. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  387. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  388. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  389. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  390. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  391. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  392. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  393. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  394. data/spec/integration/matcher_operator_data/in.yml +210 -0
  395. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  396. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  397. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  398. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  399. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  400. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  401. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  402. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  403. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  404. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  405. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  406. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  407. data/spec/integration/matcher_operator_data/not.yml +196 -0
  408. data/spec/integration/matcher_operator_data/or.yml +137 -0
  409. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  410. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  411. data/spec/integration/matcher_operator_data/size.yml +174 -0
  412. data/spec/integration/matcher_operator_data/type.yml +70 -0
  413. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  414. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  415. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  416. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  417. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  418. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  419. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  420. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  421. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  422. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  423. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  424. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  425. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  426. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  427. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  428. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  429. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  430. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  431. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  432. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  433. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  434. data/spec/integration/matcher_operator_spec.rb +124 -0
  435. data/spec/integration/matcher_spec.rb +283 -0
  436. data/spec/integration/server_query_spec.rb +141 -0
  437. data/spec/integration/shardable_spec.rb +148 -0
  438. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  439. data/spec/lite_spec_helper.rb +83 -0
  440. data/spec/mongoid/association/accessors_spec.rb +1067 -0
  441. data/spec/mongoid/association/auto_save_spec.rb +403 -0
  442. data/spec/mongoid/association/builders_spec.rb +255 -0
  443. data/spec/mongoid/association/constrainable_spec.rb +117 -0
  444. data/spec/mongoid/association/counter_cache_spec.rb +452 -0
  445. data/spec/mongoid/association/depending_spec.rb +959 -0
  446. data/spec/mongoid/association/eager_spec.rb +281 -0
  447. data/spec/mongoid/association/embedded/cyclic_spec.rb +180 -0
  448. data/spec/mongoid/association/embedded/dirty_spec.rb +67 -0
  449. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +173 -0
  450. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +36 -0
  451. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +559 -0
  452. data/spec/mongoid/association/embedded/embedded_in_spec.rb +903 -0
  453. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +56 -0
  454. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +106 -0
  455. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +4673 -0
  456. data/spec/mongoid/association/embedded/embeds_many_models.rb +190 -0
  457. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +51 -0
  458. data/spec/mongoid/association/embedded/embeds_many_spec.rb +864 -0
  459. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +79 -0
  460. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +81 -0
  461. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +1025 -0
  462. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +8 -0
  463. data/spec/mongoid/association/embedded/embeds_one_models.rb +54 -0
  464. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  465. data/spec/mongoid/association/embedded/embeds_one_spec.rb +956 -0
  466. data/spec/mongoid/association/macros_spec.rb +1116 -0
  467. data/spec/mongoid/association/nested/many_spec.rb +232 -0
  468. data/spec/mongoid/association/nested/one_spec.rb +253 -0
  469. data/spec/mongoid/association/options_spec.rb +1323 -0
  470. data/spec/mongoid/association/polymorphic_spec.rb +162 -0
  471. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +243 -0
  472. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +238 -0
  473. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +412 -0
  474. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +1373 -0
  475. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  476. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2046 -0
  477. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +180 -0
  478. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +148 -0
  479. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +196 -0
  480. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +76 -0
  481. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +3803 -0
  482. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +67 -0
  483. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  484. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1071 -0
  485. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +155 -0
  486. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +142 -0
  487. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +290 -0
  488. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2286 -0
  489. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  490. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +4112 -0
  491. data/spec/mongoid/association/referenced/has_many_models.rb +95 -0
  492. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  493. data/spec/mongoid/association/referenced/has_many_spec.rb +1248 -0
  494. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +133 -0
  495. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +159 -0
  496. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +193 -0
  497. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +1142 -0
  498. data/spec/mongoid/association/referenced/has_one_models.rb +97 -0
  499. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  500. data/spec/mongoid/association/referenced/has_one_spec.rb +1383 -0
  501. data/spec/mongoid/association/reflections_spec.rb +92 -0
  502. data/spec/mongoid/association/syncable_spec.rb +499 -0
  503. data/spec/mongoid/association_spec.rb +191 -0
  504. data/spec/mongoid/atomic/modifiers_spec.rb +51 -2
  505. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  506. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  507. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  508. data/spec/mongoid/atomic/paths_spec.rb +107 -12
  509. data/spec/mongoid/atomic_spec.rb +57 -10
  510. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  511. data/spec/mongoid/attributes/nested_spec.rb +98 -78
  512. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  513. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  514. data/spec/mongoid/attributes/projector_spec.rb +44 -0
  515. data/spec/mongoid/attributes/readonly_spec.rb +84 -127
  516. data/spec/mongoid/attributes_spec.rb +461 -34
  517. data/spec/mongoid/cacheable_spec.rb +6 -4
  518. data/spec/mongoid/changeable_spec.rb +60 -35
  519. data/spec/mongoid/clients/factory_spec.rb +98 -9
  520. data/spec/mongoid/clients/options_spec.rb +93 -60
  521. data/spec/mongoid/clients/sessions_spec.rb +34 -33
  522. data/spec/mongoid/clients/transactions_spec.rb +415 -0
  523. data/spec/mongoid/clients_spec.rb +108 -16
  524. data/spec/mongoid/composable_spec.rb +2 -0
  525. data/spec/mongoid/config/environment_spec.rb +126 -8
  526. data/spec/mongoid/config/options_spec.rb +22 -3
  527. data/spec/mongoid/config_spec.rb +357 -2
  528. data/spec/mongoid/contextual/aggregable/memory_spec.rb +53 -11
  529. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  530. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  531. data/spec/mongoid/contextual/atomic_spec.rb +242 -81
  532. data/spec/mongoid/contextual/geo_near_spec.rb +30 -19
  533. data/spec/mongoid/contextual/map_reduce_spec.rb +24 -7
  534. data/spec/mongoid/contextual/memory_spec.rb +870 -88
  535. data/spec/mongoid/contextual/mongo_spec.rb +1339 -184
  536. data/spec/mongoid/contextual/none_spec.rb +45 -71
  537. data/spec/mongoid/copyable_spec.rb +294 -29
  538. data/spec/mongoid/copyable_spec_models.rb +47 -0
  539. data/spec/mongoid/criteria/findable_spec.rb +77 -20
  540. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  541. data/spec/mongoid/criteria/marshalable_spec.rb +2 -0
  542. data/spec/mongoid/criteria/modifiable_spec.rb +215 -40
  543. data/spec/mongoid/criteria/options_spec.rb +2 -0
  544. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -1
  545. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  546. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +2 -0
  547. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +2 -0
  548. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +2 -0
  549. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -1
  550. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +2 -0
  551. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +35 -17
  552. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +2 -0
  553. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +2 -0
  554. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +2 -0
  555. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +2 -0
  556. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +2 -0
  557. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +53 -0
  558. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +2 -0
  559. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +239 -178
  560. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -1
  561. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +9 -7
  562. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +2 -0
  563. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +46 -1
  564. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -0
  565. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +42 -23
  566. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +30 -1
  567. data/spec/mongoid/criteria/queryable/key_spec.rb +50 -6
  568. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +145 -12
  569. data/spec/mongoid/criteria/queryable/optional_spec.rb +3 -1
  570. data/spec/mongoid/criteria/queryable/options_spec.rb +2 -0
  571. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +14 -0
  572. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -1
  573. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2069 -0
  574. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  575. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1155 -2927
  576. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  577. data/spec/mongoid/criteria/queryable/selector_spec.rb +114 -2
  578. data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
  579. data/spec/mongoid/criteria/queryable/storable_spec.rb +298 -0
  580. data/spec/mongoid/criteria/scopable_spec.rb +129 -0
  581. data/spec/mongoid/criteria_projection_spec.rb +410 -0
  582. data/spec/mongoid/criteria_spec.rb +826 -478
  583. data/spec/mongoid/document_fields_spec.rb +113 -0
  584. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  585. data/spec/mongoid/document_query_spec.rb +89 -0
  586. data/spec/mongoid/document_spec.rb +131 -31
  587. data/spec/mongoid/equality_spec.rb +144 -41
  588. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  589. data/spec/mongoid/errors/callback_spec.rb +2 -0
  590. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  591. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  592. data/spec/mongoid/errors/document_not_found_spec.rb +51 -0
  593. data/spec/mongoid/errors/eager_load_spec.rb +2 -0
  594. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  595. data/spec/mongoid/errors/invalid_config_file_spec.rb +31 -0
  596. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  597. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  598. data/spec/mongoid/errors/invalid_field_spec.rb +2 -0
  599. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  600. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  601. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  602. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  603. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  604. data/spec/mongoid/errors/invalid_relation_spec.rb +4 -2
  605. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  606. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  607. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  608. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  609. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  610. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  611. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  612. data/spec/mongoid/errors/mongoid_error_spec.rb +22 -8
  613. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  614. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  615. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  616. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  617. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  618. data/spec/mongoid/errors/no_environment_spec.rb +2 -0
  619. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  620. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  621. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  622. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  623. data/spec/mongoid/errors/readonly_document_spec.rb +2 -0
  624. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  625. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +2 -0
  626. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  627. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  628. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  629. data/spec/mongoid/errors/validations_spec.rb +2 -0
  630. data/spec/mongoid/extensions/array_spec.rb +36 -58
  631. data/spec/mongoid/extensions/big_decimal_spec.rb +2 -0
  632. data/spec/mongoid/extensions/binary_spec.rb +2 -0
  633. data/spec/mongoid/extensions/boolean_spec.rb +2 -0
  634. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +335 -0
  635. data/spec/mongoid/extensions/date_spec.rb +8 -160
  636. data/spec/mongoid/extensions/date_time_spec.rb +17 -60
  637. data/spec/mongoid/extensions/decimal128_spec.rb +2 -0
  638. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  639. data/spec/mongoid/extensions/float_spec.rb +17 -3
  640. data/spec/mongoid/extensions/hash_spec.rb +123 -1
  641. data/spec/mongoid/extensions/integer_spec.rb +14 -2
  642. data/spec/mongoid/extensions/module_spec.rb +2 -0
  643. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  644. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  645. data/spec/mongoid/extensions/object_spec.rb +20 -35
  646. data/spec/mongoid/extensions/range_spec.rb +9 -0
  647. data/spec/mongoid/extensions/regexp_spec.rb +2 -0
  648. data/spec/mongoid/extensions/set_spec.rb +2 -0
  649. data/spec/mongoid/extensions/string_spec.rb +60 -27
  650. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  651. data/spec/mongoid/extensions/symbol_spec.rb +2 -0
  652. data/spec/mongoid/extensions/time_spec.rb +29 -0
  653. data/spec/mongoid/extensions/time_with_zone_spec.rb +33 -0
  654. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  655. data/spec/mongoid/extensions_spec.rb +16 -2
  656. data/spec/mongoid/factory_spec.rb +301 -23
  657. data/spec/mongoid/fields/foreign_key_spec.rb +26 -32
  658. data/spec/mongoid/fields/localized_spec.rb +6 -4
  659. data/spec/mongoid/fields/standard_spec.rb +2 -0
  660. data/spec/mongoid/fields_spec.rb +419 -37
  661. data/spec/mongoid/findable_spec.rb +83 -19
  662. data/spec/mongoid/indexable/specification_spec.rb +2 -0
  663. data/spec/mongoid/indexable_spec.rb +54 -14
  664. data/spec/mongoid/inspectable_spec.rb +39 -2
  665. data/spec/mongoid/interceptable_spec.rb +189 -96
  666. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  667. data/spec/mongoid/loggable_spec.rb +2 -0
  668. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  669. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  670. data/spec/mongoid/matcher/extract_attribute_spec.rb +40 -0
  671. data/spec/mongoid/persistable/creatable_spec.rb +112 -27
  672. data/spec/mongoid/persistable/deletable_spec.rb +273 -11
  673. data/spec/mongoid/persistable/destroyable_spec.rb +201 -11
  674. data/spec/mongoid/persistable/incrementable_spec.rb +23 -7
  675. data/spec/mongoid/persistable/logical_spec.rb +19 -3
  676. data/spec/mongoid/persistable/poppable_spec.rb +19 -3
  677. data/spec/mongoid/persistable/pullable_spec.rb +36 -6
  678. data/spec/mongoid/persistable/pushable_spec.rb +91 -7
  679. data/spec/mongoid/persistable/renamable_spec.rb +18 -2
  680. data/spec/mongoid/persistable/savable_spec.rb +189 -26
  681. data/spec/mongoid/persistable/settable_spec.rb +149 -18
  682. data/spec/mongoid/persistable/unsettable_spec.rb +19 -3
  683. data/spec/mongoid/persistable/updatable_spec.rb +45 -23
  684. data/spec/mongoid/persistable/upsertable_spec.rb +4 -2
  685. data/spec/mongoid/persistable_spec.rb +106 -15
  686. data/spec/mongoid/persistence_context_spec.rb +29 -2
  687. data/spec/mongoid/positional_spec.rb +2 -0
  688. data/spec/mongoid/query_cache_middleware_spec.rb +68 -0
  689. data/spec/mongoid/query_cache_spec.rb +529 -85
  690. data/spec/mongoid/relations/proxy_spec.rb +126 -124
  691. data/spec/mongoid/reloadable_spec.rb +298 -20
  692. data/spec/mongoid/scopable_spec.rb +102 -37
  693. data/spec/mongoid/selectable_spec.rb +8 -6
  694. data/spec/mongoid/serializable_spec.rb +160 -29
  695. data/spec/mongoid/shardable_models.rb +75 -0
  696. data/spec/mongoid/shardable_spec.rb +251 -26
  697. data/spec/mongoid/stateful_spec.rb +3 -1
  698. data/spec/mongoid/tasks/database_rake_spec.rb +15 -13
  699. data/spec/mongoid/tasks/database_spec.rb +3 -1
  700. data/spec/mongoid/threaded_spec.rb +4 -2
  701. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  702. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  703. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  704. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  705. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  706. data/spec/mongoid/timestamps_spec.rb +8 -6
  707. data/spec/mongoid/touchable_spec.rb +588 -0
  708. data/spec/mongoid/touchable_spec_models.rb +53 -0
  709. data/spec/mongoid/traversable_spec.rb +1167 -1
  710. data/spec/mongoid/validatable/associated_spec.rb +3 -1
  711. data/spec/mongoid/validatable/format_spec.rb +2 -0
  712. data/spec/mongoid/validatable/length_spec.rb +2 -0
  713. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  714. data/spec/mongoid/validatable/presence_spec.rb +33 -26
  715. data/spec/mongoid/validatable/uniqueness_spec.rb +102 -73
  716. data/spec/mongoid/validatable_spec.rb +5 -3
  717. data/spec/mongoid_spec.rb +9 -1
  718. data/spec/rails/controller_extension/controller_runtime_spec.rb +3 -1
  719. data/spec/rails/mongoid_spec.rb +4 -2
  720. data/spec/shared/LICENSE +20 -0
  721. data/spec/shared/bin/get-mongodb-download-url +17 -0
  722. data/spec/shared/bin/s3-copy +45 -0
  723. data/spec/shared/bin/s3-upload +69 -0
  724. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  725. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  726. data/spec/shared/lib/mrss/constraints.rb +378 -0
  727. data/spec/shared/lib/mrss/docker_runner.rb +291 -0
  728. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  729. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  730. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  731. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  732. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  733. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  734. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  735. data/spec/shared/lib/mrss/utils.rb +15 -0
  736. data/spec/shared/share/Dockerfile.erb +325 -0
  737. data/spec/shared/share/haproxy-1.conf +16 -0
  738. data/spec/shared/share/haproxy-2.conf +17 -0
  739. data/spec/shared/shlib/config.sh +27 -0
  740. data/spec/shared/shlib/distro.sh +74 -0
  741. data/spec/shared/shlib/server.sh +392 -0
  742. data/spec/shared/shlib/set_env.sh +169 -0
  743. data/spec/spec_helper.rb +70 -83
  744. data/spec/support/authorization.rb +2 -0
  745. data/spec/support/client_registry.rb +9 -0
  746. data/spec/support/constraints.rb +27 -75
  747. data/spec/support/expectations.rb +21 -3
  748. data/spec/support/helpers.rb +11 -0
  749. data/spec/support/macros.rb +31 -0
  750. data/spec/support/models/account.rb +38 -0
  751. data/spec/support/models/acolyte.rb +19 -0
  752. data/spec/support/models/actor.rb +20 -0
  753. data/spec/support/models/actress.rb +4 -0
  754. data/spec/support/models/address.rb +85 -0
  755. data/spec/support/models/address_component.rb +7 -0
  756. data/spec/support/models/address_number.rb +8 -0
  757. data/spec/support/models/agency.rb +7 -0
  758. data/spec/support/models/agent.rb +18 -0
  759. data/spec/support/models/album.rb +20 -0
  760. data/spec/support/models/alert.rb +9 -0
  761. data/spec/support/models/animal.rb +28 -0
  762. data/spec/support/models/answer.rb +8 -0
  763. data/spec/support/models/appointment.rb +9 -0
  764. data/spec/support/models/armrest.rb +9 -0
  765. data/spec/support/models/article.rb +14 -0
  766. data/spec/support/models/artist.rb +91 -0
  767. data/spec/support/models/artwork.rb +6 -0
  768. data/spec/support/models/audible_sound.rb +3 -0
  769. data/spec/support/models/audio.rb +7 -0
  770. data/spec/support/models/augmentation.rb +13 -0
  771. data/spec/support/models/author.rb +8 -0
  772. data/spec/support/models/baby.rb +6 -0
  773. data/spec/support/models/band.rb +37 -0
  774. data/spec/support/models/bar.rb +12 -0
  775. data/spec/support/models/basic.rb +8 -0
  776. data/spec/support/models/bed.rb +3 -0
  777. data/spec/support/models/big_palette.rb +4 -0
  778. data/spec/support/models/birthday.rb +15 -0
  779. data/spec/support/models/bolt.rb +7 -0
  780. data/spec/support/models/bomb.rb +6 -0
  781. data/spec/support/models/book.rb +18 -0
  782. data/spec/support/models/breed.rb +6 -0
  783. data/spec/support/models/browser.rb +8 -0
  784. data/spec/support/models/building.rb +8 -0
  785. data/spec/support/models/building_address.rb +9 -0
  786. data/spec/support/models/bus.rb +9 -0
  787. data/spec/support/models/business.rb +7 -0
  788. data/spec/support/models/callback_test.rb +11 -0
  789. data/spec/support/models/canvas.rb +27 -0
  790. data/spec/support/models/car.rb +3 -0
  791. data/spec/support/models/cat.rb +10 -0
  792. data/spec/support/models/category.rb +10 -0
  793. data/spec/support/models/child.rb +6 -0
  794. data/spec/support/models/child_doc.rb +24 -0
  795. data/spec/support/models/church.rb +8 -0
  796. data/spec/support/models/circle.rb +5 -0
  797. data/spec/support/models/circuit.rb +6 -0
  798. data/spec/support/models/circus.rb +9 -0
  799. data/spec/support/models/code.rb +15 -0
  800. data/spec/support/models/coding/pull_request.rb +11 -0
  801. data/spec/support/models/coding.rb +3 -0
  802. data/spec/support/models/comment.rb +18 -0
  803. data/spec/support/models/company.rb +7 -0
  804. data/spec/support/models/consumption_period.rb +9 -0
  805. data/spec/support/models/contextable_item.rb +7 -0
  806. data/spec/support/models/contractor.rb +7 -0
  807. data/spec/support/models/cookie.rb +8 -0
  808. data/spec/support/models/country_code.rb +12 -0
  809. data/spec/support/models/courier_job.rb +6 -0
  810. data/spec/support/models/crate.rb +12 -0
  811. data/spec/support/models/customer.rb +10 -0
  812. data/spec/support/models/customer_address.rb +11 -0
  813. data/spec/support/models/deed.rb +7 -0
  814. data/spec/support/models/definition.rb +11 -0
  815. data/spec/support/models/delegating_patient.rb +15 -0
  816. data/spec/support/models/description.rb +13 -0
  817. data/spec/support/models/dictionary.rb +18 -0
  818. data/spec/support/models/division.rb +12 -0
  819. data/spec/support/models/doctor.rb +14 -0
  820. data/spec/support/models/dog.rb +9 -0
  821. data/spec/support/models/dokument.rb +8 -0
  822. data/spec/support/models/draft.rb +11 -0
  823. data/spec/support/models/dragon.rb +6 -0
  824. data/spec/support/models/driver.rb +9 -0
  825. data/spec/support/models/drug.rb +8 -0
  826. data/spec/support/models/dungeon.rb +6 -0
  827. data/spec/support/models/edit.rb +7 -0
  828. data/spec/support/models/email.rb +8 -0
  829. data/spec/support/models/employer.rb +7 -0
  830. data/spec/support/models/entry.rb +8 -0
  831. data/spec/support/models/eraser.rb +3 -0
  832. data/spec/support/models/even.rb +9 -0
  833. data/spec/support/models/event.rb +24 -0
  834. data/spec/support/models/exhibition.rb +6 -0
  835. data/spec/support/models/exhibitor.rb +8 -0
  836. data/spec/support/models/explosion.rb +6 -0
  837. data/spec/support/models/eye.rb +11 -0
  838. data/spec/support/models/eye_bowl.rb +11 -0
  839. data/spec/support/models/face.rb +10 -0
  840. data/spec/support/models/favorite.rb +8 -0
  841. data/spec/support/models/filesystem.rb +7 -0
  842. data/spec/support/models/fire_hydrant.rb +8 -0
  843. data/spec/support/models/firefox.rb +6 -0
  844. data/spec/support/models/fish.rb +9 -0
  845. data/spec/support/models/folder.rb +9 -0
  846. data/spec/support/models/folder_item.rb +11 -0
  847. data/spec/support/models/fruits.rb +36 -0
  848. data/spec/support/models/game.rb +21 -0
  849. data/spec/support/models/ghost.rb +9 -0
  850. data/spec/support/models/guitar.rb +4 -0
  851. data/spec/support/models/hole.rb +12 -0
  852. data/spec/support/models/home.rb +6 -0
  853. data/spec/support/models/house.rb +8 -0
  854. data/spec/support/models/html_writer.rb +5 -0
  855. data/spec/support/models/id_key.rb +8 -0
  856. data/spec/support/models/idnodef.rb +7 -0
  857. data/spec/support/models/image.rb +24 -0
  858. data/spec/support/models/implant.rb +18 -0
  859. data/spec/support/models/instrument.rb +8 -0
  860. data/spec/support/models/item.rb +10 -0
  861. data/spec/support/models/jar.rb +9 -0
  862. data/spec/support/models/kaleidoscope.rb +8 -0
  863. data/spec/support/models/kangaroo.rb +6 -0
  864. data/spec/support/models/label.rb +50 -0
  865. data/spec/support/models/language.rb +7 -0
  866. data/spec/support/models/lat_lng.rb +17 -0
  867. data/spec/support/models/league.rb +13 -0
  868. data/spec/support/models/learner.rb +4 -0
  869. data/spec/support/models/line_item.rb +8 -0
  870. data/spec/support/models/location.rb +10 -0
  871. data/spec/support/models/login.rb +10 -0
  872. data/spec/support/models/manufacturer.rb +9 -0
  873. data/spec/support/models/meat.rb +6 -0
  874. data/spec/support/models/membership.rb +7 -0
  875. data/spec/support/models/message.rb +13 -0
  876. data/spec/support/models/minim.rb +6 -0
  877. data/spec/support/models/mixed_drink.rb +6 -0
  878. data/spec/support/models/mop.rb +24 -0
  879. data/spec/support/models/movie.rb +15 -0
  880. data/spec/support/models/my_hash.rb +4 -0
  881. data/spec/support/models/name.rb +26 -0
  882. data/spec/support/models/name_only.rb +8 -0
  883. data/spec/support/models/node.rb +7 -0
  884. data/spec/support/models/note.rb +19 -0
  885. data/spec/support/models/nut.rb +7 -0
  886. data/spec/support/models/odd.rb +9 -0
  887. data/spec/support/models/order.rb +12 -0
  888. data/spec/support/models/ordered_post.rb +13 -0
  889. data/spec/support/models/ordered_preference.rb +8 -0
  890. data/spec/support/models/oscar.rb +16 -0
  891. data/spec/support/models/other_owner_object.rb +4 -0
  892. data/spec/support/models/override.rb +18 -0
  893. data/spec/support/models/ownable.rb +8 -0
  894. data/spec/support/models/owner.rb +10 -0
  895. data/spec/support/models/pack.rb +5 -0
  896. data/spec/support/models/page.rb +18 -0
  897. data/spec/support/models/page_question.rb +6 -0
  898. data/spec/support/models/palette.rb +9 -0
  899. data/spec/support/models/parent.rb +7 -0
  900. data/spec/support/models/parent_doc.rb +8 -0
  901. data/spec/support/models/passport.rb +13 -0
  902. data/spec/support/models/patient.rb +11 -0
  903. data/spec/support/models/pdf_writer.rb +5 -0
  904. data/spec/support/models/pencil.rb +3 -0
  905. data/spec/support/models/person.rb +230 -0
  906. data/spec/support/models/pet.rb +25 -0
  907. data/spec/support/models/pet_owner.rb +8 -0
  908. data/spec/support/models/phone.rb +13 -0
  909. data/spec/support/models/piano.rb +4 -0
  910. data/spec/support/models/pizza.rb +9 -0
  911. data/spec/support/models/player.rb +37 -0
  912. data/spec/support/models/post.rb +52 -0
  913. data/spec/support/models/post_genre.rb +8 -0
  914. data/spec/support/models/powerup.rb +13 -0
  915. data/spec/support/models/preference.rb +11 -0
  916. data/spec/support/models/princess.rb +12 -0
  917. data/spec/support/models/product.rb +19 -0
  918. data/spec/support/models/profile.rb +17 -0
  919. data/spec/support/models/pronunciation.rb +7 -0
  920. data/spec/support/models/pub.rb +8 -0
  921. data/spec/support/models/publication/encyclopedia.rb +11 -0
  922. data/spec/support/models/publication/review.rb +13 -0
  923. data/spec/support/models/publication.rb +4 -0
  924. data/spec/support/models/purchase.rb +6 -0
  925. data/spec/support/models/purchased_item.rb +10 -0
  926. data/spec/support/models/question.rb +10 -0
  927. data/spec/support/models/quiz.rb +9 -0
  928. data/spec/support/models/rating.rb +10 -0
  929. data/spec/support/models/record.rb +54 -0
  930. data/spec/support/models/registry.rb +6 -0
  931. data/spec/support/models/role.rb +9 -0
  932. data/spec/support/models/root_category.rb +6 -0
  933. data/spec/support/models/sandwich.rb +11 -0
  934. data/spec/support/models/scheduler.rb +9 -0
  935. data/spec/support/models/scribe.rb +7 -0
  936. data/spec/support/models/sealer.rb +7 -0
  937. data/spec/support/models/seat.rb +24 -0
  938. data/spec/support/models/seo.rb +9 -0
  939. data/spec/support/models/series.rb +7 -0
  940. data/spec/support/models/server.rb +15 -0
  941. data/spec/support/models/service.rb +24 -0
  942. data/spec/support/models/shape.rb +14 -0
  943. data/spec/support/models/shelf.rb +7 -0
  944. data/spec/support/models/shipment_address.rb +5 -0
  945. data/spec/support/models/shipping_container.rb +7 -0
  946. data/spec/support/models/shipping_pack.rb +5 -0
  947. data/spec/support/models/shirt.rb +11 -0
  948. data/spec/support/models/shop.rb +8 -0
  949. data/spec/support/models/short_agent.rb +6 -0
  950. data/spec/support/models/short_quiz.rb +7 -0
  951. data/spec/support/models/simple.rb +7 -0
  952. data/spec/support/models/slave.rb +8 -0
  953. data/spec/support/models/song.rb +10 -0
  954. data/spec/support/models/sound.rb +7 -0
  955. data/spec/support/models/spacer.rb +7 -0
  956. data/spec/support/models/square.rb +6 -0
  957. data/spec/support/models/staff.rb +9 -0
  958. data/spec/support/models/store_as_dup_test1.rb +7 -0
  959. data/spec/support/models/store_as_dup_test2.rb +7 -0
  960. data/spec/support/models/store_as_dup_test3.rb +7 -0
  961. data/spec/support/models/store_as_dup_test4.rb +7 -0
  962. data/spec/support/models/strategy.rb +5 -0
  963. data/spec/support/models/sub_item.rb +5 -0
  964. data/spec/support/models/subscription.rb +7 -0
  965. data/spec/support/models/survey.rb +7 -0
  966. data/spec/support/models/symptom.rb +8 -0
  967. data/spec/support/models/system_role.rb +7 -0
  968. data/spec/support/models/tag.rb +10 -0
  969. data/spec/support/models/target.rb +7 -0
  970. data/spec/support/models/template.rb +7 -0
  971. data/spec/support/models/thing.rb +11 -0
  972. data/spec/support/models/threadlocker.rb +7 -0
  973. data/spec/support/models/title.rb +5 -0
  974. data/spec/support/models/tool.rb +10 -0
  975. data/spec/support/models/topping.rb +7 -0
  976. data/spec/support/models/toy.rb +9 -0
  977. data/spec/support/models/track.rb +40 -0
  978. data/spec/support/models/translation.rb +7 -0
  979. data/spec/support/models/tree.rb +11 -0
  980. data/spec/support/models/truck.rb +7 -0
  981. data/spec/support/models/updatable.rb +7 -0
  982. data/spec/support/models/user.rb +23 -0
  983. data/spec/support/models/user_account.rb +12 -0
  984. data/spec/support/models/validation_callback.rb +12 -0
  985. data/spec/support/models/vehicle.rb +18 -0
  986. data/spec/support/models/version.rb +7 -0
  987. data/spec/support/models/vertex.rb +8 -0
  988. data/spec/support/models/vet_visit.rb +7 -0
  989. data/spec/support/models/video.rb +15 -0
  990. data/spec/support/models/video_game.rb +3 -0
  991. data/spec/support/models/washer.rb +7 -0
  992. data/spec/support/models/weapon.rb +13 -0
  993. data/spec/support/models/wiki_page.rb +17 -0
  994. data/spec/support/models/word.rb +17 -0
  995. data/spec/support/models/word_origin.rb +13 -0
  996. data/spec/support/models/writer.rb +13 -0
  997. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  998. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  999. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  1000. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1001. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  1002. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1003. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  1004. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1005. data/spec/support/schema_maps/schema_map_local.json +18 -0
  1006. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1007. data/spec/support/shared/time.rb +53 -0
  1008. data/spec/support/spec_config.rb +28 -6
  1009. data.tar.gz.sig +0 -0
  1010. metadata +1304 -843
  1011. metadata.gz.sig +3 -5
  1012. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  1013. data/lib/mongoid/matchable/all.rb +0 -27
  1014. data/lib/mongoid/matchable/and.rb +0 -30
  1015. data/lib/mongoid/matchable/default.rb +0 -72
  1016. data/lib/mongoid/matchable/elem_match.rb +0 -28
  1017. data/lib/mongoid/matchable/exists.rb +0 -23
  1018. data/lib/mongoid/matchable/gt.rb +0 -23
  1019. data/lib/mongoid/matchable/gte.rb +0 -23
  1020. data/lib/mongoid/matchable/in.rb +0 -24
  1021. data/lib/mongoid/matchable/lt.rb +0 -23
  1022. data/lib/mongoid/matchable/lte.rb +0 -23
  1023. data/lib/mongoid/matchable/ne.rb +0 -21
  1024. data/lib/mongoid/matchable/nin.rb +0 -22
  1025. data/lib/mongoid/matchable/nor.rb +0 -37
  1026. data/lib/mongoid/matchable/or.rb +0 -33
  1027. data/lib/mongoid/matchable/regexp.rb +0 -27
  1028. data/lib/mongoid/matchable/size.rb +0 -21
  1029. data/lib/mongoid/relations/accessors.rb +0 -267
  1030. data/lib/mongoid/relations/auto_save.rb +0 -94
  1031. data/lib/mongoid/relations/binding.rb +0 -218
  1032. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  1033. data/lib/mongoid/relations/bindings/embedded/many.rb +0 -43
  1034. data/lib/mongoid/relations/bindings/embedded/one.rb +0 -45
  1035. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  1036. data/lib/mongoid/relations/bindings/referenced/many.rb +0 -38
  1037. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  1038. data/lib/mongoid/relations/bindings/referenced/one.rb +0 -44
  1039. data/lib/mongoid/relations/bindings.rb +0 -9
  1040. data/lib/mongoid/relations/builder.rb +0 -57
  1041. data/lib/mongoid/relations/builders/embedded/in.rb +0 -29
  1042. data/lib/mongoid/relations/builders/embedded/many.rb +0 -36
  1043. data/lib/mongoid/relations/builders/embedded/one.rb +0 -30
  1044. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  1045. data/lib/mongoid/relations/builders/nested_attributes/one.rb +0 -126
  1046. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  1047. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  1048. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  1049. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  1050. data/lib/mongoid/relations/builders.rb +0 -106
  1051. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  1052. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  1053. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  1054. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  1055. data/lib/mongoid/relations/cascading.rb +0 -56
  1056. data/lib/mongoid/relations/constraint.rb +0 -55
  1057. data/lib/mongoid/relations/conversions.rb +0 -34
  1058. data/lib/mongoid/relations/counter_cache.rb +0 -160
  1059. data/lib/mongoid/relations/cyclic.rb +0 -107
  1060. data/lib/mongoid/relations/eager/base.rb +0 -153
  1061. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  1062. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  1063. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  1064. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  1065. data/lib/mongoid/relations/eager.rb +0 -36
  1066. data/lib/mongoid/relations/embedded/batchable.rb +0 -384
  1067. data/lib/mongoid/relations/embedded/in.rb +0 -241
  1068. data/lib/mongoid/relations/embedded/many.rb +0 -683
  1069. data/lib/mongoid/relations/embedded/one.rb +0 -235
  1070. data/lib/mongoid/relations/macros.rb +0 -367
  1071. data/lib/mongoid/relations/many.rb +0 -242
  1072. data/lib/mongoid/relations/marshalable.rb +0 -32
  1073. data/lib/mongoid/relations/metadata.rb +0 -1179
  1074. data/lib/mongoid/relations/nested_builder.rb +0 -74
  1075. data/lib/mongoid/relations/one.rb +0 -60
  1076. data/lib/mongoid/relations/options.rb +0 -49
  1077. data/lib/mongoid/relations/polymorphic.rb +0 -39
  1078. data/lib/mongoid/relations/proxy.rb +0 -215
  1079. data/lib/mongoid/relations/referenced/in.rb +0 -304
  1080. data/lib/mongoid/relations/referenced/many.rb +0 -812
  1081. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
  1082. data/lib/mongoid/relations/referenced/one.rb +0 -290
  1083. data/lib/mongoid/relations/reflections.rb +0 -64
  1084. data/lib/mongoid/relations/synchronization.rb +0 -169
  1085. data/lib/mongoid/relations/targets/enumerable.rb +0 -493
  1086. data/lib/mongoid/relations/targets.rb +0 -2
  1087. data/lib/mongoid/relations/touchable.rb +0 -97
  1088. data/lib/mongoid/relations.rb +0 -148
  1089. data/lib/support/ruby_version.rb +0 -26
  1090. data/spec/app/models/account.rb +0 -36
  1091. data/spec/app/models/acolyte.rb +0 -17
  1092. data/spec/app/models/actor.rb +0 -18
  1093. data/spec/app/models/actress.rb +0 -2
  1094. data/spec/app/models/address.rb +0 -79
  1095. data/spec/app/models/address_component.rb +0 -5
  1096. data/spec/app/models/address_number.rb +0 -6
  1097. data/spec/app/models/agency.rb +0 -5
  1098. data/spec/app/models/agent.rb +0 -16
  1099. data/spec/app/models/album.rb +0 -18
  1100. data/spec/app/models/alert.rb +0 -7
  1101. data/spec/app/models/animal.rb +0 -25
  1102. data/spec/app/models/answer.rb +0 -6
  1103. data/spec/app/models/appointment.rb +0 -7
  1104. data/spec/app/models/article.rb +0 -12
  1105. data/spec/app/models/artist.rb +0 -87
  1106. data/spec/app/models/artwork.rb +0 -4
  1107. data/spec/app/models/audio.rb +0 -5
  1108. data/spec/app/models/augmentation.rb +0 -11
  1109. data/spec/app/models/author.rb +0 -6
  1110. data/spec/app/models/baby.rb +0 -4
  1111. data/spec/app/models/band.rb +0 -31
  1112. data/spec/app/models/bar.rb +0 -10
  1113. data/spec/app/models/basic.rb +0 -6
  1114. data/spec/app/models/bed.rb +0 -1
  1115. data/spec/app/models/big_palette.rb +0 -2
  1116. data/spec/app/models/birthday.rb +0 -13
  1117. data/spec/app/models/bomb.rb +0 -4
  1118. data/spec/app/models/book.rb +0 -16
  1119. data/spec/app/models/breed.rb +0 -4
  1120. data/spec/app/models/browser.rb +0 -6
  1121. data/spec/app/models/building.rb +0 -6
  1122. data/spec/app/models/building_address.rb +0 -7
  1123. data/spec/app/models/bus.rb +0 -7
  1124. data/spec/app/models/business.rb +0 -5
  1125. data/spec/app/models/callback_test.rb +0 -9
  1126. data/spec/app/models/canvas.rb +0 -25
  1127. data/spec/app/models/car.rb +0 -1
  1128. data/spec/app/models/cat.rb +0 -8
  1129. data/spec/app/models/category.rb +0 -8
  1130. data/spec/app/models/child.rb +0 -4
  1131. data/spec/app/models/child_doc.rb +0 -22
  1132. data/spec/app/models/church.rb +0 -6
  1133. data/spec/app/models/circle.rb +0 -3
  1134. data/spec/app/models/circuit.rb +0 -4
  1135. data/spec/app/models/circus.rb +0 -7
  1136. data/spec/app/models/code.rb +0 -11
  1137. data/spec/app/models/comment.rb +0 -16
  1138. data/spec/app/models/company.rb +0 -5
  1139. data/spec/app/models/consumption_period.rb +0 -7
  1140. data/spec/app/models/contextable_item.rb +0 -5
  1141. data/spec/app/models/contractor.rb +0 -5
  1142. data/spec/app/models/cookie.rb +0 -6
  1143. data/spec/app/models/country_code.rb +0 -8
  1144. data/spec/app/models/courier_job.rb +0 -4
  1145. data/spec/app/models/definition.rb +0 -9
  1146. data/spec/app/models/delegating_patient.rb +0 -16
  1147. data/spec/app/models/description.rb +0 -11
  1148. data/spec/app/models/dictionary.rb +0 -10
  1149. data/spec/app/models/division.rb +0 -10
  1150. data/spec/app/models/doctor.rb +0 -12
  1151. data/spec/app/models/dog.rb +0 -7
  1152. data/spec/app/models/dokument.rb +0 -6
  1153. data/spec/app/models/draft.rb +0 -9
  1154. data/spec/app/models/dragon.rb +0 -4
  1155. data/spec/app/models/driver.rb +0 -7
  1156. data/spec/app/models/drug.rb +0 -6
  1157. data/spec/app/models/dungeon.rb +0 -4
  1158. data/spec/app/models/edit.rb +0 -5
  1159. data/spec/app/models/email.rb +0 -6
  1160. data/spec/app/models/employer.rb +0 -5
  1161. data/spec/app/models/entry.rb +0 -6
  1162. data/spec/app/models/eraser.rb +0 -1
  1163. data/spec/app/models/even.rb +0 -7
  1164. data/spec/app/models/event.rb +0 -22
  1165. data/spec/app/models/exhibition.rb +0 -4
  1166. data/spec/app/models/exhibitor.rb +0 -6
  1167. data/spec/app/models/explosion.rb +0 -4
  1168. data/spec/app/models/eye.rb +0 -9
  1169. data/spec/app/models/eye_bowl.rb +0 -9
  1170. data/spec/app/models/face.rb +0 -8
  1171. data/spec/app/models/favorite.rb +0 -6
  1172. data/spec/app/models/filesystem.rb +0 -5
  1173. data/spec/app/models/fire_hydrant.rb +0 -6
  1174. data/spec/app/models/firefox.rb +0 -4
  1175. data/spec/app/models/fish.rb +0 -7
  1176. data/spec/app/models/folder.rb +0 -7
  1177. data/spec/app/models/folder_item.rb +0 -9
  1178. data/spec/app/models/fruits.rb +0 -34
  1179. data/spec/app/models/game.rb +0 -19
  1180. data/spec/app/models/ghost.rb +0 -7
  1181. data/spec/app/models/home.rb +0 -4
  1182. data/spec/app/models/house.rb +0 -6
  1183. data/spec/app/models/html_writer.rb +0 -3
  1184. data/spec/app/models/id_key.rb +0 -6
  1185. data/spec/app/models/image.rb +0 -22
  1186. data/spec/app/models/implant.rb +0 -16
  1187. data/spec/app/models/item.rb +0 -8
  1188. data/spec/app/models/jar.rb +0 -7
  1189. data/spec/app/models/kaleidoscope.rb +0 -6
  1190. data/spec/app/models/kangaroo.rb +0 -4
  1191. data/spec/app/models/label.rb +0 -47
  1192. data/spec/app/models/language.rb +0 -5
  1193. data/spec/app/models/lat_lng.rb +0 -15
  1194. data/spec/app/models/league.rb +0 -11
  1195. data/spec/app/models/learner.rb +0 -2
  1196. data/spec/app/models/line_item.rb +0 -6
  1197. data/spec/app/models/location.rb +0 -8
  1198. data/spec/app/models/login.rb +0 -8
  1199. data/spec/app/models/manufacturer.rb +0 -7
  1200. data/spec/app/models/meat.rb +0 -4
  1201. data/spec/app/models/membership.rb +0 -4
  1202. data/spec/app/models/message.rb +0 -11
  1203. data/spec/app/models/mixed_drink.rb +0 -4
  1204. data/spec/app/models/movie.rb +0 -13
  1205. data/spec/app/models/my_hash.rb +0 -2
  1206. data/spec/app/models/name.rb +0 -24
  1207. data/spec/app/models/node.rb +0 -5
  1208. data/spec/app/models/note.rb +0 -17
  1209. data/spec/app/models/odd.rb +0 -7
  1210. data/spec/app/models/ordered_post.rb +0 -11
  1211. data/spec/app/models/ordered_preference.rb +0 -6
  1212. data/spec/app/models/oscar.rb +0 -14
  1213. data/spec/app/models/override.rb +0 -16
  1214. data/spec/app/models/ownable.rb +0 -6
  1215. data/spec/app/models/owner.rb +0 -6
  1216. data/spec/app/models/pack.rb +0 -3
  1217. data/spec/app/models/page.rb +0 -16
  1218. data/spec/app/models/page_question.rb +0 -4
  1219. data/spec/app/models/palette.rb +0 -7
  1220. data/spec/app/models/parent.rb +0 -5
  1221. data/spec/app/models/parent_doc.rb +0 -6
  1222. data/spec/app/models/passport.rb +0 -5
  1223. data/spec/app/models/patient.rb +0 -9
  1224. data/spec/app/models/pdf_writer.rb +0 -3
  1225. data/spec/app/models/pencil.rb +0 -1
  1226. data/spec/app/models/person.rb +0 -207
  1227. data/spec/app/models/pet.rb +0 -23
  1228. data/spec/app/models/pet_owner.rb +0 -6
  1229. data/spec/app/models/phone.rb +0 -9
  1230. data/spec/app/models/pizza.rb +0 -7
  1231. data/spec/app/models/player.rb +0 -35
  1232. data/spec/app/models/post.rb +0 -50
  1233. data/spec/app/models/post_genre.rb +0 -6
  1234. data/spec/app/models/powerup.rb +0 -11
  1235. data/spec/app/models/preference.rb +0 -9
  1236. data/spec/app/models/princess.rb +0 -10
  1237. data/spec/app/models/product.rb +0 -17
  1238. data/spec/app/models/profile.rb +0 -5
  1239. data/spec/app/models/pronunciation.rb +0 -5
  1240. data/spec/app/models/pub.rb +0 -6
  1241. data/spec/app/models/purchase.rb +0 -4
  1242. data/spec/app/models/question.rb +0 -8
  1243. data/spec/app/models/quiz.rb +0 -7
  1244. data/spec/app/models/rating.rb +0 -8
  1245. data/spec/app/models/record.rb +0 -52
  1246. data/spec/app/models/registry.rb +0 -4
  1247. data/spec/app/models/role.rb +0 -7
  1248. data/spec/app/models/root_category.rb +0 -4
  1249. data/spec/app/models/sandwich.rb +0 -9
  1250. data/spec/app/models/scheduler.rb +0 -7
  1251. data/spec/app/models/seo.rb +0 -7
  1252. data/spec/app/models/series.rb +0 -4
  1253. data/spec/app/models/server.rb +0 -13
  1254. data/spec/app/models/service.rb +0 -22
  1255. data/spec/app/models/shape.rb +0 -12
  1256. data/spec/app/models/shelf.rb +0 -5
  1257. data/spec/app/models/shipment_address.rb +0 -2
  1258. data/spec/app/models/shipping_container.rb +0 -5
  1259. data/spec/app/models/shipping_pack.rb +0 -3
  1260. data/spec/app/models/shop.rb +0 -6
  1261. data/spec/app/models/short_agent.rb +0 -4
  1262. data/spec/app/models/short_quiz.rb +0 -5
  1263. data/spec/app/models/simple.rb +0 -5
  1264. data/spec/app/models/slave.rb +0 -6
  1265. data/spec/app/models/song.rb +0 -8
  1266. data/spec/app/models/sound.rb +0 -5
  1267. data/spec/app/models/square.rb +0 -4
  1268. data/spec/app/models/staff.rb +0 -7
  1269. data/spec/app/models/store_as_dup_test1.rb +0 -5
  1270. data/spec/app/models/store_as_dup_test2.rb +0 -5
  1271. data/spec/app/models/strategy.rb +0 -3
  1272. data/spec/app/models/sub_item.rb +0 -3
  1273. data/spec/app/models/subscription.rb +0 -5
  1274. data/spec/app/models/survey.rb +0 -5
  1275. data/spec/app/models/symptom.rb +0 -6
  1276. data/spec/app/models/tag.rb +0 -8
  1277. data/spec/app/models/target.rb +0 -5
  1278. data/spec/app/models/template.rb +0 -5
  1279. data/spec/app/models/thing.rb +0 -9
  1280. data/spec/app/models/title.rb +0 -3
  1281. data/spec/app/models/tool.rb +0 -8
  1282. data/spec/app/models/topping.rb +0 -5
  1283. data/spec/app/models/track.rb +0 -38
  1284. data/spec/app/models/translation.rb +0 -5
  1285. data/spec/app/models/tree.rb +0 -9
  1286. data/spec/app/models/truck.rb +0 -3
  1287. data/spec/app/models/user.rb +0 -21
  1288. data/spec/app/models/user_account.rb +0 -10
  1289. data/spec/app/models/validation_callback.rb +0 -10
  1290. data/spec/app/models/vehicle.rb +0 -11
  1291. data/spec/app/models/version.rb +0 -5
  1292. data/spec/app/models/vet_visit.rb +0 -5
  1293. data/spec/app/models/video.rb +0 -13
  1294. data/spec/app/models/video_game.rb +0 -1
  1295. data/spec/app/models/weapon.rb +0 -11
  1296. data/spec/app/models/wiki_page.rb +0 -14
  1297. data/spec/app/models/word.rb +0 -15
  1298. data/spec/app/models/word_origin.rb +0 -11
  1299. data/spec/app/models/writer.rb +0 -11
  1300. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  1301. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  1302. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  1303. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1304. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1305. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1306. data/spec/mongoid/matchable/elem_match_spec.rb +0 -86
  1307. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1308. data/spec/mongoid/matchable/gt_spec.rb +0 -86
  1309. data/spec/mongoid/matchable/gte_spec.rb +0 -84
  1310. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1311. data/spec/mongoid/matchable/lt_spec.rb +0 -85
  1312. data/spec/mongoid/matchable/lte_spec.rb +0 -85
  1313. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1314. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1315. data/spec/mongoid/matchable/nor_spec.rb +0 -209
  1316. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1317. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1318. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1319. data/spec/mongoid/matchable_spec.rb +0 -853
  1320. data/spec/mongoid/relations/accessors_spec.rb +0 -821
  1321. data/spec/mongoid/relations/auto_save_spec.rb +0 -314
  1322. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +0 -171
  1323. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +0 -54
  1324. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +0 -77
  1325. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +0 -241
  1326. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +0 -153
  1327. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +0 -178
  1328. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +0 -131
  1329. data/spec/mongoid/relations/builders/embedded/in_spec.rb +0 -34
  1330. data/spec/mongoid/relations/builders/embedded/many_spec.rb +0 -132
  1331. data/spec/mongoid/relations/builders/embedded/one_spec.rb +0 -99
  1332. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +0 -233
  1333. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +0 -250
  1334. data/spec/mongoid/relations/builders/referenced/in_spec.rb +0 -230
  1335. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  1336. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  1337. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  1338. data/spec/mongoid/relations/builders_spec.rb +0 -253
  1339. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  1340. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  1341. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  1342. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  1343. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  1344. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  1345. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  1346. data/spec/mongoid/relations/counter_cache_spec.rb +0 -450
  1347. data/spec/mongoid/relations/cyclic_spec.rb +0 -178
  1348. data/spec/mongoid/relations/eager/belongs_to_spec.rb +0 -163
  1349. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +0 -133
  1350. data/spec/mongoid/relations/eager/has_many_spec.rb +0 -244
  1351. data/spec/mongoid/relations/eager/has_one_spec.rb +0 -163
  1352. data/spec/mongoid/relations/eager_spec.rb +0 -279
  1353. data/spec/mongoid/relations/embedded/dirty_spec.rb +0 -65
  1354. data/spec/mongoid/relations/embedded/in_spec.rb +0 -579
  1355. data/spec/mongoid/relations/embedded/many_spec.rb +0 -4412
  1356. data/spec/mongoid/relations/embedded/one_spec.rb +0 -1068
  1357. data/spec/mongoid/relations/macros_spec.rb +0 -1039
  1358. data/spec/mongoid/relations/metadata_spec.rb +0 -1985
  1359. data/spec/mongoid/relations/options_spec.rb +0 -35
  1360. data/spec/mongoid/relations/polymorphic_spec.rb +0 -128
  1361. data/spec/mongoid/relations/referenced/in_spec.rb +0 -1366
  1362. data/spec/mongoid/relations/referenced/many_spec.rb +0 -3816
  1363. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +0 -3577
  1364. data/spec/mongoid/relations/referenced/one_spec.rb +0 -1240
  1365. data/spec/mongoid/relations/reflections_spec.rb +0 -101
  1366. data/spec/mongoid/relations/synchronization_spec.rb +0 -495
  1367. data/spec/mongoid/relations/targets/enumerable_spec.rb +0 -1825
  1368. data/spec/mongoid/relations/touchable_spec.rb +0 -402
  1369. data/spec/mongoid/relations_spec.rb +0 -189
  1370. data/spec/support/cluster_config.rb +0 -158
  1371. data/spec/support/session_registry.rb +0 -50
  1372. /data/spec/{app → support}/models/array_field.rb +0 -0
@@ -0,0 +1,4112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Mongoid::Association::Referenced::HasMany::Proxy do
6
+
7
+ before :all do
8
+ Mongoid.raise_not_found_error = true
9
+
10
+ Drug.belongs_to :person, primary_key: :username
11
+ Person.has_many :drugs, validate: false, primary_key: :username
12
+ end
13
+
14
+ after :all do
15
+ Drug.belongs_to :person, counter_cache: true
16
+ Person.has_many :drugs, validate: false
17
+ end
18
+
19
+ [ :<<, :push ].each do |method|
20
+
21
+ describe "##{method}" do
22
+
23
+ context "when providing the base class in child constructor" do
24
+
25
+ let(:person) do
26
+ Person.create!
27
+ end
28
+
29
+ let!(:post) do
30
+ person.posts.send(method, Post.new(person: person))
31
+ end
32
+
33
+ it "only adds the association once" do
34
+ expect(person.posts.size).to eq(1)
35
+ end
36
+
37
+ it "only persists the association once" do
38
+ expect(person.reload.posts.size).to eq(1)
39
+ end
40
+ end
41
+
42
+ context "when the associations are not polymorphic" do
43
+
44
+ context "when the parent is a new record" do
45
+
46
+ let(:person) do
47
+ Person.new
48
+ end
49
+
50
+ context "when the child is new" do
51
+
52
+ let(:post) do
53
+ Post.new
54
+ end
55
+
56
+ let!(:added) do
57
+ person.posts.send(method, post)
58
+ end
59
+
60
+ it "sets the foreign key on the association" do
61
+ expect(post.person_id).to eq(person.id)
62
+ end
63
+
64
+ it "sets the base on the inverse association" do
65
+ expect(post.person).to eq(person)
66
+ end
67
+
68
+ it "sets the same instance on the inverse association" do
69
+ expect(post.person).to eql(person)
70
+ end
71
+
72
+ it "does not save the target" do
73
+ expect(post).to be_new_record
74
+ end
75
+
76
+ it "adds the document to the target" do
77
+ expect(person.posts.size).to eq(1)
78
+ end
79
+
80
+ it "returns the association" do
81
+ expect(added).to eq(person.posts)
82
+ end
83
+ end
84
+
85
+ context "when the child is persisted" do
86
+
87
+ let(:post) do
88
+ Post.create!
89
+ end
90
+
91
+ before do
92
+ person.posts.send(method, post)
93
+ end
94
+
95
+ it "sets the foreign key on the association" do
96
+ expect(post.person_id).to eq(person.id)
97
+ end
98
+
99
+ it "sets the base on the inverse association" do
100
+ expect(post.person).to eq(person)
101
+ end
102
+
103
+ it "sets the same instance on the inverse association" do
104
+ expect(post.person).to eql(person)
105
+ end
106
+
107
+ it "does not save the parent" do
108
+ expect(person).to be_new_record
109
+ end
110
+
111
+ it "adds the document to the target" do
112
+ expect(person.posts.size).to eq(1)
113
+ end
114
+
115
+ context "when subsequently saving the parent" do
116
+
117
+ before do
118
+ person.save!
119
+ post.save!
120
+ end
121
+
122
+ it "returns the correct count of the association" do
123
+ expect(person.posts.count).to eq(1)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ context "when appending in a parent create block" do
130
+
131
+ let!(:post) do
132
+ Post.create!(title: "testing")
133
+ end
134
+
135
+ let!(:person) do
136
+ Person.create! do |doc|
137
+ doc.posts << post
138
+ end
139
+ end
140
+
141
+ it "adds the documents to the association" do
142
+ expect(person.posts).to eq([ post ])
143
+ end
144
+
145
+ it "sets the foreign key on the inverse association" do
146
+ expect(post.person_id).to eq(person.id)
147
+ end
148
+
149
+ it "saves the target" do
150
+ expect(post).to be_persisted
151
+ end
152
+
153
+ it "adds the correct number of documents" do
154
+ expect(person.posts.size).to eq(1)
155
+ end
156
+
157
+ it "persists the link" do
158
+ expect(person.reload.posts).to eq([ post ])
159
+ end
160
+ end
161
+
162
+ context "when the parent is not a new record" do
163
+
164
+ let(:person) do
165
+ Person.create!
166
+ end
167
+
168
+ let(:post) do
169
+ Post.new
170
+ end
171
+
172
+ before do
173
+ person.posts.send(method, post)
174
+ end
175
+
176
+ it "sets the foreign key on the association" do
177
+ expect(post.person_id).to eq(person.id)
178
+ end
179
+
180
+ it "sets the base on the inverse association" do
181
+ expect(post.person).to eq(person)
182
+ end
183
+
184
+ it "sets the same instance on the inverse association" do
185
+ expect(post.person).to eql(person)
186
+ end
187
+
188
+ it "saves the target" do
189
+ expect(post).to be_persisted
190
+ end
191
+
192
+ it "adds the document to the target" do
193
+ expect(person.posts.count).to eq(1)
194
+ end
195
+
196
+ it "increments the counter cache" do
197
+ expect(person[:posts_count]).to eq(1)
198
+ expect(person.posts_count).to eq(1)
199
+ end
200
+
201
+ it "doesnt change the list of changes" do
202
+ expect(person.changed).to eq([])
203
+ end
204
+
205
+ context "when the related item has embedded associations" do
206
+
207
+ let!(:user) do
208
+ User.create!
209
+ end
210
+
211
+ before do
212
+ p = Post.create!(roles: [ Role.create! ])
213
+ user.posts = [ p ]
214
+ user.save!
215
+ end
216
+
217
+ it "add the document to the target" do
218
+ expect(user.posts.size).to eq(1)
219
+ expect(user.posts.first.roles.size).to eq(1)
220
+ end
221
+ end
222
+
223
+ context "when saving another post" do
224
+
225
+ before do
226
+ person.posts.send(method, Post.new)
227
+ end
228
+
229
+ it "increments the counter cache" do
230
+ expect(person.posts_count).to eq(2)
231
+ end
232
+ end
233
+
234
+ context "when documents already exist on the association" do
235
+
236
+ let(:post_two) do
237
+ Post.new(title: "Test")
238
+ end
239
+
240
+ before do
241
+ person.posts.send(method, post_two)
242
+ end
243
+
244
+ it "sets the foreign key on the association" do
245
+ expect(post_two.person_id).to eq(person.id)
246
+ end
247
+
248
+ it "sets the base on the inverse association" do
249
+ expect(post_two.person).to eq(person)
250
+ end
251
+
252
+ it "sets the same instance on the inverse association" do
253
+ expect(post_two.person).to eql(person)
254
+ end
255
+
256
+ it "saves the target" do
257
+ expect(post_two).to be_persisted
258
+ end
259
+
260
+ it "adds the document to the target" do
261
+ expect(person.posts.count).to eq(2)
262
+ end
263
+
264
+ it "increments the counter cache" do
265
+ expect(person.reload.posts_count).to eq(2)
266
+ end
267
+
268
+ it "contains the initial document in the target" do
269
+ expect(person.posts).to include(post)
270
+ end
271
+
272
+ it "contains the added document in the target" do
273
+ expect(person.posts).to include(post_two)
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ context "when.adding to the association" do
280
+
281
+ let(:person) do
282
+ Person.create!
283
+ end
284
+
285
+ context "when the operation succeeds" do
286
+
287
+ let(:post) do
288
+ Post.new
289
+ end
290
+
291
+ before do
292
+ person.posts.send(method, post)
293
+ end
294
+
295
+ it "adds the document to the association" do
296
+ expect(person.posts).to eq([ post ])
297
+ end
298
+ end
299
+
300
+ context "when the operation fails" do
301
+
302
+ let!(:existing) do
303
+ Post.create!
304
+ end
305
+
306
+ let(:post) do
307
+ Post.new do |doc|
308
+ doc._id = existing.id
309
+ end
310
+ end
311
+
312
+ it "raises an error" do
313
+ expect {
314
+ person.posts.send(method, post)
315
+ }.to raise_error(Mongo::Error::OperationFailure)
316
+ end
317
+ end
318
+ end
319
+
320
+ context "when the associations are polymorphic" do
321
+
322
+ context "when the parent is a new record" do
323
+
324
+ let(:movie) do
325
+ Movie.new
326
+ end
327
+
328
+ let(:rating) do
329
+ Rating.new
330
+ end
331
+
332
+ before do
333
+ movie.ratings.send(method, rating)
334
+ end
335
+
336
+ it "sets the foreign key on the association" do
337
+ expect(rating.ratable_id).to eq(movie.id)
338
+ end
339
+
340
+ it "sets the base on the inverse association" do
341
+ expect(rating.ratable).to eq(movie)
342
+ end
343
+
344
+ it "does not save the target" do
345
+ expect(rating).to be_new_record
346
+ end
347
+
348
+ it "adds the document to the target" do
349
+ expect(movie.ratings.size).to eq(1)
350
+ end
351
+ end
352
+
353
+ context "when the parent is not a new record" do
354
+
355
+ let(:movie) do
356
+ Movie.create!
357
+ end
358
+
359
+ let(:rating) do
360
+ Rating.new
361
+ end
362
+
363
+ before do
364
+ movie.ratings.send(method, rating)
365
+ end
366
+
367
+ it "sets the foreign key on the association" do
368
+ expect(rating.ratable_id).to eq(movie.id)
369
+ end
370
+
371
+ it "sets the base on the inverse association" do
372
+ expect(rating.ratable).to eq(movie)
373
+ end
374
+
375
+ it "saves the target" do
376
+ expect(rating).to be_persisted
377
+ end
378
+
379
+ it "adds the document to the target" do
380
+ expect(movie.ratings.count).to eq(1)
381
+ end
382
+ end
383
+ end
384
+ end
385
+ end
386
+
387
+ describe "#=" do
388
+
389
+ context "when the association is not polymorphic" do
390
+
391
+ context "when the parent is a new record" do
392
+
393
+ let(:person) do
394
+ Person.new
395
+ end
396
+
397
+ let(:post) do
398
+ Post.new
399
+ end
400
+
401
+ before do
402
+ person.posts = [ post ]
403
+ end
404
+
405
+ it "sets the target of the association" do
406
+ expect(person.posts._target).to eq([ post ])
407
+ end
408
+
409
+ it "sets the foreign key on the association" do
410
+ expect(post.person_id).to eq(person.id)
411
+ end
412
+
413
+ it "sets the base on the inverse association" do
414
+ expect(post.person).to eq(person)
415
+ end
416
+
417
+ it "does not save the target" do
418
+ expect(post).to_not be_persisted
419
+ end
420
+ end
421
+
422
+ context "when the parent is not a new record" do
423
+
424
+ let(:person) do
425
+ Person.create!
426
+ end
427
+
428
+ let(:post) do
429
+ Post.new
430
+ end
431
+
432
+ before do
433
+ person.posts = [ post ]
434
+ end
435
+
436
+ it "sets the target of the association" do
437
+ expect(person.posts._target).to eq([ post ])
438
+ end
439
+
440
+ it "sets the foreign key of the association" do
441
+ expect(post.person_id).to eq(person.id)
442
+ end
443
+
444
+ it "sets the base on the inverse association" do
445
+ expect(post.person).to eq(person)
446
+ end
447
+
448
+ it "saves the target" do
449
+ expect(post).to be_persisted
450
+ end
451
+
452
+ context "when replacing the association with the same documents" do
453
+
454
+ context "when using the same in memory instance" do
455
+
456
+ before do
457
+ person.posts = [ post ]
458
+ end
459
+
460
+ it "keeps the association intact" do
461
+ expect(person.posts).to eq([ post ])
462
+ end
463
+
464
+ it "does not delete the association" do
465
+ expect(person.reload.posts).to eq([ post ])
466
+ end
467
+ end
468
+
469
+ context "when using a new instance" do
470
+
471
+ let(:from_db) do
472
+ Person.find(person.id)
473
+ end
474
+
475
+ before do
476
+ from_db.posts = [ post ]
477
+ end
478
+
479
+ it "keeps the association intact" do
480
+ expect(from_db.posts).to eq([ post ])
481
+ end
482
+
483
+ it "does not delete the association" do
484
+ expect(from_db.reload.posts).to eq([ post ])
485
+ end
486
+ end
487
+ end
488
+
489
+ context "when replacing the with a combination of old and new docs" do
490
+
491
+ let(:new_post) do
492
+ Post.create!(title: "new post")
493
+ end
494
+
495
+ context "when using the same in memory instance" do
496
+
497
+ before do
498
+ person.posts = [ post, new_post ]
499
+ end
500
+
501
+ it "keeps the association intact" do
502
+ expect(person.posts.size).to eq(2)
503
+ end
504
+
505
+ it "keeps the first post" do
506
+ expect(person.posts).to include(post)
507
+ end
508
+
509
+ it "keeps the second post" do
510
+ expect(person.posts).to include(new_post)
511
+ end
512
+
513
+ it "does not delete the association" do
514
+ expect(person.reload.posts).to eq([ post, new_post ])
515
+ end
516
+ end
517
+
518
+ context "when using a new instance" do
519
+
520
+ let(:from_db) do
521
+ Person.find(person.id)
522
+ end
523
+
524
+ before do
525
+ from_db.posts = [ post, new_post ]
526
+ end
527
+
528
+ it "keeps the association intact" do
529
+ expect(from_db.posts).to eq([ post, new_post ])
530
+ end
531
+
532
+ it "does not delete the association" do
533
+ expect(from_db.reload.posts).to eq([ post, new_post ])
534
+ end
535
+ end
536
+ end
537
+
538
+ context "when replacing the with a combination of only new docs" do
539
+
540
+ let(:new_post) do
541
+ Post.create!(title: "new post")
542
+ end
543
+
544
+ context "when using the same in memory instance" do
545
+
546
+ before do
547
+ person.posts = [ new_post ]
548
+ end
549
+
550
+ it "keeps the association intact" do
551
+ expect(person.posts).to eq([ new_post ])
552
+ end
553
+
554
+ it "does not delete the association" do
555
+ expect(person.reload.posts).to eq([ new_post ])
556
+ end
557
+ end
558
+
559
+ context "when using a new instance" do
560
+
561
+ let(:from_db) do
562
+ Person.find(person.id)
563
+ end
564
+
565
+ before do
566
+ from_db.posts = [ new_post ]
567
+ end
568
+
569
+ it "keeps the association intact" do
570
+ expect(from_db.posts).to eq([ new_post ])
571
+ end
572
+
573
+ it "does not delete the association" do
574
+ expect(from_db.reload.posts).to eq([ new_post ])
575
+ end
576
+ end
577
+ end
578
+ end
579
+ end
580
+
581
+ context "when the association is polymorphic" do
582
+
583
+ context "when the parent is a new record" do
584
+
585
+ let(:movie) do
586
+ Movie.new
587
+ end
588
+
589
+ let(:rating) do
590
+ Rating.new
591
+ end
592
+
593
+ before do
594
+ movie.ratings = [ rating ]
595
+ end
596
+
597
+ it "sets the target of the association" do
598
+ expect(movie.ratings._target).to eq([ rating ])
599
+ end
600
+
601
+ it "sets the foreign key on the association" do
602
+ expect(rating.ratable_id).to eq(movie.id)
603
+ end
604
+
605
+ it "sets the base on the inverse association" do
606
+ expect(rating.ratable).to eq(movie)
607
+ end
608
+
609
+ it "does not save the target" do
610
+ expect(rating).to_not be_persisted
611
+ end
612
+ end
613
+
614
+ context "when the parent is not a new record" do
615
+
616
+ let(:movie) do
617
+ Movie.create!
618
+ end
619
+
620
+ let(:rating) do
621
+ Rating.new
622
+ end
623
+
624
+ before do
625
+ movie.ratings = [ rating ]
626
+ end
627
+
628
+ it "sets the target of the association" do
629
+ expect(movie.ratings._target).to eq([ rating ])
630
+ end
631
+
632
+ it "sets the foreign key of the association" do
633
+ expect(rating.ratable_id).to eq(movie.id)
634
+ end
635
+
636
+ it "sets the base on the inverse association" do
637
+ expect(rating.ratable).to eq(movie)
638
+ end
639
+
640
+ it "saves the target" do
641
+ expect(rating).to be_persisted
642
+ end
643
+ end
644
+ end
645
+ end
646
+
647
+ describe "#= []" do
648
+
649
+ context "when the parent is persisted" do
650
+
651
+ let(:posts) do
652
+ [ Post.create!(title: "1"), Post.create!(title: "2") ]
653
+ end
654
+
655
+ let(:person) do
656
+ Person.create!(posts: posts)
657
+ end
658
+
659
+ context "when the parent has multiple children" do
660
+
661
+ before do
662
+ person.posts = []
663
+ end
664
+
665
+ it "removes all the children" do
666
+ expect(person.posts).to be_empty
667
+ end
668
+
669
+ it "persists the changes" do
670
+ expect(person.posts(true)).to be_empty
671
+ end
672
+ end
673
+ end
674
+ end
675
+
676
+ describe "#= nil" do
677
+
678
+ context "when the association is not polymorphic" do
679
+
680
+ context "when the parent is a new record" do
681
+
682
+ let(:person) do
683
+ Person.new
684
+ end
685
+
686
+ let(:post) do
687
+ Post.new
688
+ end
689
+
690
+ before do
691
+ person.posts = [ post ]
692
+ person.posts = nil
693
+ end
694
+
695
+ it "sets the association to an empty array" do
696
+ expect(person.posts).to be_empty
697
+ end
698
+
699
+ it "removed the inverse association" do
700
+ expect(post.person).to be_nil
701
+ end
702
+
703
+ it "removes the foreign key value" do
704
+ expect(post.person_id).to be_nil
705
+ end
706
+ end
707
+
708
+ context "when the parent is not a new record" do
709
+
710
+ let(:person) do
711
+ Person.create!
712
+ end
713
+
714
+ context "when dependent is destructive" do
715
+
716
+ let(:post) do
717
+ Post.new
718
+ end
719
+
720
+ before do
721
+ person.posts = [ post ]
722
+ person.posts = nil
723
+ end
724
+
725
+ it "sets the association to empty" do
726
+ expect(person.posts).to be_empty
727
+ end
728
+
729
+ it "removed the inverse association" do
730
+ expect(post.person).to be_nil
731
+ end
732
+
733
+ it "removes the foreign key value" do
734
+ expect(post.person_id).to be_nil
735
+ end
736
+
737
+ it "deletes the target from the database" do
738
+ expect(post).to be_destroyed
739
+ end
740
+ end
741
+
742
+ context "when dependent is not destructive" do
743
+
744
+ let(:drug) do
745
+ Drug.new(name: "Oxycodone")
746
+ end
747
+
748
+ before do
749
+ person.drugs = [ drug ]
750
+ person.drugs = nil
751
+ end
752
+
753
+ it "sets the association to empty" do
754
+ expect(person.drugs).to be_empty
755
+ end
756
+
757
+ it "removed the inverse association" do
758
+ expect(drug.person).to be_nil
759
+ end
760
+
761
+ it "removes the foreign key value" do
762
+ expect(drug.person_id).to be_nil
763
+ end
764
+
765
+ it "nullifies the association" do
766
+ expect(drug).to_not be_destroyed
767
+ end
768
+ end
769
+ end
770
+ end
771
+
772
+ context "when the association is polymorphic" do
773
+
774
+ context "when the parent is a new record" do
775
+
776
+ let(:movie) do
777
+ Movie.new
778
+ end
779
+
780
+ let(:rating) do
781
+ Rating.new
782
+ end
783
+
784
+ before do
785
+ movie.ratings = [ rating ]
786
+ movie.ratings = nil
787
+ end
788
+
789
+ it "sets the association to an empty array" do
790
+ expect(movie.ratings).to be_empty
791
+ end
792
+
793
+ it "removed the inverse association" do
794
+ expect(rating.ratable).to be_nil
795
+ end
796
+
797
+ it "removes the foreign key value" do
798
+ expect(rating.ratable_id).to be_nil
799
+ end
800
+ end
801
+
802
+ context "when the parent is not a new record" do
803
+
804
+ let(:movie) do
805
+ Movie.create!
806
+ end
807
+
808
+ let(:rating) do
809
+ Rating.new
810
+ end
811
+
812
+ before do
813
+ movie.ratings = [ rating ]
814
+ movie.ratings = nil
815
+ end
816
+
817
+ it "sets the association to empty" do
818
+ expect(movie.ratings).to be_empty
819
+ end
820
+
821
+ it "removed the inverse association" do
822
+ expect(rating.ratable).to be_nil
823
+ end
824
+
825
+ it "removes the foreign key value" do
826
+ expect(rating.ratable_id).to be_nil
827
+ end
828
+
829
+ context "when dependent is nullify" do
830
+
831
+ it "does not delete the target from the database" do
832
+ expect(rating).to_not be_destroyed
833
+ end
834
+ end
835
+ end
836
+ end
837
+ end
838
+
839
+ describe "#\{name}_ids=" do
840
+
841
+ let(:person) do
842
+ Person.new
843
+ end
844
+
845
+ let(:post_one) do
846
+ Post.create!
847
+ end
848
+
849
+ let(:post_two) do
850
+ Post.create!
851
+ end
852
+
853
+ before do
854
+ person.post_ids = [ post_one.id, post_two.id ]
855
+ end
856
+
857
+ it "calls setter with documents find by given ids" do
858
+ expect(person.posts).to eq([ post_one, post_two ])
859
+ end
860
+ end
861
+
862
+ describe "#\{name}_ids" do
863
+
864
+ let(:posts) do
865
+ [ Post.create!, Post.create! ]
866
+ end
867
+
868
+ let(:person) do
869
+ Person.create!(posts: posts)
870
+ end
871
+
872
+ it "returns ids of documents that are in the association" do
873
+ expect(person.post_ids).to eq(posts.map(&:id))
874
+ end
875
+ end
876
+
877
+ [ :build, :new ].each do |method|
878
+
879
+ describe "##{method}" do
880
+
881
+ context "when the association is not polymorphic" do
882
+
883
+ context "when the parent is a new record" do
884
+
885
+ let(:person) do
886
+ Person.new(title: "sir")
887
+ end
888
+
889
+ let!(:post) do
890
+ person.posts.send(method, title: "$$$")
891
+ end
892
+
893
+ it "sets the foreign key on the association" do
894
+ expect(post.person_id).to eq(person.id)
895
+ end
896
+
897
+ it "sets the base on the inverse association" do
898
+ expect(post.person).to eq(person)
899
+ end
900
+
901
+ it "sets the attributes" do
902
+ expect(post.title).to eq("$$$")
903
+ end
904
+
905
+ it "sets the post processed defaults" do
906
+ expect(post.person_title).to eq(person.title)
907
+ end
908
+
909
+ it "does not save the target" do
910
+ expect(post).to be_new_record
911
+ end
912
+
913
+ it "adds the document to the target" do
914
+ expect(person.posts.size).to eq(1)
915
+ end
916
+
917
+ it "does not perform validation" do
918
+ expect(post.errors).to be_empty
919
+ end
920
+ end
921
+
922
+ context "when the parent is not a new record" do
923
+
924
+ let(:person) do
925
+ Person.create!
926
+ end
927
+
928
+ let!(:post) do
929
+ person.posts.send(method, text: "Testing")
930
+ end
931
+
932
+ it "sets the foreign key on the association" do
933
+ expect(post.person_id).to eq(person.id)
934
+ end
935
+
936
+ it "sets the base on the inverse association" do
937
+ expect(post.person).to eq(person)
938
+ end
939
+
940
+ it "sets the attributes" do
941
+ expect(post.text).to eq("Testing")
942
+ end
943
+
944
+ it "does not save the target" do
945
+ expect(post).to be_new_record
946
+ end
947
+
948
+ it "adds the document to the target" do
949
+ expect(person.posts.size).to eq(1)
950
+ end
951
+ end
952
+ end
953
+
954
+ context "when the association is polymorphic" do
955
+
956
+ context "when the parent is a subclass" do
957
+
958
+ let(:video_game) do
959
+ VideoGame.create!
960
+ end
961
+
962
+ let(:rating) do
963
+ video_game.ratings.build
964
+ end
965
+
966
+ it "sets the parent on the child" do
967
+ expect(rating.ratable).to eq(video_game)
968
+ end
969
+
970
+ it "sets the correct polymorphic type" do
971
+ expect(rating.ratable_type).to eq("VideoGame")
972
+ end
973
+ end
974
+
975
+ context "when the parent is a new record" do
976
+
977
+ let(:movie) do
978
+ Movie.new
979
+ end
980
+
981
+ let!(:rating) do
982
+ movie.ratings.send(method, value: 3)
983
+ end
984
+
985
+ it "sets the foreign key on the association" do
986
+ expect(rating.ratable_id).to eq(movie.id)
987
+ end
988
+
989
+ it "sets the base on the inverse association" do
990
+ expect(rating.ratable).to eq(movie)
991
+ end
992
+
993
+ it "sets the attributes" do
994
+ expect(rating.value).to eq(3)
995
+ end
996
+
997
+ it "does not save the target" do
998
+ expect(rating).to be_new_record
999
+ end
1000
+
1001
+ it "adds the document to the target" do
1002
+ expect(movie.ratings.size).to eq(1)
1003
+ end
1004
+
1005
+ it "does not perform validation" do
1006
+ expect(rating.errors).to be_empty
1007
+ end
1008
+ end
1009
+
1010
+ context "when the parent is not a new record" do
1011
+
1012
+ let(:movie) do
1013
+ Movie.create!
1014
+ end
1015
+
1016
+ let!(:rating) do
1017
+ movie.ratings.send(method, value: 4)
1018
+ end
1019
+
1020
+ it "sets the foreign key on the association" do
1021
+ expect(rating.ratable_id).to eq(movie.id)
1022
+ end
1023
+
1024
+ it "sets the base on the inverse association" do
1025
+ expect(rating.ratable).to eq(movie)
1026
+ end
1027
+
1028
+ it "sets the attributes" do
1029
+ expect(rating.value).to eq(4)
1030
+ end
1031
+
1032
+ it "does not save the target" do
1033
+ expect(rating).to be_new_record
1034
+ end
1035
+
1036
+ it "adds the document to the target" do
1037
+ expect(movie.ratings.size).to eq(1)
1038
+ end
1039
+ end
1040
+ end
1041
+ end
1042
+ end
1043
+
1044
+ describe "#clear" do
1045
+
1046
+ context "when the association is not polymorphic" do
1047
+
1048
+ context "when the parent has been persisted" do
1049
+
1050
+ let!(:person) do
1051
+ Person.create!
1052
+ end
1053
+
1054
+ context "when the children are persisted" do
1055
+
1056
+ let!(:post) do
1057
+ person.posts.create!(title: "Testing")
1058
+ end
1059
+
1060
+ let!(:association) do
1061
+ person.posts.clear
1062
+ end
1063
+
1064
+ it "clears out the association" do
1065
+ expect(person.posts).to be_empty
1066
+ end
1067
+
1068
+ it "marks the documents as deleted" do
1069
+ expect(post).to be_destroyed
1070
+ end
1071
+
1072
+ it "deletes the documents from the db" do
1073
+ expect(person.reload.posts).to be_empty
1074
+ end
1075
+
1076
+ it "returns the association" do
1077
+ expect(association).to be_empty
1078
+ end
1079
+ end
1080
+
1081
+ context "when the children are not persisted" do
1082
+
1083
+ let!(:post) do
1084
+ person.posts.build(title: "Testing")
1085
+ end
1086
+
1087
+ let!(:association) do
1088
+ person.posts.clear
1089
+ end
1090
+
1091
+ it "clears out the association" do
1092
+ expect(person.posts).to be_empty
1093
+ end
1094
+ end
1095
+ end
1096
+
1097
+ context "when the parent is not persisted" do
1098
+
1099
+ let(:person) do
1100
+ Person.new
1101
+ end
1102
+
1103
+ let!(:post) do
1104
+ person.posts.build(title: "Testing")
1105
+ end
1106
+
1107
+ let!(:association) do
1108
+ person.posts.clear
1109
+ end
1110
+
1111
+ it "clears out the association" do
1112
+ expect(person.posts).to be_empty
1113
+ end
1114
+ end
1115
+ end
1116
+
1117
+ context "when the association is polymorphic" do
1118
+
1119
+ context "when the parent has been persisted" do
1120
+
1121
+ let!(:movie) do
1122
+ Movie.create!
1123
+ end
1124
+
1125
+ context "when the children are persisted" do
1126
+
1127
+ let!(:rating) do
1128
+ movie.ratings.create!(value: 1)
1129
+ end
1130
+
1131
+ let!(:association) do
1132
+ movie.ratings.clear
1133
+ end
1134
+
1135
+ it "clears out the association" do
1136
+ expect(movie.ratings).to be_empty
1137
+ end
1138
+
1139
+ it "handles the proper dependent strategy" do
1140
+ expect(rating).to_not be_destroyed
1141
+ end
1142
+
1143
+ it "deletes the documents from the db" do
1144
+ expect(movie.reload.ratings).to be_empty
1145
+ end
1146
+
1147
+ it "returns the association" do
1148
+ expect(association).to be_empty
1149
+ end
1150
+ end
1151
+
1152
+ context "when the children are not persisted" do
1153
+
1154
+ let!(:rating) do
1155
+ movie.ratings.build(value: 3)
1156
+ end
1157
+
1158
+ let!(:association) do
1159
+ movie.ratings.clear
1160
+ end
1161
+
1162
+ it "clears out the association" do
1163
+ expect(movie.ratings).to be_empty
1164
+ end
1165
+ end
1166
+ end
1167
+
1168
+ context "when the parent is not persisted" do
1169
+
1170
+ let(:movie) do
1171
+ Movie.new
1172
+ end
1173
+
1174
+ let!(:rating) do
1175
+ movie.ratings.build(value: 2)
1176
+ end
1177
+
1178
+ let!(:association) do
1179
+ movie.ratings.clear
1180
+ end
1181
+
1182
+ it "clears out the association" do
1183
+ expect(movie.ratings).to be_empty
1184
+ end
1185
+ end
1186
+ end
1187
+ end
1188
+
1189
+ describe "#concat" do
1190
+
1191
+ context "when the associations are not polymorphic" do
1192
+
1193
+ context "when the parent is a new record" do
1194
+
1195
+ let(:person) do
1196
+ Person.new
1197
+ end
1198
+
1199
+ let(:post) do
1200
+ Post.new
1201
+ end
1202
+
1203
+ before do
1204
+ person.posts.concat([ post ])
1205
+ end
1206
+
1207
+ it "sets the foreign key on the association" do
1208
+ expect(post.person_id).to eq(person.id)
1209
+ end
1210
+
1211
+ it "sets the base on the inverse association" do
1212
+ expect(post.person).to eq(person)
1213
+ end
1214
+
1215
+ it "sets the same instance on the inverse association" do
1216
+ expect(post.person).to eql(person)
1217
+ end
1218
+
1219
+ it "does not save the target" do
1220
+ expect(post).to be_new_record
1221
+ end
1222
+
1223
+ it "adds the document to the target" do
1224
+ expect(person.posts.size).to eq(1)
1225
+ end
1226
+ end
1227
+
1228
+ context "when appending in a parent create block" do
1229
+
1230
+ let!(:post) do
1231
+ Post.create!(title: "testing")
1232
+ end
1233
+
1234
+ let!(:person) do
1235
+ Person.create! do |doc|
1236
+ doc.posts.concat([ post ])
1237
+ end
1238
+ end
1239
+
1240
+ it "adds the documents to the association" do
1241
+ expect(person.posts).to eq([ post ])
1242
+ end
1243
+
1244
+ it "sets the foreign key on the inverse association" do
1245
+ expect(post.person_id).to eq(person.id)
1246
+ end
1247
+
1248
+ it "saves the target" do
1249
+ expect(post).to be_persisted
1250
+ end
1251
+
1252
+ it "adds the correct number of documents" do
1253
+ expect(person.posts.size).to eq(1)
1254
+ end
1255
+
1256
+ it "persists the link" do
1257
+ expect(person.reload.posts).to eq([ post ])
1258
+ end
1259
+ end
1260
+
1261
+ context "when the parent is not a new record" do
1262
+
1263
+ let(:person) do
1264
+ Person.create!
1265
+ end
1266
+
1267
+ let(:post) do
1268
+ Post.new
1269
+ end
1270
+
1271
+ let(:post_three) do
1272
+ Post.new
1273
+ end
1274
+
1275
+ before do
1276
+ person.posts.concat([ post, post_three ])
1277
+ end
1278
+
1279
+ it "sets the foreign key on the association" do
1280
+ expect(post.person_id).to eq(person.id)
1281
+ end
1282
+
1283
+ it "sets the base on the inverse association" do
1284
+ expect(post.person).to eq(person)
1285
+ end
1286
+
1287
+ it "sets the same instance on the inverse association" do
1288
+ expect(post.person).to eql(person)
1289
+ end
1290
+
1291
+ it "saves the target" do
1292
+ expect(post).to be_persisted
1293
+ end
1294
+
1295
+ it "adds the document to the target" do
1296
+ expect(person.posts.count).to eq(2)
1297
+ end
1298
+
1299
+ context "when documents already exist on the association" do
1300
+
1301
+ let(:post_two) do
1302
+ Post.new(title: "Test")
1303
+ end
1304
+
1305
+ before do
1306
+ person.posts.concat([ post_two ])
1307
+ end
1308
+
1309
+ it "sets the foreign key on the association" do
1310
+ expect(post_two.person_id).to eq(person.id)
1311
+ end
1312
+
1313
+ it "sets the base on the inverse association" do
1314
+ expect(post_two.person).to eq(person)
1315
+ end
1316
+
1317
+ it "sets the same instance on the inverse association" do
1318
+ expect(post_two.person).to eql(person)
1319
+ end
1320
+
1321
+ it "saves the target" do
1322
+ expect(post_two).to be_persisted
1323
+ end
1324
+
1325
+ it "adds the document to the target" do
1326
+ expect(person.posts.count).to eq(3)
1327
+ end
1328
+
1329
+ it "contains the initial document in the target" do
1330
+ expect(person.posts).to include(post)
1331
+ end
1332
+
1333
+ it "contains the added document in the target" do
1334
+ expect(person.posts).to include(post_two)
1335
+ end
1336
+ end
1337
+ end
1338
+ end
1339
+ end
1340
+
1341
+ context "when the associations are polymorphic" do
1342
+
1343
+ context "when the parent is a new record" do
1344
+
1345
+ let(:movie) do
1346
+ Movie.new
1347
+ end
1348
+
1349
+ let(:rating) do
1350
+ Rating.new
1351
+ end
1352
+
1353
+ before do
1354
+ movie.ratings.concat([ rating ])
1355
+ end
1356
+
1357
+ it "sets the foreign key on the association" do
1358
+ expect(rating.ratable_id).to eq(movie.id)
1359
+ end
1360
+
1361
+ it "sets the base on the inverse association" do
1362
+ expect(rating.ratable).to eq(movie)
1363
+ end
1364
+
1365
+ it "does not save the target" do
1366
+ expect(rating).to be_new_record
1367
+ end
1368
+
1369
+ it "adds the document to the target" do
1370
+ expect(movie.ratings.size).to eq(1)
1371
+ end
1372
+ end
1373
+
1374
+ context "when the parent is not a new record" do
1375
+
1376
+ let(:movie) do
1377
+ Movie.create!
1378
+ end
1379
+
1380
+ let(:rating) do
1381
+ Rating.new
1382
+ end
1383
+
1384
+ before do
1385
+ movie.ratings.concat([ rating ])
1386
+ end
1387
+
1388
+ it "sets the foreign key on the association" do
1389
+ expect(rating.ratable_id).to eq(movie.id)
1390
+ end
1391
+
1392
+ it "sets the base on the inverse association" do
1393
+ expect(rating.ratable).to eq(movie)
1394
+ end
1395
+
1396
+ it "saves the target" do
1397
+ expect(rating).to be_persisted
1398
+ end
1399
+
1400
+ it "adds the document to the target" do
1401
+ expect(movie.ratings.count).to eq(1)
1402
+ end
1403
+ end
1404
+ end
1405
+
1406
+ describe "#count" do
1407
+
1408
+ let(:movie) do
1409
+ Movie.create!
1410
+ end
1411
+
1412
+ context "when documents have been persisted" do
1413
+
1414
+ let!(:rating) do
1415
+ movie.ratings.create!(value: 1)
1416
+ end
1417
+
1418
+ it "returns the number of persisted documents" do
1419
+ expect(movie.ratings.count).to eq(1)
1420
+ end
1421
+
1422
+ it "block form includes persisted results" do
1423
+ expect(movie.ratings.count {|r| r.value >= 1 }).to eq(1)
1424
+ expect(movie.ratings.count {|r| r.value >= 2 }).to eq(0)
1425
+ end
1426
+ end
1427
+
1428
+ context "when documents have not been persisted" do
1429
+
1430
+ let!(:rating) do
1431
+ movie.ratings.build(value: 1)
1432
+ end
1433
+
1434
+ it "returns 0" do
1435
+ expect(movie.ratings.count).to eq(0)
1436
+ end
1437
+
1438
+ it "block form does not include unpersisted results" do
1439
+ expect(movie.ratings.count {|r| r.value == 1 }).to eq(0)
1440
+ end
1441
+ end
1442
+
1443
+ context "when mixed persisted and unpersisted documents" do
1444
+
1445
+ before do
1446
+ movie.ratings.create(value: 1)
1447
+ movie.ratings.build(value: 2)
1448
+ end
1449
+
1450
+ it "returns 1" do
1451
+ expect(movie.ratings.count).to eq(1)
1452
+ end
1453
+
1454
+ it "block form includes only persisted results" do
1455
+ expect(movie.ratings.count {|r| r.value >= 1 }).to eq(1)
1456
+ expect(movie.ratings.count {|r| r.value == 2 }).to eq(0)
1457
+ end
1458
+ end
1459
+
1460
+ context "when no document is added" do
1461
+
1462
+ it "returns false" do
1463
+ expect(movie.ratings.any?).to be false
1464
+ end
1465
+ end
1466
+
1467
+ context "when new documents exist in the database" do
1468
+
1469
+ context "when the documents are part of the association" do
1470
+
1471
+ before do
1472
+ Rating.create!(ratable: movie)
1473
+ end
1474
+
1475
+ it "returns the count from the db" do
1476
+ expect(movie.ratings.count).to eq(1)
1477
+ end
1478
+ end
1479
+
1480
+ context "when the documents are not part of the association" do
1481
+
1482
+ before do
1483
+ Rating.create!
1484
+ end
1485
+
1486
+ it "returns the count from the db" do
1487
+ expect(movie.ratings.count).to eq(0)
1488
+ end
1489
+ end
1490
+ end
1491
+ end
1492
+
1493
+ describe "#any?" do
1494
+
1495
+ shared_examples 'does not query database when association is loaded' do
1496
+
1497
+ let(:fresh_movie) { Movie.find(movie.id) }
1498
+
1499
+ context 'when association is not loaded' do
1500
+ it 'queries database on each call' do
1501
+ fresh_movie
1502
+
1503
+ expect_query(1) do
1504
+ fresh_movie.ratings.any?.should be expected_result
1505
+ end
1506
+
1507
+ expect_query(1) do
1508
+ fresh_movie.ratings.any?.should be expected_result
1509
+ end
1510
+ end
1511
+
1512
+ context 'when using a block' do
1513
+ it 'queries database on first call only' do
1514
+ fresh_movie
1515
+
1516
+ expect_query(1) do
1517
+ fresh_movie.ratings.any? { false }.should be false
1518
+ end
1519
+
1520
+ expect_no_queries do
1521
+ fresh_movie.ratings.any? { false }.should be false
1522
+ end
1523
+ end
1524
+ end
1525
+ end
1526
+
1527
+ context 'when association is loaded' do
1528
+ it 'does not query database' do
1529
+ fresh_movie
1530
+
1531
+ expect_query(1) do
1532
+ fresh_movie.ratings.any?.should be expected_result
1533
+ end
1534
+
1535
+ fresh_movie.ratings.to_a
1536
+
1537
+ expect_no_queries do
1538
+ fresh_movie.ratings.any?.should be expected_result
1539
+ end
1540
+ end
1541
+ end
1542
+ end
1543
+
1544
+ let(:movie) do
1545
+ Movie.create!
1546
+ end
1547
+
1548
+ context "when nothing exists on the association" do
1549
+
1550
+ context "when no document is added" do
1551
+
1552
+ let!(:movie) do
1553
+ Movie.create!
1554
+ end
1555
+
1556
+ it "returns false" do
1557
+ expect(movie.ratings.any?).to be false
1558
+ end
1559
+
1560
+ let(:expected_result) { false }
1561
+ include_examples 'does not query database when association is loaded'
1562
+ end
1563
+
1564
+ context "when the document is destroyed" do
1565
+
1566
+ before do
1567
+ Rating.create!
1568
+ end
1569
+
1570
+ let!(:movie) do
1571
+ Movie.create!
1572
+ end
1573
+
1574
+ it "returns false" do
1575
+ movie.destroy
1576
+ expect(movie.ratings.any?).to be false
1577
+ end
1578
+ end
1579
+ end
1580
+
1581
+ context "when appending to a association and _loaded/_unloaded are empty" do
1582
+
1583
+ let!(:movie) do
1584
+ Movie.create!
1585
+ end
1586
+
1587
+ before do
1588
+ movie.ratings << Rating.new
1589
+ end
1590
+
1591
+ it "returns true" do
1592
+ expect(movie.ratings.any?).to be true
1593
+ end
1594
+
1595
+ context 'when association is not loaded' do
1596
+ before do
1597
+ movie.ratings._loaded?.should be false
1598
+ end
1599
+
1600
+ it 'does not query the database because it knows about the added models' do
1601
+ expect_no_queries do
1602
+ movie.ratings.any?.should be true
1603
+ end
1604
+ end
1605
+ end
1606
+
1607
+ context 'when association is loaded' do
1608
+ it 'does not query database' do
1609
+ expect_no_queries do
1610
+ movie.ratings.any?.should be true
1611
+ end
1612
+
1613
+ movie.ratings.to_a
1614
+
1615
+ expect_no_queries do
1616
+ movie.ratings.any?.should be true
1617
+ end
1618
+ end
1619
+ end
1620
+ end
1621
+
1622
+ context "when appending to a association in a transaction" do
1623
+ require_transaction_support
1624
+
1625
+ let!(:movie) do
1626
+ Movie.create!
1627
+ end
1628
+
1629
+ it "returns true" do
1630
+ movie.with_session do |session|
1631
+ session.with_transaction do
1632
+ expect{ movie.ratings << Rating.new }.to_not raise_error
1633
+ expect(movie.ratings.any?).to be true
1634
+ end
1635
+ end
1636
+ end
1637
+ end
1638
+
1639
+ context "when documents have been persisted" do
1640
+
1641
+ let!(:rating) do
1642
+ movie.ratings.create!(value: 1)
1643
+ end
1644
+
1645
+ it "returns true" do
1646
+ expect(movie.ratings.any?).to be true
1647
+ end
1648
+
1649
+ let(:expected_result) { true }
1650
+ include_examples 'does not query database when association is loaded'
1651
+ end
1652
+
1653
+ context "when documents have not been persisted" do
1654
+
1655
+ let!(:rating) do
1656
+ movie.ratings.build(value: 1)
1657
+ end
1658
+
1659
+ it "returns false" do
1660
+ expect(movie.ratings.any?).to be true
1661
+ end
1662
+ end
1663
+
1664
+ context "when new documents exist in the database" do
1665
+ before do
1666
+ Rating.create!(ratable: movie)
1667
+ end
1668
+
1669
+ it "returns true" do
1670
+ expect(movie.ratings.any?).to be true
1671
+ end
1672
+ end
1673
+ end
1674
+
1675
+ describe "#create" do
1676
+
1677
+ context "when providing multiple attributes" do
1678
+
1679
+ let(:person) do
1680
+ Person.create!
1681
+ end
1682
+
1683
+ let!(:posts) do
1684
+ person.posts.create!([{ text: "Test1" }, { text: "Test2" }])
1685
+ end
1686
+
1687
+ it "creates multiple documents" do
1688
+ expect(posts.size).to eq(2)
1689
+ end
1690
+
1691
+ it "sets the first attributes" do
1692
+ expect(posts.first.text).to eq("Test1")
1693
+ end
1694
+
1695
+ it "sets the second attributes" do
1696
+ expect(posts.last.text).to eq("Test2")
1697
+ end
1698
+
1699
+ it "persists the children" do
1700
+ expect(person.posts.count).to eq(2)
1701
+ end
1702
+ end
1703
+
1704
+ context "when the association is not polymorphic" do
1705
+
1706
+ context "when the parent is a new record" do
1707
+
1708
+ let(:person) do
1709
+ Person.new
1710
+ end
1711
+
1712
+ let(:post) do
1713
+ person.posts.create!(text: "Testing")
1714
+ end
1715
+
1716
+ it "raises an unsaved document error" do
1717
+ expect { post }.to raise_error(Mongoid::Errors::UnsavedDocument)
1718
+ end
1719
+ end
1720
+
1721
+ context "when.creating the document" do
1722
+
1723
+ context "when the operation is successful" do
1724
+
1725
+ let(:person) do
1726
+ Person.create!
1727
+ end
1728
+
1729
+ let!(:post) do
1730
+ person.posts.create!(text: "Testing")
1731
+ end
1732
+
1733
+ it "creates the document" do
1734
+ expect(person.posts).to eq([ post ])
1735
+ end
1736
+ end
1737
+
1738
+ context "when the operation fails" do
1739
+
1740
+ let(:person) do
1741
+ Person.create!
1742
+ end
1743
+
1744
+ let!(:existing) do
1745
+ Post.create!
1746
+ end
1747
+
1748
+ it "raises an error" do
1749
+ expect {
1750
+ person.posts.create! do |doc|
1751
+ doc._id = existing.id
1752
+ end
1753
+ }.to raise_error(Mongo::Error::OperationFailure)
1754
+ end
1755
+ end
1756
+ end
1757
+
1758
+ context "when the parent is not a new record" do
1759
+
1760
+ let(:person) do
1761
+ Person.create!
1762
+ end
1763
+
1764
+ let!(:post) do
1765
+ person.posts.create!(text: "Testing") do |post|
1766
+ post.content = "The Content"
1767
+ end
1768
+ end
1769
+
1770
+ it "sets the foreign key on the association" do
1771
+ expect(post.person_id).to eq(person.id)
1772
+ end
1773
+
1774
+ it "sets the base on the inverse association" do
1775
+ expect(post.person).to eq(person)
1776
+ end
1777
+
1778
+ it "sets the attributes" do
1779
+ expect(post.text).to eq("Testing")
1780
+ end
1781
+
1782
+ it "saves the target" do
1783
+ expect(post).to_not be_a_new_record
1784
+ end
1785
+
1786
+ it "calls the passed block" do
1787
+ expect(post.content).to eq("The Content")
1788
+ end
1789
+
1790
+ it "adds the document to the target" do
1791
+ expect(person.posts.count).to eq(1)
1792
+ end
1793
+ end
1794
+
1795
+ context "when passing a new object" do
1796
+
1797
+ let!(:odd) do
1798
+ Odd.create!(name: 'one')
1799
+ end
1800
+
1801
+ let!(:even) do
1802
+ odd.evens.create!(name: 'two', odds: [Odd.new(name: 'three')])
1803
+ end
1804
+
1805
+ it "only push one even to the list" do
1806
+ expect(odd.evens.count).to eq(1)
1807
+ end
1808
+
1809
+ it "saves the reference back" do
1810
+ expect(odd.evens.first.odds.count).to eq(1)
1811
+ end
1812
+
1813
+ it "only saves one even" do
1814
+ expect(Even.count).to eq(1)
1815
+ end
1816
+
1817
+ it "saves the first odd and the second" do
1818
+ expect(Odd.count).to eq(2)
1819
+ end
1820
+ end
1821
+ end
1822
+
1823
+ context "when the association is polymorphic" do
1824
+
1825
+ context "when the parent is a new record" do
1826
+
1827
+ let(:movie) do
1828
+ Movie.new
1829
+ end
1830
+
1831
+ let(:rating) do
1832
+ movie.ratings.create!(value: 1)
1833
+ end
1834
+
1835
+ it "raises an unsaved document error" do
1836
+ expect { rating }.to raise_error(Mongoid::Errors::UnsavedDocument)
1837
+ end
1838
+ end
1839
+
1840
+ context "when the parent is not a new record" do
1841
+
1842
+ let(:movie) do
1843
+ Movie.create!
1844
+ end
1845
+
1846
+ let!(:rating) do
1847
+ movie.ratings.create!(value: 3)
1848
+ end
1849
+
1850
+ it "sets the foreign key on the association" do
1851
+ expect(rating.ratable_id).to eq(movie.id)
1852
+ end
1853
+
1854
+ it "sets the base on the inverse association" do
1855
+ expect(rating.ratable).to eq(movie)
1856
+ end
1857
+
1858
+ it "sets the attributes" do
1859
+ expect(rating.value).to eq(3)
1860
+ end
1861
+
1862
+ it "saves the target" do
1863
+ expect(rating).to_not be_new_record
1864
+ end
1865
+
1866
+ it "adds the document to the target" do
1867
+ expect(movie.ratings.count).to eq(1)
1868
+ end
1869
+ end
1870
+ end
1871
+
1872
+ context "when using a different primary_key" do
1873
+
1874
+ let(:person) do
1875
+ Person.create!(username: 'arthurnn')
1876
+ end
1877
+
1878
+ let(:drug) do
1879
+ person.drugs.create!
1880
+ end
1881
+
1882
+ it 'saves pk value on fk field' do
1883
+ expect(drug.person_id).to eq('arthurnn')
1884
+ end
1885
+ end
1886
+ end
1887
+
1888
+ describe "#create!" do
1889
+
1890
+ context "when providing multiple attributes" do
1891
+
1892
+ let(:person) do
1893
+ Person.create!
1894
+ end
1895
+
1896
+ let!(:posts) do
1897
+ person.posts.create!([{ text: "Test1" }, { text: "Test2" }])
1898
+ end
1899
+
1900
+ it "creates multiple documents" do
1901
+ expect(posts.size).to eq(2)
1902
+ end
1903
+
1904
+ it "sets the first attributes" do
1905
+ expect(posts.first.text).to eq("Test1")
1906
+ end
1907
+
1908
+ it "sets the second attributes" do
1909
+ expect(posts.last.text).to eq("Test2")
1910
+ end
1911
+
1912
+ it "persists the children" do
1913
+ expect(person.posts.count).to eq(2)
1914
+ end
1915
+ end
1916
+
1917
+ context "when the association is not polymorphic" do
1918
+
1919
+ context "when the parent is a new record" do
1920
+
1921
+ let(:person) do
1922
+ Person.new
1923
+ end
1924
+
1925
+ let(:post) do
1926
+ person.posts.create!(title: "Testing")
1927
+ end
1928
+
1929
+ it "raises an unsaved document error" do
1930
+ expect { post }.to raise_error(Mongoid::Errors::UnsavedDocument)
1931
+ end
1932
+ end
1933
+
1934
+ context "when the parent is not a new record" do
1935
+
1936
+ let(:person) do
1937
+ Person.create!
1938
+ end
1939
+
1940
+ let!(:post) do
1941
+ person.posts.create!(title: "Testing")
1942
+ end
1943
+
1944
+ it "sets the foreign key on the association" do
1945
+ expect(post.person_id).to eq(person.id)
1946
+ end
1947
+
1948
+ it "sets the base on the inverse association" do
1949
+ expect(post.person).to eq(person)
1950
+ end
1951
+
1952
+ it "sets the attributes" do
1953
+ expect(post.title).to eq("Testing")
1954
+ end
1955
+
1956
+ it "saves the target" do
1957
+ expect(post).to_not be_a_new_record
1958
+ end
1959
+
1960
+ it "adds the document to the target" do
1961
+ expect(person.posts.count).to eq(1)
1962
+ end
1963
+
1964
+ context "when validation fails" do
1965
+
1966
+ it "raises an error" do
1967
+ expect {
1968
+ person.posts.create!(title: "$$$")
1969
+ }.to raise_error(Mongoid::Errors::Validations)
1970
+ end
1971
+ end
1972
+ end
1973
+ end
1974
+
1975
+ context "when the association is polymorphic" do
1976
+
1977
+ context "when the parent is a new record" do
1978
+
1979
+ let(:movie) do
1980
+ Movie.new
1981
+ end
1982
+
1983
+ let(:rating) do
1984
+ movie.ratings.create!(value: 1)
1985
+ end
1986
+
1987
+ it "raises an unsaved document error" do
1988
+ expect { rating }.to raise_error(Mongoid::Errors::UnsavedDocument)
1989
+ end
1990
+ end
1991
+
1992
+ context "when the parent is not a new record" do
1993
+
1994
+ let(:movie) do
1995
+ Movie.create!
1996
+ end
1997
+
1998
+ let!(:rating) do
1999
+ movie.ratings.create!(value: 4)
2000
+ end
2001
+
2002
+ it "sets the foreign key on the association" do
2003
+ expect(rating.ratable_id).to eq(movie.id)
2004
+ end
2005
+
2006
+ it "sets the base on the inverse association" do
2007
+ expect(rating.ratable).to eq(movie)
2008
+ end
2009
+
2010
+ it "sets the attributes" do
2011
+ expect(rating.value).to eq(4)
2012
+ end
2013
+
2014
+ it "saves the target" do
2015
+ expect(rating).to_not be_new_record
2016
+ end
2017
+
2018
+ it "adds the document to the target" do
2019
+ expect(movie.ratings.count).to eq(1)
2020
+ end
2021
+
2022
+ context "when validation fails" do
2023
+
2024
+ it "raises an error" do
2025
+ expect {
2026
+ movie.ratings.create!(value: 1000)
2027
+ }.to raise_error(Mongoid::Errors::Validations)
2028
+ end
2029
+ end
2030
+ end
2031
+ end
2032
+ end
2033
+
2034
+ describe "#criteria" do
2035
+
2036
+ let(:base) do
2037
+ Movie.new
2038
+ end
2039
+
2040
+ context "when the association is polymorphic" do
2041
+
2042
+ let(:association) do
2043
+ Movie.relations["ratings"]
2044
+ end
2045
+
2046
+ let(:criteria) do
2047
+ association.criteria(base)
2048
+ end
2049
+
2050
+ it "includes the type in the criteria" do
2051
+ expect(criteria.selector).to eq(
2052
+ {
2053
+ "ratable_id" => base.id,
2054
+ "ratable_type" => "Movie"
2055
+ }
2056
+ )
2057
+ end
2058
+ end
2059
+
2060
+ context "when the association is not polymorphic" do
2061
+
2062
+ let(:association) do
2063
+ Person.relations["posts"]
2064
+ end
2065
+
2066
+ let(:base) do
2067
+ Person.new
2068
+ end
2069
+
2070
+ let(:criteria) do
2071
+ association.criteria(base)
2072
+ end
2073
+
2074
+ it "does not include the type in the criteria" do
2075
+ expect(criteria.selector).to eq({ "person_id" => base.id })
2076
+ end
2077
+ end
2078
+ end
2079
+
2080
+ describe "#delete" do
2081
+
2082
+ let!(:person) do
2083
+ Person.create!(username: 'arthurnn')
2084
+ end
2085
+
2086
+ context "when the document is found" do
2087
+
2088
+ context "when no dependent option is set" do
2089
+
2090
+ context "when we are assigning attributes" do
2091
+
2092
+ let!(:drug) do
2093
+ person.drugs.create!
2094
+ end
2095
+
2096
+ before do
2097
+ Mongoid::Threaded.begin_execution(:assign)
2098
+ end
2099
+
2100
+ after do
2101
+ Mongoid::Threaded.exit_execution(:assign)
2102
+ end
2103
+
2104
+ let(:deleted) do
2105
+ person.drugs.delete(drug)
2106
+ end
2107
+
2108
+ it "does not cascade" do
2109
+ expect(deleted.changes.keys).to eq([ "person_id" ])
2110
+ end
2111
+ end
2112
+
2113
+ context "when the document is loaded" do
2114
+
2115
+ let!(:drug) do
2116
+ person.drugs.create!
2117
+ end
2118
+
2119
+ let!(:deleted) do
2120
+ person.drugs.delete(drug)
2121
+ end
2122
+
2123
+ it "returns the document" do
2124
+ expect(deleted).to eq(drug)
2125
+ end
2126
+
2127
+ it "deletes the foreign key" do
2128
+ expect(drug.person_id).to be_nil
2129
+ end
2130
+
2131
+ it "removes the document from the association" do
2132
+ expect(person.drugs).to_not include(drug)
2133
+ end
2134
+ end
2135
+
2136
+ context "when the document is not loaded" do
2137
+
2138
+ let!(:drug) do
2139
+ Drug.create!(person_id: person.username)
2140
+ end
2141
+
2142
+ let!(:deleted) do
2143
+ person.drugs.delete(drug)
2144
+ end
2145
+
2146
+ it "returns the document" do
2147
+ expect(deleted).to eq(drug)
2148
+ end
2149
+
2150
+ it "deletes the foreign key" do
2151
+ expect(drug.person_id).to be_nil
2152
+ end
2153
+
2154
+ it "removes the document from the association" do
2155
+ expect(person.drugs).to_not include(drug)
2156
+ end
2157
+ end
2158
+ end
2159
+
2160
+ context "when dependent is delete" do
2161
+
2162
+ context "when the document is loaded" do
2163
+
2164
+ let!(:post) do
2165
+ person.posts.create!(title: "test")
2166
+ end
2167
+
2168
+ let!(:deleted) do
2169
+ person.posts.delete(post)
2170
+ end
2171
+
2172
+ it "returns the document" do
2173
+ expect(deleted).to eq(post)
2174
+ end
2175
+
2176
+ it "deletes the document" do
2177
+ expect(post).to be_destroyed
2178
+ end
2179
+
2180
+ it "removes the document from the association" do
2181
+ expect(person.posts).to_not include(post)
2182
+ end
2183
+ end
2184
+
2185
+ context "when the document is not loaded" do
2186
+
2187
+ let!(:post) do
2188
+ Post.create!(title: "foo", person_id: person.id)
2189
+ end
2190
+
2191
+ let!(:deleted) do
2192
+ person.posts.delete(post)
2193
+ end
2194
+
2195
+ it "returns the document" do
2196
+ expect(deleted).to eq(post)
2197
+ end
2198
+
2199
+ it "deletes the document" do
2200
+ expect(post).to be_destroyed
2201
+ end
2202
+
2203
+ it "removes the document from the association" do
2204
+ expect(person.posts).to_not include(post)
2205
+ end
2206
+ end
2207
+ end
2208
+ end
2209
+
2210
+ context "when the document is not found" do
2211
+
2212
+ let!(:post) do
2213
+ Post.create!(title: "foo")
2214
+ end
2215
+
2216
+ let!(:deleted) do
2217
+ person.posts.delete(post)
2218
+ end
2219
+
2220
+ it "returns nil" do
2221
+ expect(deleted).to be_nil
2222
+ end
2223
+
2224
+ it "does not delete the document" do
2225
+ expect(post).to be_persisted
2226
+ end
2227
+ end
2228
+ end
2229
+
2230
+ [ :delete_all, :destroy_all ].each do |method|
2231
+
2232
+ describe "##{method}" do
2233
+
2234
+ context "when the association is not polymorphic" do
2235
+
2236
+ context "when conditions are provided" do
2237
+
2238
+ let(:person) do
2239
+ Person.create!(username: 'durran')
2240
+ end
2241
+
2242
+ before do
2243
+ person.posts.create!(title: "Testing")
2244
+ person.posts.create!(title: "Test")
2245
+ end
2246
+
2247
+ it "removes the correct posts" do
2248
+ person.posts.send(method, { title: "Testing" })
2249
+ expect(person.posts.count).to eq(1)
2250
+ expect(person.reload.posts_count).to eq(1) if method == :destroy_all
2251
+ end
2252
+
2253
+ it "deletes the documents from the database" do
2254
+ person.posts.send(method, { title: "Testing" })
2255
+ expect(Post.where(title: "Testing").count).to eq(0)
2256
+ end
2257
+
2258
+ it "returns the number of documents deleted" do
2259
+ expect(person.posts.send(method, { title: "Testing" })).to eq(1)
2260
+ end
2261
+ end
2262
+
2263
+ context "when conditions are not provided" do
2264
+
2265
+ let(:person) do
2266
+ Person.create!
2267
+ end
2268
+
2269
+ before do
2270
+ person.posts.create!(title: "Testing")
2271
+ person.posts.create!(title: "Test")
2272
+ end
2273
+
2274
+ it "removes the correct posts" do
2275
+ person.posts.send(method)
2276
+ expect(person.posts.count).to eq(0)
2277
+ end
2278
+
2279
+ it "deletes the documents from the database" do
2280
+ person.posts.send(method)
2281
+ expect(Post.where(title: "Testing").count).to eq(0)
2282
+ end
2283
+
2284
+ it "returns the number of documents deleted" do
2285
+ expect(person.posts.send(method)).to eq(2)
2286
+ end
2287
+ end
2288
+ end
2289
+
2290
+ context "when the association is polymorphic" do
2291
+
2292
+ context "when conditions are provided" do
2293
+
2294
+ let(:movie) do
2295
+ Movie.create!(title: "Bladerunner")
2296
+ end
2297
+
2298
+ before do
2299
+ movie.ratings.create!(value: 1)
2300
+ movie.ratings.create!(value: 2)
2301
+ end
2302
+
2303
+ it "removes the correct ratings" do
2304
+ movie.ratings.send(method, { value: 1 })
2305
+ expect(movie.ratings.count).to eq(1)
2306
+ end
2307
+
2308
+ it "deletes the documents from the database" do
2309
+ movie.ratings.send(method, { value: 1 })
2310
+ expect(Rating.where(value: 1).count).to eq(0)
2311
+ end
2312
+
2313
+ it "returns the number of documents deleted" do
2314
+ expect(movie.ratings.send(method, { value: 1 })).to eq(1)
2315
+ end
2316
+ end
2317
+
2318
+ context "when conditions are not provided" do
2319
+
2320
+ let(:movie) do
2321
+ Movie.create!(title: "Bladerunner")
2322
+ end
2323
+
2324
+ before do
2325
+ movie.ratings.create!(value: 1)
2326
+ movie.ratings.create!(value: 2)
2327
+ end
2328
+
2329
+ it "removes the correct ratings" do
2330
+ movie.ratings.send(method)
2331
+ expect(movie.ratings.count).to eq(0)
2332
+ end
2333
+
2334
+ it "deletes the documents from the database" do
2335
+ movie.ratings.send(method)
2336
+ expect(Rating.where(value: 1).count).to eq(0)
2337
+ end
2338
+
2339
+ it "returns the number of documents deleted" do
2340
+ expect(movie.ratings.send(method)).to eq(2)
2341
+ end
2342
+ end
2343
+ end
2344
+ end
2345
+ end
2346
+
2347
+ describe ".embedded?" do
2348
+
2349
+ it "returns false" do
2350
+ expect(described_class).to_not be_embedded
2351
+ end
2352
+ end
2353
+
2354
+ describe "#exists?" do
2355
+
2356
+ let!(:person) do
2357
+ Person.create!
2358
+ end
2359
+
2360
+ context "when documents exist in the database" do
2361
+
2362
+ before do
2363
+ person.posts.create!
2364
+ end
2365
+
2366
+ it "returns true" do
2367
+ expect(person.posts.exists?).to be true
2368
+ end
2369
+
2370
+ context 'when association is not loaded' do
2371
+ it 'queries database on each call' do
2372
+ expect_query(1) do
2373
+ person.posts.exists?.should be true
2374
+ end
2375
+
2376
+ expect_query(1) do
2377
+ person.posts.exists?.should be true
2378
+ end
2379
+ end
2380
+ end
2381
+
2382
+ context 'when association is loaded' do
2383
+ it 'queries database on each call' do
2384
+ expect_query(1) do
2385
+ person.posts.exists?.should be true
2386
+ end
2387
+
2388
+ person.posts.to_a
2389
+
2390
+ expect_query(1) do
2391
+ person.posts.exists?.should be true
2392
+ end
2393
+ end
2394
+ end
2395
+ end
2396
+
2397
+ context "when documents exist in application but not in database" do
2398
+
2399
+ before do
2400
+ person.posts.build
2401
+ end
2402
+
2403
+ it "returns false" do
2404
+ expect(person.posts.exists?).to be false
2405
+ end
2406
+
2407
+ context 'when association is not loaded' do
2408
+ it 'queries database on each call' do
2409
+ expect_query(1) do
2410
+ person.posts.exists?.should be false
2411
+ end
2412
+
2413
+ expect_query(1) do
2414
+ person.posts.exists?.should be false
2415
+ end
2416
+ end
2417
+ end
2418
+
2419
+ context 'when association is loaded' do
2420
+ it 'queries database on each call' do
2421
+ expect_query(1) do
2422
+ person.posts.exists?.should be false
2423
+ end
2424
+
2425
+ person.posts.to_a
2426
+
2427
+ expect_query(1) do
2428
+ person.posts.exists?.should be false
2429
+ end
2430
+ end
2431
+ end
2432
+ end
2433
+
2434
+ context "when no documents exist" do
2435
+
2436
+ it "returns false" do
2437
+ expect(person.posts.exists?).to be false
2438
+ end
2439
+
2440
+ context 'when association is not loaded' do
2441
+ it 'queries database on each call' do
2442
+ expect_query(1) do
2443
+ person.posts.exists?.should be false
2444
+ end
2445
+
2446
+ expect_query(1) do
2447
+ person.posts.exists?.should be false
2448
+ end
2449
+ end
2450
+ end
2451
+
2452
+ context 'when association is loaded' do
2453
+ it 'queries database on each call' do
2454
+ expect_query(1) do
2455
+ person.posts.exists?.should be false
2456
+ end
2457
+
2458
+ person.posts.to_a
2459
+
2460
+ expect_query(1) do
2461
+ person.posts.exists?.should be false
2462
+ end
2463
+ end
2464
+ end
2465
+ end
2466
+ end
2467
+
2468
+ describe "#find" do
2469
+
2470
+ context "when iterating after the find" do
2471
+
2472
+ let(:person) do
2473
+ Person.create!
2474
+ end
2475
+
2476
+ let(:post_id) do
2477
+ person.posts.first.id
2478
+ end
2479
+
2480
+ before do
2481
+ 5.times { person.posts.create! }
2482
+ end
2483
+
2484
+ it "does not change the in memory size" do
2485
+ expect {
2486
+ person.posts.find(post_id)
2487
+ }.not_to change { person.posts.to_a.size }
2488
+ end
2489
+ end
2490
+
2491
+ context "when the association is not polymorphic" do
2492
+
2493
+ let(:person) do
2494
+ Person.create!
2495
+ end
2496
+
2497
+ let!(:post_one) do
2498
+ person.posts.create!(title: "Test")
2499
+ end
2500
+
2501
+ let!(:post_two) do
2502
+ person.posts.create!(title: "OMG I has associations")
2503
+ end
2504
+
2505
+ context "when providing an id" do
2506
+
2507
+ context "when the id matches" do
2508
+
2509
+ let(:post) do
2510
+ person.posts.find(post_one.id)
2511
+ end
2512
+
2513
+ it "returns the matching document" do
2514
+ expect(post).to eq(post_one)
2515
+ end
2516
+ end
2517
+
2518
+ context "when the id matches but is not scoped to the association" do
2519
+
2520
+ let(:post) do
2521
+ Post.create!(title: "Unscoped")
2522
+ end
2523
+
2524
+ it "raises an error" do
2525
+ expect {
2526
+ person.posts.find(post.id)
2527
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2528
+ end
2529
+ end
2530
+
2531
+ context "when the id does not match" do
2532
+
2533
+ context "when config set to raise error" do
2534
+
2535
+ before do
2536
+ Mongoid.raise_not_found_error = true
2537
+ end
2538
+
2539
+ it "raises an error" do
2540
+ expect {
2541
+ person.posts.find(BSON::ObjectId.new)
2542
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2543
+ end
2544
+ end
2545
+
2546
+ context "when config set not to raise error" do
2547
+
2548
+ let(:post) do
2549
+ person.posts.find(BSON::ObjectId.new)
2550
+ end
2551
+
2552
+ before do
2553
+ Mongoid.raise_not_found_error = false
2554
+ end
2555
+
2556
+ after do
2557
+ Mongoid.raise_not_found_error = true
2558
+ end
2559
+
2560
+ it "returns nil" do
2561
+ expect(post).to be_nil
2562
+ end
2563
+ end
2564
+ end
2565
+ end
2566
+
2567
+ context "when providing an array of ids" do
2568
+
2569
+ context "when the ids match" do
2570
+
2571
+ let(:posts) do
2572
+ person.posts.find([ post_one.id, post_two.id ])
2573
+ end
2574
+
2575
+ it "returns the matching documents" do
2576
+ expect(posts).to eq([ post_one, post_two ])
2577
+ end
2578
+ end
2579
+
2580
+ context "when the ids do not match" do
2581
+
2582
+ context "when config set to raise error" do
2583
+
2584
+ before do
2585
+ Mongoid.raise_not_found_error = true
2586
+ end
2587
+
2588
+ it "raises an error" do
2589
+ expect {
2590
+ person.posts.find([ BSON::ObjectId.new ])
2591
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2592
+ end
2593
+ end
2594
+
2595
+ context "when config set not to raise error" do
2596
+
2597
+ let(:posts) do
2598
+ person.posts.find([ BSON::ObjectId.new ])
2599
+ end
2600
+
2601
+ before do
2602
+ Mongoid.raise_not_found_error = false
2603
+ end
2604
+
2605
+ after do
2606
+ Mongoid.raise_not_found_error = true
2607
+ end
2608
+
2609
+ it "returns an empty array" do
2610
+ expect(posts).to be_empty
2611
+ end
2612
+ end
2613
+ end
2614
+ end
2615
+ end
2616
+
2617
+ context "when the association is polymorphic" do
2618
+
2619
+ let(:movie) do
2620
+ Movie.create!
2621
+ end
2622
+
2623
+ let!(:rating_one) do
2624
+ movie.ratings.create!(value: 1)
2625
+ end
2626
+
2627
+ let!(:rating_two) do
2628
+ movie.ratings.create!(value: 5)
2629
+ end
2630
+
2631
+ context "when providing an id" do
2632
+
2633
+ context "when the id matches" do
2634
+
2635
+ let(:rating) do
2636
+ movie.ratings.find(rating_one.id)
2637
+ end
2638
+
2639
+ it "returns the matching document" do
2640
+ expect(rating).to eq(rating_one)
2641
+ end
2642
+ end
2643
+
2644
+ context "when the id does not match" do
2645
+
2646
+ context "when config set to raise error" do
2647
+
2648
+ before do
2649
+ Mongoid.raise_not_found_error = true
2650
+ end
2651
+
2652
+ it "raises an error" do
2653
+ expect {
2654
+ movie.ratings.find(BSON::ObjectId.new)
2655
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2656
+ end
2657
+ end
2658
+
2659
+ context "when config set not to raise error" do
2660
+
2661
+ let(:rating) do
2662
+ movie.ratings.find(BSON::ObjectId.new)
2663
+ end
2664
+
2665
+ before do
2666
+ Mongoid.raise_not_found_error = false
2667
+ end
2668
+
2669
+ after do
2670
+ Mongoid.raise_not_found_error = true
2671
+ end
2672
+
2673
+ it "returns nil" do
2674
+ expect(rating).to be_nil
2675
+ end
2676
+ end
2677
+ end
2678
+ end
2679
+
2680
+ context "when providing an array of ids" do
2681
+
2682
+ context "when the ids match" do
2683
+
2684
+ let(:ratings) do
2685
+ movie.ratings.find([ rating_one.id, rating_two.id ])
2686
+ end
2687
+
2688
+ it "returns the first matching document" do
2689
+ expect(ratings).to include(rating_one)
2690
+ end
2691
+
2692
+ it "returns the second matching document" do
2693
+ expect(ratings).to include(rating_two)
2694
+ end
2695
+
2696
+ it "returns the correct number of documents" do
2697
+ expect(ratings.size).to eq(2)
2698
+ end
2699
+ end
2700
+
2701
+ context "when the ids do not match" do
2702
+
2703
+ context "when config set to raise error" do
2704
+
2705
+ before do
2706
+ Mongoid.raise_not_found_error = true
2707
+ end
2708
+
2709
+ it "raises an error" do
2710
+ expect {
2711
+ movie.ratings.find([ BSON::ObjectId.new ])
2712
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2713
+ end
2714
+ end
2715
+
2716
+ context "when config set not to raise error" do
2717
+
2718
+ let(:ratings) do
2719
+ movie.ratings.find([ BSON::ObjectId.new ])
2720
+ end
2721
+
2722
+ before do
2723
+ Mongoid.raise_not_found_error = false
2724
+ end
2725
+
2726
+ after do
2727
+ Mongoid.raise_not_found_error = true
2728
+ end
2729
+
2730
+ it "returns an empty array" do
2731
+ expect(ratings).to be_empty
2732
+ end
2733
+ end
2734
+ end
2735
+ end
2736
+ end
2737
+
2738
+ context "with block" do
2739
+ let!(:author) do
2740
+ Person.create!(title: 'Person')
2741
+ end
2742
+
2743
+ let!(:post_one) do
2744
+ author.posts.create!(title: 'post one')
2745
+ end
2746
+
2747
+ let!(:post_two) do
2748
+ author.posts.create!(title: 'post two')
2749
+ end
2750
+
2751
+ it "finds one" do
2752
+ expect(
2753
+ author.posts.find do |post|
2754
+ post.title == 'post one'
2755
+ end
2756
+ ).to be_a(Post)
2757
+ end
2758
+
2759
+ it "returns first match of multiple" do
2760
+ expect(
2761
+ author.posts.find do |post|
2762
+ ['post one', 'post two'].include?(post.title)
2763
+ end
2764
+ ).to eq(post_one)
2765
+ end
2766
+
2767
+ it "returns nil when not found" do
2768
+ expect(
2769
+ author.posts.find do |post|
2770
+ post.title == 'non exiting one'
2771
+ end
2772
+ ).to be_nil
2773
+ end
2774
+ end
2775
+ end
2776
+
2777
+ describe "#find_or_create_by" do
2778
+
2779
+ context "when the association is not polymorphic" do
2780
+
2781
+ let(:person) do
2782
+ Person.create!
2783
+ end
2784
+
2785
+ let!(:post) do
2786
+ person.posts.create!(title: "Testing")
2787
+ end
2788
+
2789
+ context "when the document exists" do
2790
+
2791
+ let(:found) do
2792
+ person.posts.find_or_create_by(title: "Testing")
2793
+ end
2794
+
2795
+ it "returns the document" do
2796
+ expect(found).to eq(post)
2797
+ end
2798
+
2799
+ it "keeps the document in the association" do
2800
+ expect(found.person).to eq(person)
2801
+ end
2802
+ end
2803
+
2804
+ context "when the document does not exist" do
2805
+
2806
+ context "when there is no criteria attached" do
2807
+
2808
+ let(:found) do
2809
+ person.posts.find_or_create_by(title: "Test") do |post|
2810
+ post.content = "The Content"
2811
+ end
2812
+ end
2813
+
2814
+ it "sets the new document attributes" do
2815
+ expect(found.title).to eq("Test")
2816
+ end
2817
+
2818
+ it "returns a newly persisted document" do
2819
+ expect(found).to be_persisted
2820
+ end
2821
+
2822
+ it "calls the passed block" do
2823
+ expect(found.content).to eq("The Content")
2824
+ end
2825
+
2826
+ it "keeps the document in the association" do
2827
+ expect(found.person).to eq(person)
2828
+ end
2829
+ end
2830
+
2831
+ context "when a criteria is attached" do
2832
+
2833
+ let(:found) do
2834
+ person.posts.recent.find_or_create_by(title: "Test")
2835
+ end
2836
+
2837
+ it "sets the new document attributes" do
2838
+ expect(found.title).to eq("Test")
2839
+ end
2840
+
2841
+ it "returns a newly persisted document" do
2842
+ expect(found).to be_persisted
2843
+ end
2844
+
2845
+ it "keeps the document in the association" do
2846
+ expect(found.person).to eq(person)
2847
+ end
2848
+ end
2849
+ end
2850
+ end
2851
+
2852
+ context "when the association is polymorphic" do
2853
+
2854
+ let(:movie) do
2855
+ Movie.create!
2856
+ end
2857
+
2858
+ let!(:rating) do
2859
+ movie.ratings.create!(value: 1)
2860
+ end
2861
+
2862
+ context "when the document exists" do
2863
+
2864
+ let(:found) do
2865
+ movie.ratings.find_or_create_by(value: 1)
2866
+ end
2867
+
2868
+ it "returns the document" do
2869
+ expect(found).to eq(rating)
2870
+ end
2871
+
2872
+ it "keeps the document in the association" do
2873
+ expect(found.ratable).to eq(movie)
2874
+ end
2875
+ end
2876
+
2877
+ context "when the document does not exist" do
2878
+
2879
+ let(:found) do
2880
+ movie.ratings.find_or_create_by(value: 3)
2881
+ end
2882
+
2883
+ it "sets the new document attributes" do
2884
+ expect(found.value).to eq(3)
2885
+ end
2886
+
2887
+ it "returns a newly persisted document" do
2888
+ expect(found).to be_persisted
2889
+ end
2890
+
2891
+ it "keeps the document in the association" do
2892
+ expect(found.ratable).to eq(movie)
2893
+ end
2894
+ end
2895
+ end
2896
+ end
2897
+
2898
+ describe "#find_or_create_by!" do
2899
+
2900
+ context "when the association is not polymorphic" do
2901
+
2902
+ let(:person) do
2903
+ Person.create!
2904
+ end
2905
+
2906
+ let!(:post) do
2907
+ person.posts.create!(title: "Testing")
2908
+ end
2909
+
2910
+ context "when the document exists" do
2911
+
2912
+ let(:found) do
2913
+ person.posts.find_or_create_by!(title: "Testing")
2914
+ end
2915
+
2916
+ it "returns the document" do
2917
+ expect(found).to eq(post)
2918
+ end
2919
+
2920
+ it "keeps the document in the association" do
2921
+ expect(found.person).to eq(person)
2922
+ end
2923
+ end
2924
+
2925
+ context "when the document does not exist" do
2926
+
2927
+ context "when there is no criteria attached" do
2928
+
2929
+ let(:found) do
2930
+ person.posts.find_or_create_by!(title: "Test") do |post|
2931
+ post.content = "The Content"
2932
+ end
2933
+ end
2934
+
2935
+ it "sets the new document attributes" do
2936
+ expect(found.title).to eq("Test")
2937
+ end
2938
+
2939
+ it "returns a newly persisted document" do
2940
+ expect(found).to be_persisted
2941
+ end
2942
+
2943
+ it "calls the passed block" do
2944
+ expect(found.content).to eq("The Content")
2945
+ end
2946
+
2947
+ it "keeps the document in the association" do
2948
+ expect(found.person).to eq(person)
2949
+ end
2950
+ end
2951
+
2952
+ context "when a criteria is attached" do
2953
+
2954
+ let(:found) do
2955
+ person.posts.recent.find_or_create_by!(title: "Test")
2956
+ end
2957
+
2958
+ it "sets the new document attributes" do
2959
+ expect(found.title).to eq("Test")
2960
+ end
2961
+
2962
+ it "returns a newly persisted document" do
2963
+ expect(found).to be_persisted
2964
+ end
2965
+
2966
+ it "keeps the document in the association" do
2967
+ expect(found.person).to eq(person)
2968
+ end
2969
+ end
2970
+ end
2971
+ end
2972
+
2973
+ context "when the association is polymorphic" do
2974
+
2975
+ let(:movie) do
2976
+ Movie.create!
2977
+ end
2978
+
2979
+ let!(:rating) do
2980
+ movie.ratings.create!(value: 1)
2981
+ end
2982
+
2983
+ context "when the document exists" do
2984
+
2985
+ let(:found) do
2986
+ movie.ratings.find_or_create_by!(value: 1)
2987
+ end
2988
+
2989
+ it "returns the document" do
2990
+ expect(found).to eq(rating)
2991
+ end
2992
+
2993
+ it "keeps the document in the association" do
2994
+ expect(found.ratable).to eq(movie)
2995
+ end
2996
+ end
2997
+
2998
+ context "when the document does not exist" do
2999
+
3000
+ let(:found) do
3001
+ movie.ratings.find_or_create_by!(value: 3)
3002
+ end
3003
+
3004
+ it "sets the new document attributes" do
3005
+ expect(found.value).to eq(3)
3006
+ end
3007
+
3008
+ it "returns a newly persisted document" do
3009
+ expect(found).to be_persisted
3010
+ end
3011
+
3012
+ it "keeps the document in the association" do
3013
+ expect(found.ratable).to eq(movie)
3014
+ end
3015
+
3016
+ context "when validation fails" do
3017
+
3018
+ it "raises an error" do
3019
+ expect {
3020
+ movie.comments.find_or_create_by!(title: "")
3021
+ }.to raise_error(Mongoid::Errors::Validations)
3022
+ end
3023
+ end
3024
+ end
3025
+ end
3026
+ end
3027
+
3028
+ describe "#find_or_initialize_by" do
3029
+
3030
+ context "when the association is not polymorphic" do
3031
+
3032
+ let(:person) do
3033
+ Person.create!
3034
+ end
3035
+
3036
+ let!(:post) do
3037
+ person.posts.create!(title: "Testing")
3038
+ end
3039
+
3040
+ context "when the document exists" do
3041
+
3042
+ let(:found) do
3043
+ person.posts.find_or_initialize_by(title: "Testing")
3044
+ end
3045
+
3046
+ it "returns the document" do
3047
+ expect(found).to eq(post)
3048
+ end
3049
+ end
3050
+
3051
+ context "when the document does not exist" do
3052
+
3053
+ let(:found) do
3054
+ person.posts.find_or_initialize_by(title: "Test") do |post|
3055
+ post.content = "The Content"
3056
+ end
3057
+ end
3058
+
3059
+ it "sets the new document attributes" do
3060
+ expect(found.title).to eq("Test")
3061
+ end
3062
+
3063
+ it "returns a non persisted document" do
3064
+ expect(found).to_not be_persisted
3065
+ end
3066
+
3067
+ it "calls the passed block" do
3068
+ expect(found.content).to eq("The Content")
3069
+ end
3070
+ end
3071
+ end
3072
+
3073
+ context "when the association is polymorphic" do
3074
+
3075
+ let(:movie) do
3076
+ Movie.create!
3077
+ end
3078
+
3079
+ let!(:rating) do
3080
+ movie.ratings.create!(value: 1)
3081
+ end
3082
+
3083
+ context "when the document exists" do
3084
+
3085
+ let(:found) do
3086
+ movie.ratings.find_or_initialize_by(value: 1)
3087
+ end
3088
+
3089
+ it "returns the document" do
3090
+ expect(found).to eq(rating)
3091
+ end
3092
+ end
3093
+
3094
+ context "when the document does not exist" do
3095
+
3096
+ let(:found) do
3097
+ movie.ratings.find_or_initialize_by(value: 3)
3098
+ end
3099
+
3100
+ it "sets the new document attributes" do
3101
+ expect(found.value).to eq(3)
3102
+ end
3103
+
3104
+ it "returns a non persisted document" do
3105
+ expect(found).to_not be_persisted
3106
+ end
3107
+ end
3108
+ end
3109
+ end
3110
+
3111
+ describe "#initialize" do
3112
+
3113
+ context "when an illegal mixed association exists" do
3114
+
3115
+ let(:post) do
3116
+ Post.new
3117
+ end
3118
+
3119
+ it "raises an error" do
3120
+ expect {
3121
+ post.videos
3122
+ }.to raise_error(Mongoid::Errors::MixedRelations)
3123
+ end
3124
+ end
3125
+
3126
+ context "when a cyclic association exists" do
3127
+
3128
+ let(:post) do
3129
+ Post.new
3130
+ end
3131
+
3132
+ it "does not raise an error" do
3133
+ expect(post.roles).to be_empty
3134
+ end
3135
+ end
3136
+ end
3137
+
3138
+ describe "#last" do
3139
+
3140
+ let(:person) do
3141
+ Person.create!
3142
+ end
3143
+
3144
+ let!(:persisted_post) do
3145
+ person.posts.create!
3146
+ end
3147
+
3148
+ context "when a new document is added" do
3149
+
3150
+ let!(:new_post) do
3151
+ person.posts.new
3152
+ end
3153
+
3154
+ context "when the target is subsequently loaded" do
3155
+
3156
+ before do
3157
+ person.posts.entries
3158
+ end
3159
+
3160
+ it "returns the expected last document" do
3161
+ expect(person.posts.last).to eq(new_post)
3162
+ end
3163
+ end
3164
+ end
3165
+ end
3166
+
3167
+ describe "#max" do
3168
+
3169
+ let(:person) do
3170
+ Person.create!
3171
+ end
3172
+
3173
+ let(:post_one) do
3174
+ Post.create!(rating: 5)
3175
+ end
3176
+
3177
+ let(:post_two) do
3178
+ Post.create!(rating: 10)
3179
+ end
3180
+
3181
+ before do
3182
+ person.posts.push(post_one, post_two)
3183
+ end
3184
+
3185
+ let(:max) do
3186
+ person.posts.max do |a,b|
3187
+ a.rating <=> b.rating
3188
+ end
3189
+ end
3190
+
3191
+ it "returns the document with the max value of the supplied field" do
3192
+ expect(max).to eq(post_two)
3193
+ end
3194
+ end
3195
+
3196
+ describe "#max_by" do
3197
+
3198
+ let(:person) do
3199
+ Person.create!
3200
+ end
3201
+
3202
+ let(:post_one) do
3203
+ Post.create!(rating: 5)
3204
+ end
3205
+
3206
+ let(:post_two) do
3207
+ Post.create!(rating: 10)
3208
+ end
3209
+
3210
+ before do
3211
+ person.posts.push(post_one, post_two)
3212
+ end
3213
+
3214
+ let(:max) do
3215
+ person.posts.max_by(&:rating)
3216
+ end
3217
+
3218
+ it "returns the document with the max value of the supplied field" do
3219
+ expect(max).to eq(post_two)
3220
+ end
3221
+ end
3222
+
3223
+ describe "#method_missing" do
3224
+
3225
+ let!(:person) do
3226
+ Person.create!
3227
+ end
3228
+
3229
+ let!(:post_one) do
3230
+ person.posts.create!(title: "First", content: "Posting")
3231
+ end
3232
+
3233
+ let!(:post_two) do
3234
+ person.posts.create!(title: "Second", content: "Testing")
3235
+ end
3236
+
3237
+ context "when providing a single criteria" do
3238
+
3239
+ let(:posts) do
3240
+ person.posts.where(title: "First")
3241
+ end
3242
+
3243
+ it "applies the criteria to the documents" do
3244
+ expect(posts).to eq([ post_one ])
3245
+ end
3246
+
3247
+ context 'when providing a collation' do
3248
+ min_server_version '3.4'
3249
+
3250
+ let(:posts) do
3251
+ person.posts.where(title: "FIRST").collation(locale: 'en_US', strength: 2)
3252
+ end
3253
+
3254
+ it "applies the collation option to the query" do
3255
+ expect(posts).to eq([ post_one ])
3256
+ end
3257
+ end
3258
+ end
3259
+
3260
+ context "when providing a criteria class method" do
3261
+
3262
+ let(:posts) do
3263
+ person.posts.posting
3264
+ end
3265
+
3266
+ it "applies the criteria to the documents" do
3267
+ expect(posts).to eq([ post_one ])
3268
+ end
3269
+ end
3270
+
3271
+ context "when chaining criteria" do
3272
+
3273
+ let(:posts) do
3274
+ person.posts.posting.where(:title.in => [ "First" ])
3275
+ end
3276
+
3277
+ it "applies the criteria to the documents" do
3278
+ expect(posts).to eq([ post_one ])
3279
+ end
3280
+ end
3281
+
3282
+ context "when delegating methods" do
3283
+
3284
+ describe "#distinct" do
3285
+
3286
+ let(:values) do
3287
+ person.posts.distinct(:title)
3288
+ end
3289
+
3290
+ it "returns the distinct values for the fields" do
3291
+ expect(values).to include("First")
3292
+ expect(values).to include("Second")
3293
+ end
3294
+ end
3295
+ end
3296
+ end
3297
+
3298
+ describe "#min" do
3299
+
3300
+ let(:person) do
3301
+ Person.create!
3302
+ end
3303
+
3304
+ let(:post_one) do
3305
+ Post.create!(rating: 5)
3306
+ end
3307
+
3308
+ let(:post_two) do
3309
+ Post.create!(rating: 10)
3310
+ end
3311
+
3312
+ before do
3313
+ person.posts.push(post_one, post_two)
3314
+ end
3315
+
3316
+ let(:min) do
3317
+ person.posts.min do |a, b|
3318
+ a.rating <=> b.rating
3319
+ end
3320
+ end
3321
+
3322
+ it "returns the min value of the supplied field" do
3323
+ expect(min).to eq(post_one)
3324
+ end
3325
+ end
3326
+
3327
+ describe "#min_by" do
3328
+
3329
+ let(:person) do
3330
+ Person.create!
3331
+ end
3332
+
3333
+ let(:post_one) do
3334
+ Post.create!(rating: 5)
3335
+ end
3336
+
3337
+ let(:post_two) do
3338
+ Post.create!(rating: 10)
3339
+ end
3340
+
3341
+ before do
3342
+ person.posts.push(post_one, post_two)
3343
+ end
3344
+
3345
+ let(:min) do
3346
+ person.posts.min_by(&:rating)
3347
+ end
3348
+
3349
+ it "returns the min value of the supplied field" do
3350
+ expect(min).to eq(post_one)
3351
+ end
3352
+ end
3353
+
3354
+ describe "#nullify_all" do
3355
+
3356
+ context "when the inverse has not been loaded" do
3357
+
3358
+ let(:person) do
3359
+ Person.create!
3360
+ end
3361
+
3362
+ let!(:post_one) do
3363
+ person.posts.create!(title: "One")
3364
+ end
3365
+
3366
+ let!(:post_two) do
3367
+ person.posts.create!(title: "Two")
3368
+ end
3369
+
3370
+ let(:from_db) do
3371
+ Person.first
3372
+ end
3373
+
3374
+ before do
3375
+ from_db.posts.nullify_all
3376
+ end
3377
+
3378
+ it "loads the targets before nullifying" do
3379
+ expect(from_db.posts).to be_empty
3380
+ end
3381
+
3382
+ it "persists the base nullifications" do
3383
+ expect(Person.first.posts).to be_empty
3384
+ end
3385
+
3386
+ it "persists the inverse nullifications" do
3387
+ Post.all.each do |post|
3388
+ expect(post.person).to be_nil
3389
+ end
3390
+ end
3391
+ end
3392
+
3393
+ context "when the association is not polymorphic" do
3394
+
3395
+ let(:person) do
3396
+ Person.create!
3397
+ end
3398
+
3399
+ let!(:post_one) do
3400
+ person.posts.create!(title: "One")
3401
+ end
3402
+
3403
+ let!(:post_two) do
3404
+ person.posts.create!(title: "Two")
3405
+ end
3406
+
3407
+ before do
3408
+ person.posts.nullify_all
3409
+ end
3410
+
3411
+ it "removes all the foreign keys from the target" do
3412
+ [ post_one, post_two ].each do |post|
3413
+ expect(post.person_id).to be_nil
3414
+ end
3415
+ end
3416
+
3417
+ it "removes all the references from the target" do
3418
+ [ post_one, post_two ].each do |post|
3419
+ expect(post.person).to be_nil
3420
+ end
3421
+ end
3422
+
3423
+ it "saves the documents" do
3424
+ expect(post_one.reload.person).to be_nil
3425
+ end
3426
+
3427
+ context "when adding a nullified document back to the association" do
3428
+
3429
+ before do
3430
+ person.posts.push(post_one)
3431
+ end
3432
+
3433
+ it "persists the association" do
3434
+ expect(person.posts(true)).to eq([ post_one ])
3435
+ end
3436
+ end
3437
+ end
3438
+
3439
+ context "when the association is polymorphic" do
3440
+
3441
+ let(:movie) do
3442
+ Movie.create!(title: "Oldboy")
3443
+ end
3444
+
3445
+ let!(:rating_one) do
3446
+ movie.ratings.create!(value: 10)
3447
+ end
3448
+
3449
+ let!(:rating_two) do
3450
+ movie.ratings.create!(value: 9)
3451
+ end
3452
+
3453
+ before do
3454
+ movie.ratings.nullify_all
3455
+ end
3456
+
3457
+ it "removes all the foreign keys from the target" do
3458
+ [ rating_one, rating_two ].each do |rating|
3459
+ expect(rating.ratable_id).to be_nil
3460
+ end
3461
+ end
3462
+
3463
+ it "removes all the references from the target" do
3464
+ [ rating_one, rating_two ].each do |rating|
3465
+ expect(rating.ratable).to be_nil
3466
+ end
3467
+ end
3468
+ end
3469
+ end
3470
+
3471
+ describe "#respond_to?" do
3472
+
3473
+ let(:person) do
3474
+ Person.new
3475
+ end
3476
+
3477
+ let(:posts) do
3478
+ person.posts
3479
+ end
3480
+
3481
+ Array.public_instance_methods.each do |method|
3482
+
3483
+ context "when checking #{method}" do
3484
+
3485
+ it "returns true" do
3486
+ expect(posts.respond_to?(method)).to be true
3487
+ end
3488
+ end
3489
+ end
3490
+
3491
+ Mongoid::Association::Referenced::HasMany::Proxy.public_instance_methods.each do |method|
3492
+
3493
+ context "when checking #{method}" do
3494
+
3495
+ it "returns true" do
3496
+ expect(posts.respond_to?(method)).to be true
3497
+ end
3498
+ end
3499
+ end
3500
+
3501
+ Post.scopes.keys.each do |method|
3502
+
3503
+ context "when checking #{method}" do
3504
+
3505
+ it "returns true" do
3506
+ expect(posts.respond_to?(method)).to be true
3507
+ end
3508
+ end
3509
+ end
3510
+ end
3511
+
3512
+ describe "#scoped" do
3513
+
3514
+ let(:person) do
3515
+ Person.new
3516
+ end
3517
+
3518
+ let(:scoped) do
3519
+ person.posts.scoped
3520
+ end
3521
+
3522
+ it "returns the association criteria" do
3523
+ expect(scoped).to be_a(Mongoid::Criteria)
3524
+ end
3525
+
3526
+ it "returns with an empty selector" do
3527
+ expect(scoped.selector).to eq({ "person_id" => person.id })
3528
+ end
3529
+ end
3530
+
3531
+ [ :size, :length ].each do |method|
3532
+
3533
+ describe "##{method}" do
3534
+
3535
+ let(:movie) do
3536
+ Movie.create!
3537
+ end
3538
+
3539
+ context "when documents have been persisted" do
3540
+
3541
+ let!(:rating) do
3542
+ movie.ratings.create!(value: 1)
3543
+ end
3544
+
3545
+ it "returns 1" do
3546
+ expect(movie.ratings.send(method)).to eq(1)
3547
+ end
3548
+ end
3549
+
3550
+ context "when documents have not been persisted" do
3551
+
3552
+ before do
3553
+ movie.ratings.build(value: 1)
3554
+ movie.ratings.create!(value: 2)
3555
+ end
3556
+
3557
+ it "returns the total number of documents" do
3558
+ expect(movie.ratings.send(method)).to eq(2)
3559
+ end
3560
+ end
3561
+ end
3562
+ end
3563
+
3564
+ describe "#unscoped" do
3565
+
3566
+ context "when the association has no default scope" do
3567
+
3568
+ let!(:person) do
3569
+ Person.create!
3570
+ end
3571
+
3572
+ let!(:post_one) do
3573
+ person.posts.create!(title: "first")
3574
+ end
3575
+
3576
+ let!(:post_two) do
3577
+ Post.create!(title: "second")
3578
+ end
3579
+
3580
+ let(:unscoped) do
3581
+ person.posts.unscoped
3582
+ end
3583
+
3584
+ it "returns only the associated documents" do
3585
+ expect(unscoped).to eq([ post_one ])
3586
+ end
3587
+ end
3588
+
3589
+ context "when the association has a default scope" do
3590
+
3591
+ let!(:church) do
3592
+ Church.create!
3593
+ end
3594
+
3595
+ let!(:acolyte_one) do
3596
+ church.acolytes.create!(name: "first")
3597
+ end
3598
+
3599
+ let!(:acolyte_two) do
3600
+ Acolyte.create!(name: "second")
3601
+ end
3602
+
3603
+ let(:unscoped) do
3604
+ church.acolytes.unscoped
3605
+ end
3606
+
3607
+ it "only returns associated documents" do
3608
+ expect(unscoped).to eq([ acolyte_one ])
3609
+ end
3610
+
3611
+ it "removes the default scoping options" do
3612
+ expect(unscoped.options).to eq({})
3613
+ end
3614
+ end
3615
+ end
3616
+
3617
+ context "when the association has an order defined" do
3618
+
3619
+ let(:person) do
3620
+ Person.create!
3621
+ end
3622
+
3623
+ let(:post_one) do
3624
+ OrderedPost.create!(rating: 10, title: '1')
3625
+ end
3626
+
3627
+ let(:post_two) do
3628
+ OrderedPost.create!(rating: 20, title: '2')
3629
+ end
3630
+
3631
+ let(:post_three) do
3632
+ OrderedPost.create!(rating: 20, title: '3')
3633
+ end
3634
+
3635
+ before do
3636
+ person.ordered_posts.nullify_all
3637
+ person.ordered_posts.push(post_one, post_two, post_three)
3638
+ end
3639
+
3640
+ it "order documents" do
3641
+ expect(person.ordered_posts(true)).to eq(
3642
+ [post_two, post_three, post_one]
3643
+ )
3644
+ end
3645
+
3646
+ it "chaining order criteria" do
3647
+ expect(person.ordered_posts.order_by(:title.desc).to_a).to eq(
3648
+ [post_three, post_two, post_one]
3649
+ )
3650
+ end
3651
+ end
3652
+
3653
+ context "when reloading the association" do
3654
+
3655
+ let!(:person) do
3656
+ Person.create!
3657
+ end
3658
+
3659
+ let!(:post_one) do
3660
+ Post.create!(title: "one")
3661
+ end
3662
+
3663
+ let!(:post_two) do
3664
+ Post.create!(title: "two")
3665
+ end
3666
+
3667
+ before do
3668
+ person.posts << post_one
3669
+ end
3670
+
3671
+ context "when the association references the same documents" do
3672
+
3673
+ before do
3674
+ Post.collection.find({ _id: post_one.id }).
3675
+ update_one({ "$set" => { title: "reloaded" }})
3676
+ end
3677
+
3678
+ let(:reloaded) do
3679
+ person.posts(true)
3680
+ end
3681
+
3682
+ it "reloads the document from the database" do
3683
+ expect(reloaded.first.title).to eq("reloaded")
3684
+ end
3685
+ end
3686
+
3687
+ context "when the association references different documents" do
3688
+
3689
+ before do
3690
+ person.posts << post_two
3691
+ end
3692
+
3693
+ let(:reloaded) do
3694
+ person.posts(true)
3695
+ end
3696
+
3697
+ it "reloads the first document from the database" do
3698
+ expect(reloaded).to include(post_one)
3699
+ end
3700
+
3701
+ it "reloads the new document from the database" do
3702
+ expect(reloaded).to include(post_two)
3703
+ end
3704
+ end
3705
+ end
3706
+
3707
+ context "when the parent is using integer ids" do
3708
+
3709
+ let(:jar) do
3710
+ Jar.create! do |doc|
3711
+ doc._id = 1
3712
+ end
3713
+ end
3714
+
3715
+ it "allows creation of the document" do
3716
+ expect(jar.id).to eq(1)
3717
+ end
3718
+ end
3719
+
3720
+ context "when adding a document" do
3721
+
3722
+ let(:person) do
3723
+ Person.new
3724
+ end
3725
+
3726
+ let(:post_one) do
3727
+ Post.new
3728
+ end
3729
+
3730
+ let(:first_add) do
3731
+ person.posts.push(post_one)
3732
+ end
3733
+
3734
+ context "when chaining a second add" do
3735
+
3736
+ let(:post_two) do
3737
+ Post.new
3738
+ end
3739
+
3740
+ let(:result) do
3741
+ first_add.push(post_two)
3742
+ end
3743
+
3744
+ it "adds both documents" do
3745
+ expect(result).to eq([ post_one, post_two ])
3746
+ end
3747
+ end
3748
+ end
3749
+
3750
+ context "when pushing with a before_add callback" do
3751
+
3752
+ let(:artist) do
3753
+ Artist.new
3754
+ end
3755
+
3756
+ let(:album) do
3757
+ Album.new
3758
+ end
3759
+
3760
+ context "when execution raises no errors" do
3761
+
3762
+ before do
3763
+ artist.albums << album
3764
+ end
3765
+
3766
+ it "it executes method callbacks" do
3767
+ expect(artist.before_add_referenced_called).to be true
3768
+ end
3769
+
3770
+ it "it executes proc callbacks" do
3771
+ expect(album.before_add_called).to be true
3772
+ end
3773
+
3774
+ it "adds the document to the association" do
3775
+ expect(artist.albums).to eq([ album ])
3776
+ end
3777
+ end
3778
+
3779
+ context "when execution raises errors" do
3780
+
3781
+ before do
3782
+ expect(artist).to receive(:before_add_album).and_raise
3783
+ begin; artist.albums << album; rescue; end
3784
+ end
3785
+
3786
+ it "does not add the document to the association" do
3787
+ expect(artist.albums).to be_empty
3788
+ end
3789
+ end
3790
+ end
3791
+
3792
+ context "when pushing with an after_add callback" do
3793
+
3794
+ let(:artist) do
3795
+ Artist.new
3796
+ end
3797
+
3798
+ let(:album) do
3799
+ Album.new
3800
+ end
3801
+
3802
+ it "executes the callback" do
3803
+ artist.albums << album
3804
+ expect(artist.after_add_referenced_called).to be true
3805
+ end
3806
+
3807
+ context "when execution raises errors" do
3808
+
3809
+ before do
3810
+ expect(artist).to receive(:after_add_album).and_raise
3811
+ begin; artist.albums << album; rescue; end
3812
+ end
3813
+
3814
+ it "adds the document to the association" do
3815
+ expect(artist.albums).to eq([ album ])
3816
+ end
3817
+ end
3818
+
3819
+ context 'when the association already exists' do
3820
+
3821
+ before do
3822
+ artist.albums << album
3823
+ album.save!
3824
+ artist.save!
3825
+ expect(artist).not_to receive(:after_add_album)
3826
+ end
3827
+
3828
+ let(:reloaded_album) do
3829
+ Album.where(artist_id: artist.id).first
3830
+ end
3831
+
3832
+ it 'does not execute the callback when the association is accessed' do
3833
+ expect(reloaded_album.artist.after_add_referenced_called).to be(nil)
3834
+ end
3835
+ end
3836
+ end
3837
+
3838
+ context "when #delete or #clear with before_remove callback" do
3839
+
3840
+ let(:artist) do
3841
+ Artist.new
3842
+ end
3843
+
3844
+ let(:album) do
3845
+ Album.new
3846
+ end
3847
+
3848
+ before do
3849
+ artist.albums << album
3850
+ end
3851
+
3852
+ context "when executing raises no errors" do
3853
+
3854
+ describe "#delete" do
3855
+
3856
+ before do
3857
+ artist.albums.delete album
3858
+ end
3859
+
3860
+ it "executes the callback" do
3861
+ expect(artist.before_remove_referenced_called).to be true
3862
+ end
3863
+
3864
+ it "removes the document from the association" do
3865
+ expect(artist.albums).to be_empty
3866
+ end
3867
+ end
3868
+
3869
+ describe "#clear" do
3870
+
3871
+ before do
3872
+ artist.albums.clear
3873
+ end
3874
+
3875
+ it "executes the callback" do
3876
+ expect(artist.before_remove_referenced_called).to be true
3877
+ end
3878
+
3879
+ it "clears the association" do
3880
+ expect(artist.albums).to be_empty
3881
+ end
3882
+ end
3883
+
3884
+ context "when execution raises errors" do
3885
+
3886
+ before do
3887
+ expect(artist).to receive(:before_remove_album).and_raise
3888
+ end
3889
+
3890
+ describe "#delete" do
3891
+
3892
+ before do
3893
+ begin; artist.albums.delete(album); rescue; end
3894
+ end
3895
+
3896
+ it "does not remove the document from the association" do
3897
+ expect(artist.albums).to eq([ album ])
3898
+ end
3899
+ end
3900
+
3901
+ describe "#clear" do
3902
+
3903
+ before do
3904
+ begin; artist.albums.clear; rescue; end
3905
+ end
3906
+
3907
+ it "does not clear the association" do
3908
+ expect(artist.albums).to eq([ album ])
3909
+ end
3910
+ end
3911
+ end
3912
+ end
3913
+ end
3914
+
3915
+ context "when #delete or #clear with after_remove callback" do
3916
+
3917
+ let(:artist) do
3918
+ Artist.new
3919
+ end
3920
+
3921
+ let(:album) do
3922
+ Album.new
3923
+ end
3924
+
3925
+ before do
3926
+ artist.albums << album
3927
+ end
3928
+
3929
+ context "without errors" do
3930
+
3931
+ describe "#delete" do
3932
+
3933
+ before do
3934
+ artist.albums.delete album
3935
+ end
3936
+
3937
+ it "executes the callback" do
3938
+ expect(artist.after_remove_referenced_called).to be true
3939
+ end
3940
+ end
3941
+
3942
+ describe "#clear" do
3943
+
3944
+ before do
3945
+ artist.albums.clear
3946
+ end
3947
+
3948
+ it "executes the callback" do
3949
+ artist.albums.clear
3950
+ expect(artist.after_remove_referenced_called).to be true
3951
+ end
3952
+ end
3953
+ end
3954
+
3955
+ context "when errors are raised" do
3956
+
3957
+ before do
3958
+ expect(artist).to receive(:after_remove_album).and_raise
3959
+ end
3960
+
3961
+ describe "#delete" do
3962
+
3963
+ before do
3964
+ begin; artist.albums.delete(album); rescue; end
3965
+ end
3966
+
3967
+ it "removes the documents from the association" do
3968
+ expect(artist.albums).to be_empty
3969
+ end
3970
+ end
3971
+
3972
+ describe "#clear" do
3973
+
3974
+ before do
3975
+ begin; artist.albums.clear; rescue; end
3976
+ end
3977
+
3978
+ it "removes the documents from the association" do
3979
+ expect(artist.albums).to be_empty
3980
+ end
3981
+ end
3982
+ end
3983
+ end
3984
+
3985
+ context "when executing a criteria call on an ordered association" do
3986
+
3987
+ let(:person) do
3988
+ Person.create!
3989
+ end
3990
+
3991
+ let!(:post_one) do
3992
+ person.ordered_posts.create!(rating: 1)
3993
+ end
3994
+
3995
+ let!(:post_two) do
3996
+ person.ordered_posts.create!(rating: 5)
3997
+ end
3998
+
3999
+ let(:criteria) do
4000
+ person.ordered_posts.only(:_id, :rating)
4001
+ end
4002
+
4003
+ it "does not drop the ordering" do
4004
+ expect(criteria).to eq([ post_two, post_one ])
4005
+ end
4006
+ end
4007
+
4008
+ context "when accessing a scope named open" do
4009
+
4010
+ let(:person) do
4011
+ Person.create!
4012
+ end
4013
+
4014
+ let!(:post) do
4015
+ person.posts.create!(title: "open")
4016
+ end
4017
+
4018
+ it "returns the appropriate documents" do
4019
+ expect(person.posts.open).to eq([ post ])
4020
+ end
4021
+ end
4022
+
4023
+ context "when accessing a association named parent" do
4024
+
4025
+ let!(:parent) do
4026
+ Odd.create!(name: "odd parent")
4027
+ end
4028
+
4029
+ let(:child) do
4030
+ Even.create!(parent_id: parent.id, name: "original even child")
4031
+ end
4032
+
4033
+ it "updates the child after accessing the parent" do
4034
+ # Access parent association on the child to make sure it is loaded
4035
+ child.parent
4036
+
4037
+ new_child_name = "updated even child"
4038
+
4039
+ child.name = new_child_name
4040
+ child.save!
4041
+
4042
+ reloaded = Even.find(child.id)
4043
+ expect(reloaded.name).to eq(new_child_name)
4044
+ end
4045
+ end
4046
+
4047
+ context 'when a document has referenced and embedded associations' do
4048
+
4049
+ let(:agent) do
4050
+ Agent.new
4051
+ end
4052
+
4053
+ let(:basic) do
4054
+ Basic.new
4055
+ end
4056
+
4057
+ let(:address) do
4058
+ Address.new
4059
+ end
4060
+
4061
+ before do
4062
+ agent.basics << basic
4063
+ agent.address = address
4064
+ end
4065
+
4066
+ it 'saves the document correctly' do
4067
+ expect(agent.save!).to be(true)
4068
+ end
4069
+ end
4070
+
4071
+ context 'when the two models use the same name to refer to the association' do
4072
+
4073
+ let(:agent) do
4074
+ Agent.new
4075
+ end
4076
+
4077
+ let(:band) do
4078
+ Band.new
4079
+ end
4080
+
4081
+ before do
4082
+ agent.same_name = band
4083
+ agent.save!
4084
+ band.save!
4085
+ band.reload
4086
+ end
4087
+
4088
+ it 'constructs the correct criteria' do
4089
+ expect(band.same_name).to eq([agent])
4090
+ end
4091
+ end
4092
+
4093
+ context "when executing concat on foreign key array from the db" do
4094
+ config_override :legacy_attributes, false
4095
+
4096
+ before do
4097
+ Agent.create!
4098
+ Basic.create!
4099
+ end
4100
+
4101
+ let!(:agent) { Agent.first }
4102
+ let!(:basic) { Basic.first }
4103
+
4104
+ before do
4105
+ agent.basic_ids.concat([basic.id])
4106
+ end
4107
+
4108
+ it "works on the first attempt" do
4109
+ expect(agent.basic_ids).to eq([basic.id])
4110
+ end
4111
+ end
4112
+ end