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,3803 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require_relative "../has_and_belongs_to_many_models.rb"
5
+
6
+ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
7
+
8
+ around(:each) do |example|
9
+ original_raise_not_found_error = Mongoid.raise_not_found_error
10
+ original_preferences_association = Person.relations["preferences"]
11
+ Mongoid.raise_not_found_error = true
12
+ Person.has_and_belongs_to_many :preferences, autosave: true
13
+ example.run
14
+ Mongoid.raise_not_found_error = original_raise_not_found_error
15
+ Person.relations["preferences"] = original_preferences_association
16
+ end
17
+
18
+ after(:all) do
19
+ Person.reset_callbacks(:save)
20
+ Person.reset_callbacks(:destroy)
21
+ end
22
+
23
+ [ :<<, :push ].each do |method|
24
+
25
+ describe "##{method}" do
26
+
27
+ context "when the inverse_of is nil" do
28
+
29
+ let!(:article) do
30
+ Article.create!
31
+ end
32
+
33
+ context "when the child document is new" do
34
+
35
+ let(:preference) do
36
+ Preference.new
37
+ end
38
+
39
+ before do
40
+ article.preferences.send(method, preference)
41
+ end
42
+
43
+ it "persists the child document" do
44
+ expect(preference).to be_persisted
45
+ end
46
+ end
47
+
48
+ context "when the child document is not new" do
49
+
50
+ let(:preference) do
51
+ Preference.create!
52
+ end
53
+
54
+ it "does not persist the child document" do
55
+ expect(preference).to receive(:save).never
56
+ article.preferences.send(method, preference)
57
+ end
58
+ end
59
+ end
60
+
61
+ context "when the parent is a new record" do
62
+
63
+ let(:person) do
64
+ Person.new
65
+ end
66
+
67
+ let!(:preference) do
68
+ Preference.new
69
+ end
70
+
71
+ let(:result) do
72
+ person.preferences.send(method, preference)
73
+ end
74
+
75
+ it "returns an array of loaded documents" do
76
+ expect(result).to eq([ preference ])
77
+ end
78
+ end
79
+
80
+ context "when the parent is not a new record" do
81
+
82
+ let(:person) do
83
+ Person.create!
84
+ end
85
+
86
+ let!(:preference) do
87
+ Preference.new
88
+ end
89
+
90
+ let(:result) do
91
+ person.preferences.send(method, preference)
92
+ end
93
+
94
+ it "returns an array of loaded documents" do
95
+ expect(result).to eq([ preference ])
96
+ end
97
+ end
98
+
99
+ context "when the relations are not polymorphic" do
100
+
101
+ context "when the inverse relation is not defined" do
102
+
103
+ let(:person) do
104
+ Person.new
105
+ end
106
+
107
+ let(:house) do
108
+ House.new
109
+ end
110
+
111
+ before do
112
+ person.houses << house
113
+ end
114
+
115
+ it "appends the document to the relation" do
116
+ expect(person.houses).to eq([ house ])
117
+ end
118
+
119
+ it "sets the foreign key on the relation" do
120
+ expect(person.house_ids).to eq([ house.id ])
121
+ end
122
+ end
123
+
124
+ context "when appending in a parent create block" do
125
+
126
+ let!(:preference) do
127
+ Preference.create!(name: "testing")
128
+ end
129
+
130
+ let!(:person) do
131
+ Person.create! do |doc|
132
+ doc.preferences << preference
133
+ end
134
+ end
135
+
136
+ it "adds the documents to the relation" do
137
+ expect(person.preferences).to eq([ preference ])
138
+ end
139
+
140
+ it "sets the foreign key on the relation" do
141
+ expect(person.preference_ids).to eq([ preference.id ])
142
+ end
143
+
144
+ it "sets the foreign key on the inverse relation" do
145
+ expect(preference.person_ids).to eq([ person.id ])
146
+ end
147
+
148
+ it "saves the target" do
149
+ expect(preference).to be_persisted
150
+ end
151
+
152
+ it "adds the correct number of documents" do
153
+ expect(person.preferences.size).to eq(1)
154
+ end
155
+
156
+ it "persists the link" do
157
+ expect(person.reload.preferences).to eq([ preference ])
158
+ end
159
+ end
160
+
161
+ context "when the parent is a new record" do
162
+
163
+ let(:person) do
164
+ Person.new
165
+ end
166
+
167
+ context "when the child is new" do
168
+
169
+ let(:preference) do
170
+ Preference.new
171
+ end
172
+
173
+ before do
174
+ person.preferences.send(method, preference)
175
+ end
176
+
177
+ it "adds the documents to the relation" do
178
+ expect(person.preferences).to eq([ preference ])
179
+ end
180
+
181
+ it "sets the foreign key on the relation" do
182
+ expect(person.preference_ids).to eq([ preference.id ])
183
+ end
184
+
185
+ it "sets the foreign key on the inverse relation" do
186
+ expect(preference.person_ids).to eq([ person.id ])
187
+ end
188
+
189
+ it "does not save the target" do
190
+ expect(preference).to be_new_record
191
+ end
192
+
193
+ it "adds the correct number of documents" do
194
+ expect(person.preferences.size).to eq(1)
195
+ end
196
+
197
+ context "when appending a second time" do
198
+
199
+ before do
200
+ person.preferences.send(method, preference)
201
+ end
202
+
203
+ it "does not allow the document to be added again" do
204
+ expect(person.preferences).to eq([ preference ])
205
+ end
206
+
207
+ it "does not allow duplicate ids" do
208
+ expect(person.preference_ids).to eq([ preference.id ])
209
+ end
210
+ end
211
+ end
212
+
213
+ context "when the child is already persisted" do
214
+
215
+ let!(:persisted) do
216
+ Preference.create!(name: "testy")
217
+ end
218
+
219
+ let(:preference) do
220
+ Preference.first
221
+ end
222
+
223
+ before do
224
+ person.preferences.send(method, preference)
225
+ person.save!
226
+ end
227
+
228
+ it "adds the documents to the relation" do
229
+ expect(person.preferences).to eq([ preference ])
230
+ end
231
+
232
+ it "sets the foreign key on the relation" do
233
+ expect(person.preference_ids).to eq([ preference.id ])
234
+ end
235
+
236
+ it "sets the foreign key on the inverse relation" do
237
+ expect(preference.person_ids).to eq([ person.id ])
238
+ end
239
+
240
+ it "saves the target" do
241
+ expect(preference).to be_persisted
242
+ end
243
+
244
+ it "adds the correct number of documents" do
245
+ expect(person.preferences.size).to eq(1)
246
+ end
247
+
248
+ it "persists the link" do
249
+ expect(person.reload.preferences).to eq([ preference ])
250
+ end
251
+ end
252
+
253
+ context "when setting via the associated ids" do
254
+
255
+ let!(:persisted) do
256
+ Preference.create!(name: "testy")
257
+ end
258
+
259
+ let(:preference) do
260
+ Preference.first
261
+ end
262
+
263
+ let(:person) do
264
+ Person.new(preference_ids: [ preference.id ])
265
+ end
266
+
267
+ before do
268
+ person.save!
269
+ end
270
+
271
+ it "adds the documents to the relation" do
272
+ expect(person.preferences).to eq([ preference ])
273
+ end
274
+
275
+ it "sets the foreign key on the relation" do
276
+ expect(person.preference_ids).to eq([ preference.id ])
277
+ end
278
+
279
+ it "sets the foreign key on the inverse relation" do
280
+ expect(preference.reload.person_ids).to eq([ person.id ])
281
+ end
282
+
283
+ it "adds the correct number of documents" do
284
+ expect(person.preferences.size).to eq(1)
285
+ end
286
+
287
+ it "persists the link" do
288
+ expect(person.reload.preferences).to eq([ preference ])
289
+ end
290
+ end
291
+ end
292
+
293
+ context "when the parent is not a new record" do
294
+
295
+ let(:person) do
296
+ Person.create!
297
+ end
298
+
299
+ let(:preference) do
300
+ Preference.new
301
+ end
302
+
303
+ before do
304
+ person.preferences.send(method, preference)
305
+ end
306
+
307
+ it "adds the documents to the relation" do
308
+ expect(person.preferences).to eq([ preference ])
309
+ end
310
+
311
+ it "sets the foreign key on the relation" do
312
+ expect(person.preference_ids).to eq([ preference.id ])
313
+ end
314
+
315
+ it "sets the foreign key on the inverse relation" do
316
+ expect(preference.person_ids).to eq([ person.id ])
317
+ end
318
+
319
+ it "sets the base on the inverse relation" do
320
+ expect(preference.people).to eq([ person ])
321
+ end
322
+
323
+ it "sets the same instance on the inverse relation" do
324
+ expect(preference.people.first).to eql(person)
325
+ end
326
+
327
+ it "saves the target" do
328
+ expect(preference).to_not be_new_record
329
+ end
330
+
331
+ it "adds the document to the target" do
332
+ expect(person.preferences.count).to eq(1)
333
+ end
334
+
335
+ context "when documents already exist on the relation" do
336
+
337
+ let(:preference_two) do
338
+ Preference.new
339
+ end
340
+
341
+ before do
342
+ person.preferences.send(method, preference_two)
343
+ end
344
+
345
+ it "adds the documents to the relation" do
346
+ expect(person.preferences).to eq([ preference, preference_two ])
347
+ end
348
+
349
+ it "sets the foreign key on the relation" do
350
+ expect(person.preference_ids).to eq([ preference.id, preference_two.id ])
351
+ end
352
+
353
+ it "sets the foreign key on the inverse relation" do
354
+ expect(preference_two.person_ids).to eq([ person.id ])
355
+ end
356
+
357
+ it "sets the base on the inverse relation" do
358
+ expect(preference_two.people).to eq([ person ])
359
+ end
360
+
361
+ it "sets the same instance on the inverse relation" do
362
+ expect(preference_two.people.first).to eql(person)
363
+ end
364
+
365
+ it "saves the target" do
366
+ expect(preference).to_not be_new_record
367
+ end
368
+
369
+ it "adds the document to the target" do
370
+ expect(person.preferences.count).to eq(2)
371
+ end
372
+ end
373
+ end
374
+
375
+ context "when both sides have been persisted" do
376
+
377
+ let(:person) do
378
+ Person.create!
379
+ end
380
+
381
+ let(:event) do
382
+ Event.create!
383
+ end
384
+
385
+ before do
386
+ person.administrated_events << event
387
+ end
388
+
389
+ it "sets the front side of the relation" do
390
+ expect(person.administrated_events).to eq([ event ])
391
+ end
392
+
393
+ it "sets the inverse side of the relation" do
394
+ expect(event.administrators(true)).to eq([ person ])
395
+ end
396
+
397
+ context "when reloading" do
398
+
399
+ it "sets the front side of the relation" do
400
+ expect(person.reload.administrated_events).to eq([ event ])
401
+ end
402
+
403
+ it "sets the inverse side of the relation" do
404
+ expect(event.reload.administrators).to eq([ person ])
405
+ end
406
+ end
407
+
408
+ context "when performing a new database query" do
409
+
410
+ let(:loaded_person) do
411
+ Person.find(person.id)
412
+ end
413
+
414
+ let(:loaded_event) do
415
+ Event.find(event.id)
416
+ end
417
+
418
+ it "sets the front side of the relation" do
419
+ expect(loaded_person.administrated_events).to eq([ event ])
420
+ end
421
+
422
+ it "sets the inverse side of the relation" do
423
+ expect(loaded_event.administrators).to eq([ person ])
424
+ end
425
+ end
426
+ end
427
+
428
+ context "when the relation also includes a has_many relation" do
429
+
430
+ let(:artwork) do
431
+ Artwork.create!
432
+ end
433
+
434
+ let(:exhibition) do
435
+ Exhibition.create!
436
+ end
437
+
438
+ let(:exhibitor) do
439
+ Exhibitor.create!(exhibition: exhibition)
440
+ end
441
+
442
+ before do
443
+ artwork.exhibitors << exhibitor
444
+ end
445
+
446
+ it "creates a single artwork object" do
447
+ expect(Artwork.count).to eq(1)
448
+ end
449
+ end
450
+
451
+ context "when the relation is self referencing" do
452
+
453
+ let(:tag_one) do
454
+ Tag.create!(text: "one")
455
+ end
456
+
457
+ let(:tag_two) do
458
+ Tag.create!(text: "two")
459
+ end
460
+
461
+ before do
462
+ tag_one.related << tag_two
463
+ end
464
+
465
+ it "sets the front side of the relation" do
466
+ expect(tag_one.related).to eq([ tag_two ])
467
+ end
468
+
469
+ it "sets the inverse side of the relation" do
470
+ expect(tag_two.related(true)).to eq([ tag_one ])
471
+ end
472
+
473
+ context "when reloading" do
474
+
475
+ it "sets the front side of the relation" do
476
+ expect(tag_one.reload.related).to eq([ tag_two ])
477
+ end
478
+
479
+ it "sets the inverse side of the relation" do
480
+ expect(tag_two.reload.related).to eq([ tag_one ])
481
+ end
482
+ end
483
+
484
+ context "when performing a new database query" do
485
+
486
+ let(:loaded_tag_one) do
487
+ Tag.find(tag_one.id)
488
+ end
489
+
490
+ let(:loaded_tag_two) do
491
+ Tag.find(tag_two.id)
492
+ end
493
+
494
+ it "sets the front side of the relation" do
495
+ expect(loaded_tag_one.related).to eq([ tag_two ])
496
+ end
497
+
498
+ it "sets the inverse side of the relation" do
499
+ expect(loaded_tag_two.related).to eq([ tag_one ])
500
+ end
501
+ end
502
+ end
503
+ end
504
+
505
+ context "when association has callbacks" do
506
+
507
+ let(:post) do
508
+ Post.new
509
+ end
510
+
511
+ let(:tag) do
512
+ Tag.new
513
+ end
514
+
515
+ context "when the callback is a before_add" do
516
+
517
+ it "executes the callback" do
518
+ post.tags.send(method, tag)
519
+ expect(post.before_add_called).to be true
520
+ end
521
+
522
+ context "when errors are raised" do
523
+
524
+ before do
525
+ expect(post).to receive(:before_add_tag).and_raise
526
+ begin; post.tags.send(method, tag); rescue; end;
527
+ end
528
+
529
+ it "does not add the document to the relation" do
530
+ expect(post.tags).to be_empty
531
+ end
532
+ end
533
+ end
534
+
535
+ context "when the callback is an after_add" do
536
+
537
+ it "executes the callback" do
538
+ post.tags.send(method, tag)
539
+ expect(post.after_add_called).to be true
540
+ end
541
+
542
+ context "when errors are raised" do
543
+
544
+ before do
545
+ expect(post).to receive(:after_add_tag).and_raise
546
+ begin; post.tags.send(method, tag); rescue; end
547
+ end
548
+
549
+ it "adds the document to the relation" do
550
+ expect(post.tags).to eq([ tag ])
551
+ end
552
+ end
553
+ end
554
+ end
555
+ end
556
+ end
557
+
558
+ describe "#=" do
559
+
560
+ context "when trying to add duplicate entries" do
561
+
562
+ let(:person) do
563
+ Person.new
564
+ end
565
+
566
+ let(:preference) do
567
+ Preference.create!(name: "one")
568
+ end
569
+
570
+ before do
571
+ person.preferences = [ preference, preference ]
572
+ end
573
+
574
+ context "when the document is new" do
575
+
576
+ it "does not add the duplicates" do
577
+ expect(person.preferences).to eq([ preference ])
578
+ end
579
+
580
+ it "does not create duplicate keys" do
581
+ expect(person.preference_ids).to eq([ preference.id ])
582
+ end
583
+ end
584
+
585
+ context "when the document is persisted" do
586
+
587
+ before do
588
+ person.save!
589
+ end
590
+
591
+ it "does not add the duplicates" do
592
+ expect(person.preferences).to eq([ preference ])
593
+ end
594
+
595
+ it "does not create duplicate keys" do
596
+ expect(person.preference_ids).to eq([ preference.id ])
597
+ end
598
+
599
+ it "does not add duplicates on the inverse" do
600
+ expect(preference.people).to eq([ person ])
601
+ end
602
+
603
+ it "does not add duplicate inverse keys" do
604
+ expect(preference.person_ids).to eq([ person.id ])
605
+ end
606
+
607
+ context "when reloading document from db" do
608
+
609
+ let(:from_db) { Preference.last }
610
+
611
+ it "does not create duplicate keys" do
612
+ person.preferences = [ from_db ]
613
+ expect(from_db.person_ids).to eq([ person.id ])
614
+ end
615
+ end
616
+ end
617
+ end
618
+
619
+ context "when the relation is not polymorphic" do
620
+
621
+ context "when the parent and relation are new records" do
622
+
623
+ let(:person) do
624
+ Person.new
625
+ end
626
+
627
+ let(:preference) do
628
+ Preference.new
629
+ end
630
+
631
+ before do
632
+ person.preferences = [ preference ]
633
+ end
634
+
635
+ it "sets the relation" do
636
+ expect(person.preferences).to eq([ preference ])
637
+ end
638
+
639
+ it "sets the foreign key on the relation" do
640
+ expect(person.preference_ids).to eq([ preference.id ])
641
+ end
642
+
643
+ it "sets the foreign key on the inverse relation" do
644
+ expect(preference.person_ids).to eq([ person.id ])
645
+ end
646
+
647
+ it "does not save the target" do
648
+ expect(preference).to be_new_record
649
+ end
650
+ end
651
+
652
+ context "when the parent is new but the relation exists" do
653
+
654
+ let(:person) do
655
+ Person.new
656
+ end
657
+
658
+ let!(:preference) do
659
+ Preference.create!
660
+ end
661
+
662
+ before do
663
+ person.preferences = [ preference ]
664
+ end
665
+
666
+ it "sets the relation" do
667
+ expect(person.preferences).to eq([ preference ])
668
+ end
669
+
670
+ it "sets the foreign key on the relation" do
671
+ expect(person.preference_ids).to eq([ preference.id ])
672
+ end
673
+
674
+ it "sets the foreign key on the inverse relation" do
675
+ expect(preference.person_ids).to eq([ person.id ])
676
+ end
677
+
678
+ context "and the parent is persisted" do
679
+
680
+ before do
681
+ person.save!
682
+ preference.reload
683
+ end
684
+
685
+ it "maintains the relation" do
686
+ expect(person.preferences).to eq([ preference ])
687
+ end
688
+
689
+ it "maintains the foreign key on the relation" do
690
+ expect(person.preference_ids).to eq([ preference.id ])
691
+ end
692
+
693
+ it "maintains the foreign key on the inverse relation" do
694
+ expect(preference.person_ids).to eq([ person.id ])
695
+ end
696
+
697
+ it "maintains the base on the inverse relation" do
698
+ expect(preference.people.first).to eq(person)
699
+ end
700
+ end
701
+ end
702
+
703
+ context "when the parent is not a new record" do
704
+
705
+ let(:person) do
706
+ Person.create!
707
+ end
708
+
709
+ let(:preference) do
710
+ Preference.new
711
+ end
712
+
713
+ before do
714
+ person.preferences = [ preference ]
715
+ end
716
+
717
+ it "sets the relation" do
718
+ expect(person.preferences).to eq([ preference ])
719
+ end
720
+
721
+ it "sets the foreign key on the relation" do
722
+ expect(person.preference_ids).to eq([ preference.id ])
723
+ end
724
+
725
+ it "sets the foreign key on the inverse relation" do
726
+ expect(preference.person_ids).to eq([ person.id ])
727
+ end
728
+
729
+ it "sets the base on the inverse relation" do
730
+ expect(preference.people.first).to eq(person)
731
+ end
732
+
733
+ it "saves the target" do
734
+ expect(preference).to be_persisted
735
+ end
736
+
737
+ it "persists the relation" do
738
+ person.reload.preferences == [ preference ]
739
+ end
740
+
741
+ context "when overwriting an existing relation" do
742
+
743
+ let(:another_preference) do
744
+ Preference.new
745
+ end
746
+
747
+ before do
748
+ person.preferences = [ another_preference ]
749
+ end
750
+
751
+ it "sets the relation" do
752
+ expect(person.preferences).to eq([ another_preference ])
753
+ end
754
+
755
+ it "saves the target" do
756
+ expect(another_preference).to be_persisted
757
+ end
758
+
759
+ it "does not leave foreign keys of the previous relation" do
760
+ expect(person.preference_ids).to eq([ another_preference.id ])
761
+ end
762
+
763
+ it "clears its own key on the foreign relation" do
764
+ expect(preference.person_ids).to be_empty
765
+ end
766
+
767
+ context "and then overwriting it again with the same value" do
768
+
769
+ before do
770
+ person.preferences = [ another_preference ]
771
+ end
772
+
773
+ it "persists the relation between another_preference and person" do
774
+ expect(another_preference.reload.people).to eq([ person ])
775
+ end
776
+
777
+ end
778
+
779
+ context "and person reloaded instead of saved" do
780
+
781
+ before do
782
+ person.reload
783
+ another_preference.reload
784
+ end
785
+
786
+ it "persists the relation between person and another_preference" do
787
+ expect(person.preferences).to eq([ another_preference ])
788
+ end
789
+
790
+ it "persists the relation between another_preference and person" do
791
+ expect(another_preference.people).to eq([ person ])
792
+ end
793
+
794
+ it "no longer has any relation between preference and person" do
795
+ expect(preference.people).to be_empty
796
+ end
797
+ end
798
+
799
+ context "and person is saved" do
800
+
801
+ before do
802
+ person.save!
803
+ person.reload
804
+ another_preference.reload
805
+ end
806
+
807
+ it "persists the relation between person and another_preference" do
808
+ expect(person.preferences).to eq([ another_preference ])
809
+ end
810
+
811
+ it "persists the relation between another_preference and person" do
812
+ expect(another_preference.people).to eq([ person ])
813
+ end
814
+
815
+ it "no longer has any relation between preference and person" do
816
+ expect(preference.people).to be_empty
817
+ end
818
+ end
819
+ end
820
+ end
821
+ end
822
+ end
823
+
824
+ describe "when self-referencing" do
825
+ let!(:parent) do
826
+ Vertex.create!
827
+ end
828
+
829
+ let!(:child) do
830
+ Vertex.create!(parents: [parent])
831
+ end
832
+
833
+ before do
834
+ parent.reload
835
+ child.reload
836
+ end
837
+
838
+ it "sets the parent" do
839
+ expect(child.parents).to include(parent)
840
+ end
841
+
842
+ it "sets the parent id" do
843
+ expect(child.parent_ids).to include(parent.id)
844
+ end
845
+
846
+ it "sets the child" do
847
+ expect(parent.children).to include(child)
848
+ end
849
+
850
+ it "sets the child id" do
851
+ expect(parent.child_ids).to include(child.id)
852
+ end
853
+
854
+ describe "#update" do
855
+ before do
856
+ child.update(parents: [parent])
857
+ end
858
+
859
+ it "sets the parent" do
860
+ expect(child.parents).to include(parent)
861
+ end
862
+
863
+ it "sets the parent id" do
864
+ expect(child.parent_ids).to include(parent.id)
865
+ end
866
+
867
+ it "sets the child" do
868
+ expect(parent.children).to include(child)
869
+ end
870
+
871
+ it "sets the child id" do
872
+ expect(parent.child_ids).to include(child.id)
873
+ end
874
+
875
+ describe "when reloading" do
876
+ before do
877
+ parent.reload
878
+ child.reload
879
+ end
880
+
881
+ it "sets the parent" do
882
+ expect(child.parents).to include(parent)
883
+ end
884
+
885
+ it "sets the parent id" do
886
+ expect(child.parent_ids).to include(parent.id)
887
+ end
888
+
889
+ it "sets the child" do
890
+ expect(parent.children).to include(child)
891
+ end
892
+
893
+ it "sets the child id" do
894
+ expect(parent.child_ids).to include(child.id)
895
+ end
896
+ end
897
+ end
898
+ end
899
+
900
+ [ nil, [] ].each do |value|
901
+
902
+ describe "#= #{value}" do
903
+
904
+ context "when the relation is not polymorphic" do
905
+
906
+ context "when the inverse relation is not defined" do
907
+
908
+ let(:person) do
909
+ Person.new
910
+ end
911
+
912
+ let(:house) do
913
+ House.new
914
+ end
915
+
916
+ before do
917
+ person.houses << house
918
+ person.houses = value
919
+ end
920
+
921
+ it "clears the relation" do
922
+ expect(person.houses).to be_empty
923
+ end
924
+
925
+ it "clears the foreign keys" do
926
+ expect(person.house_ids).to be_empty
927
+ end
928
+ end
929
+
930
+ context "when the parent is a new record" do
931
+
932
+ let(:person) do
933
+ Person.new
934
+ end
935
+
936
+ let(:preference) do
937
+ Preference.new
938
+ end
939
+
940
+ before do
941
+ person.preferences = [ preference ]
942
+ person.preferences = value
943
+ end
944
+
945
+ it "sets the relation to an empty array" do
946
+ expect(person.preferences).to be_empty
947
+ end
948
+
949
+ it "removed the inverse relation" do
950
+ expect(preference.people).to be_empty
951
+ end
952
+
953
+ it "removes the foreign key values" do
954
+ expect(person.preference_ids).to be_empty
955
+ end
956
+
957
+ it "removes the inverse foreign key values" do
958
+ expect(preference.person_ids).to be_empty
959
+ end
960
+ end
961
+
962
+ context "when the parent is not a new record" do
963
+
964
+ context "when the relation has been loaded" do
965
+
966
+ let(:person) do
967
+ Person.create!
968
+ end
969
+
970
+ let(:preference) do
971
+ Preference.new
972
+ end
973
+
974
+ before do
975
+ person.preferences = [ preference ]
976
+ person.preferences = value
977
+ end
978
+
979
+ it "sets the relation to an empty array" do
980
+ expect(person.preferences).to be_empty
981
+ end
982
+
983
+ it "removed the inverse relation" do
984
+ expect(preference.people).to be_empty
985
+ end
986
+
987
+ it "removes the foreign key values" do
988
+ expect(person.preference_ids).to be_empty
989
+ end
990
+
991
+ it "removes the inverse foreign key values" do
992
+ expect(preference.person_ids).to be_empty
993
+ end
994
+
995
+ it "does not delete the target from the database" do
996
+ expect(preference).to_not be_destroyed
997
+ end
998
+ end
999
+
1000
+ context "when the relation has not been loaded" do
1001
+
1002
+ let(:preference) do
1003
+ Preference.new
1004
+ end
1005
+
1006
+ let(:person) do
1007
+ Person.create!.tap do |p|
1008
+ p.preferences = [ preference ]
1009
+ end
1010
+ end
1011
+
1012
+ let!(:from_db) do
1013
+ Person.find(person.id)
1014
+ end
1015
+
1016
+ before do
1017
+ from_db.preferences = value
1018
+ end
1019
+
1020
+ it "sets the relation to an empty array" do
1021
+ expect(from_db.preferences).to be_empty
1022
+ end
1023
+
1024
+ it "removes the foreign key values" do
1025
+ expect(from_db.preference_ids).to be_empty
1026
+ end
1027
+ end
1028
+ end
1029
+ end
1030
+ end
1031
+ end
1032
+
1033
+ [ :build, :new ].each do |method|
1034
+
1035
+ describe "##{method}" do
1036
+
1037
+ context "when the relation is not polymorphic" do
1038
+
1039
+ context "when the parent is a new record" do
1040
+
1041
+ let(:person) do
1042
+ Person.new
1043
+ end
1044
+
1045
+ let!(:preference) do
1046
+ person.preferences.send(method, name: "settings")
1047
+ end
1048
+
1049
+ it "adds the document to the relation" do
1050
+ expect(person.preferences).to eq([ preference ])
1051
+ end
1052
+
1053
+ it "sets the foreign key on the relation" do
1054
+ expect(person.preference_ids).to eq([ preference.id ])
1055
+ end
1056
+
1057
+ it "sets the inverse foreign key on the relation" do
1058
+ expect(preference.person_ids).to eq([ person.id ])
1059
+ end
1060
+
1061
+ it "sets the attributes" do
1062
+ expect(preference.name).to eq("settings")
1063
+ end
1064
+
1065
+ it "does not save the target" do
1066
+ expect(preference).to be_new_record
1067
+ end
1068
+
1069
+ it "adds the correct number of documents" do
1070
+ expect(person.preferences.size).to eq(1)
1071
+ end
1072
+ end
1073
+
1074
+ context "when the parent is not a new record" do
1075
+
1076
+ let(:person) do
1077
+ Person.create!
1078
+ end
1079
+
1080
+ let!(:preference) do
1081
+ person.preferences.send(method, name: "settings")
1082
+ end
1083
+
1084
+ it "adds the document to the relation" do
1085
+ expect(person.preferences).to eq([ preference ])
1086
+ end
1087
+
1088
+ it "sets the foreign key on the relation" do
1089
+ expect(person.preference_ids).to eq([ preference.id ])
1090
+ end
1091
+
1092
+ it "sets the inverse foreign key on the relation" do
1093
+ expect(preference.person_ids).to eq([ person.id ])
1094
+ end
1095
+
1096
+ it "sets the base on the inverse relation" do
1097
+ expect(preference.people).to eq([ person ])
1098
+ end
1099
+
1100
+ it "sets the attributes" do
1101
+ expect(preference.name).to eq("settings")
1102
+ end
1103
+
1104
+ it "does not save the target" do
1105
+ expect(preference).to be_new_record
1106
+ end
1107
+
1108
+ it "adds the correct number of documents" do
1109
+ expect(person.preferences.size).to eq(1)
1110
+ end
1111
+
1112
+ context "when saving the target" do
1113
+
1114
+ before do
1115
+ preference.save!
1116
+ end
1117
+
1118
+ it "persists the parent keys" do
1119
+ expect(person.reload.preference_ids).to eq([ preference.id ])
1120
+ end
1121
+ end
1122
+ end
1123
+ end
1124
+ end
1125
+ end
1126
+
1127
+ describe "#clear" do
1128
+
1129
+ context "when the relation is not polymorphic" do
1130
+
1131
+ context "when the parent has been persisted" do
1132
+
1133
+ let!(:person) do
1134
+ Person.create!
1135
+ end
1136
+
1137
+ context "when the children are persisted" do
1138
+
1139
+ let!(:preference) do
1140
+ person.preferences.create!(name: "settings")
1141
+ end
1142
+
1143
+ let!(:relation) do
1144
+ person.preferences.clear
1145
+ end
1146
+
1147
+ it "clears out the relation" do
1148
+ expect(person.preferences).to be_empty
1149
+ end
1150
+
1151
+ it "removes the parent from the inverse relation" do
1152
+ expect(preference.people).to_not include(person)
1153
+ end
1154
+
1155
+ it "removes the foreign keys" do
1156
+ expect(person.preference_ids).to be_empty
1157
+ end
1158
+
1159
+ it "removes the parent key from the inverse" do
1160
+ expect(preference.person_ids).to_not include(person.id)
1161
+ end
1162
+
1163
+ it "does not delete the documents" do
1164
+ expect(preference).to_not be_destroyed
1165
+ end
1166
+
1167
+ it "persists the nullification" do
1168
+ expect(person.reload.preferences).to be_empty
1169
+ end
1170
+
1171
+ it "returns the relation" do
1172
+ expect(relation).to be_empty
1173
+ end
1174
+ end
1175
+
1176
+ context "when the children are not persisted" do
1177
+
1178
+ let!(:preference) do
1179
+ person.preferences.build(name: "setting")
1180
+ end
1181
+
1182
+ let!(:relation) do
1183
+ person.preferences.clear
1184
+ end
1185
+
1186
+ it "clears out the relation" do
1187
+ expect(person.preferences).to be_empty
1188
+ end
1189
+ end
1190
+ end
1191
+
1192
+ context "when the parent is not persisted" do
1193
+
1194
+ let(:person) do
1195
+ Person.new
1196
+ end
1197
+
1198
+ let!(:preference) do
1199
+ person.preferences.build(name: "setting")
1200
+ end
1201
+
1202
+ let!(:relation) do
1203
+ person.preferences.clear
1204
+ end
1205
+
1206
+ it "clears out the relation" do
1207
+ expect(person.preferences).to be_empty
1208
+ end
1209
+ end
1210
+ end
1211
+
1212
+ context "when the association has callbacks" do
1213
+
1214
+ let(:post) do
1215
+ Post.new
1216
+ end
1217
+
1218
+ let(:tag) do
1219
+ Tag.new
1220
+ end
1221
+
1222
+ before do
1223
+ post.tags << tag
1224
+ end
1225
+
1226
+ context "when the callback is a before_remove" do
1227
+
1228
+ context "when no errors are raised" do
1229
+
1230
+ before do
1231
+ post.tags.clear
1232
+ end
1233
+
1234
+ it "executes the callback" do
1235
+ expect(post.before_remove_called).to be true
1236
+ end
1237
+
1238
+ it "removes the document from the relation" do
1239
+ expect(post.tags).to be_empty
1240
+ end
1241
+ end
1242
+
1243
+ context "when errors are raised" do
1244
+
1245
+ before do
1246
+ expect(post).to receive(:before_remove_tag).and_raise
1247
+ begin; post.tags.clear; rescue; end
1248
+ end
1249
+
1250
+ it "does not remove the document from the relation" do
1251
+ expect(post.tags).to eq([ tag ])
1252
+ end
1253
+ end
1254
+ end
1255
+
1256
+ context "when the callback is an after_remove" do
1257
+
1258
+ context "when no errors are raised" do
1259
+
1260
+ before do
1261
+ post.tags.clear
1262
+ end
1263
+
1264
+ it "executes the callback" do
1265
+ expect(post.after_remove_called).to be true
1266
+ end
1267
+
1268
+ it "removes the document from the relation" do
1269
+ expect(post.tags).to be_empty
1270
+ end
1271
+ end
1272
+
1273
+ context "when errors are raised" do
1274
+
1275
+ before do
1276
+ expect(post).to receive(:after_remove_tag).and_raise
1277
+ begin; post.tags.clear; rescue; end
1278
+ end
1279
+
1280
+ it "removes the document from the relation" do
1281
+ expect(post.tags).to be_empty
1282
+ end
1283
+ end
1284
+ end
1285
+ end
1286
+ end
1287
+
1288
+ describe "#concat" do
1289
+
1290
+ context "when the parent is a new record" do
1291
+
1292
+ let(:person) do
1293
+ Person.new
1294
+ end
1295
+
1296
+ let!(:preference) do
1297
+ Preference.new
1298
+ end
1299
+
1300
+ let(:result) do
1301
+ person.preferences.concat([ preference ])
1302
+ end
1303
+
1304
+ it "returns an array of loaded documents" do
1305
+ expect(result).to eq([ preference ])
1306
+ end
1307
+ end
1308
+
1309
+ context "when the parent is not a new record" do
1310
+
1311
+ let(:person) do
1312
+ Person.create!
1313
+ end
1314
+
1315
+ let!(:preference) do
1316
+ Preference.new
1317
+ end
1318
+
1319
+ let(:result) do
1320
+ person.preferences.concat([ preference ])
1321
+ end
1322
+
1323
+ it "returns an array of loaded documents" do
1324
+ expect(result).to eq([ preference ])
1325
+ end
1326
+ end
1327
+
1328
+ context "when the relations are not polymorphic" do
1329
+
1330
+ context "when the inverse relation is not defined" do
1331
+
1332
+ let(:person) do
1333
+ Person.new
1334
+ end
1335
+
1336
+ let(:house) do
1337
+ House.new
1338
+ end
1339
+
1340
+ before do
1341
+ person.houses.concat([ house ])
1342
+ end
1343
+
1344
+ it "appends the document to the relation" do
1345
+ expect(person.houses).to eq([ house ])
1346
+ end
1347
+
1348
+ it "sets the foreign key on the relation" do
1349
+ expect(person.house_ids).to eq([ house.id ])
1350
+ end
1351
+ end
1352
+
1353
+ context "when appending in a parent create block" do
1354
+
1355
+ let!(:preference) do
1356
+ Preference.create!(name: "testing")
1357
+ end
1358
+
1359
+ let!(:person) do
1360
+ Person.create! do |doc|
1361
+ doc.preferences.concat([ preference ])
1362
+ end
1363
+ end
1364
+
1365
+ it "adds the documents to the relation" do
1366
+ expect(person.preferences).to eq([ preference ])
1367
+ end
1368
+
1369
+ it "sets the foreign key on the relation" do
1370
+ expect(person.preference_ids).to eq([ preference.id ])
1371
+ end
1372
+
1373
+ it "sets the foreign key on the inverse relation" do
1374
+ expect(preference.person_ids).to eq([ person.id ])
1375
+ end
1376
+
1377
+ it "saves the target" do
1378
+ expect(preference).to be_persisted
1379
+ end
1380
+
1381
+ it "adds the correct number of documents" do
1382
+ expect(person.preferences.size).to eq(1)
1383
+ end
1384
+
1385
+ it "persists the link" do
1386
+ expect(person.reload.preferences).to eq([ preference ])
1387
+ end
1388
+ end
1389
+
1390
+ context "when the parent is a new record" do
1391
+
1392
+ let(:person) do
1393
+ Person.new
1394
+ end
1395
+
1396
+ context "when the child is new" do
1397
+
1398
+ let(:preference) do
1399
+ Preference.new
1400
+ end
1401
+
1402
+ before do
1403
+ person.preferences.concat([ preference ])
1404
+ end
1405
+
1406
+ it "adds the documents to the relation" do
1407
+ expect(person.preferences).to eq([ preference ])
1408
+ end
1409
+
1410
+ it "sets the foreign key on the relation" do
1411
+ expect(person.preference_ids).to eq([ preference.id ])
1412
+ end
1413
+
1414
+ it "sets the foreign key on the inverse relation" do
1415
+ expect(preference.person_ids).to eq([ person.id ])
1416
+ end
1417
+
1418
+ it "does not save the target" do
1419
+ expect(preference).to be_new_record
1420
+ end
1421
+
1422
+ it "adds the correct number of documents" do
1423
+ expect(person.preferences.size).to eq(1)
1424
+ end
1425
+
1426
+ context "when appending a second time" do
1427
+
1428
+ before do
1429
+ person.preferences.concat([ preference ])
1430
+ end
1431
+
1432
+ it "does not allow the document to be added again" do
1433
+ expect(person.preferences).to eq([ preference ])
1434
+ end
1435
+
1436
+ it "does not allow duplicate ids" do
1437
+ expect(person.preference_ids).to eq([ preference.id ])
1438
+ end
1439
+ end
1440
+ end
1441
+
1442
+ context "when the child is already persisted" do
1443
+
1444
+ let!(:persisted) do
1445
+ Preference.create!(name: "testy")
1446
+ end
1447
+
1448
+ let(:preference) do
1449
+ Preference.first
1450
+ end
1451
+
1452
+ before do
1453
+ person.preferences.concat([ preference ])
1454
+ person.save!
1455
+ end
1456
+
1457
+ it "adds the documents to the relation" do
1458
+ expect(person.preferences).to eq([ preference ])
1459
+ end
1460
+
1461
+ it "sets the foreign key on the relation" do
1462
+ expect(person.preference_ids).to eq([ preference.id ])
1463
+ end
1464
+
1465
+ it "sets the foreign key on the inverse relation" do
1466
+ expect(preference.person_ids).to eq([ person.id ])
1467
+ end
1468
+
1469
+ it "saves the target" do
1470
+ expect(preference).to be_persisted
1471
+ end
1472
+
1473
+ it "adds the correct number of documents" do
1474
+ expect(person.preferences.size).to eq(1)
1475
+ end
1476
+
1477
+ it "persists the link" do
1478
+ expect(person.reload.preferences).to eq([ preference ])
1479
+ end
1480
+ end
1481
+
1482
+ context "when setting via the associated ids" do
1483
+
1484
+ let!(:persisted) do
1485
+ Preference.create!(name: "testy")
1486
+ end
1487
+
1488
+ let(:preference) do
1489
+ Preference.first
1490
+ end
1491
+
1492
+ let(:person) do
1493
+ Person.new(preference_ids: [ preference.id ])
1494
+ end
1495
+
1496
+ before do
1497
+ person.save!
1498
+ end
1499
+
1500
+ it "adds the documents to the relation" do
1501
+ expect(person.preferences).to eq([ preference ])
1502
+ end
1503
+
1504
+ it "sets the foreign key on the relation" do
1505
+ expect(person.preference_ids).to eq([ preference.id ])
1506
+ end
1507
+
1508
+ it "sets the foreign key on the inverse relation" do
1509
+ expect(preference.reload.person_ids).to eq([ person.id ])
1510
+ end
1511
+
1512
+ it "adds the correct number of documents" do
1513
+ expect(person.preferences.size).to eq(1)
1514
+ end
1515
+
1516
+ it "persists the link" do
1517
+ expect(person.reload.preferences).to eq([ preference ])
1518
+ end
1519
+ end
1520
+ end
1521
+
1522
+ context "when the parent is not a new record" do
1523
+
1524
+ let(:person) do
1525
+ Person.create!
1526
+ end
1527
+
1528
+ let(:preference) do
1529
+ Preference.new
1530
+ end
1531
+
1532
+ before do
1533
+ person.preferences.concat([ preference ])
1534
+ end
1535
+
1536
+ it "adds the documents to the relation" do
1537
+ expect(person.preferences).to eq([ preference ])
1538
+ end
1539
+
1540
+ it "sets the foreign key on the relation" do
1541
+ expect(person.preference_ids).to eq([ preference.id ])
1542
+ end
1543
+
1544
+ it "sets the foreign key on the inverse relation" do
1545
+ expect(preference.person_ids).to eq([ person.id ])
1546
+ end
1547
+
1548
+ it "sets the base on the inverse relation" do
1549
+ expect(preference.people).to eq([ person ])
1550
+ end
1551
+
1552
+ it "sets the same instance on the inverse relation" do
1553
+ expect(preference.people.first).to eql(person)
1554
+ end
1555
+
1556
+ it "saves the target" do
1557
+ expect(preference).to_not be_new_record
1558
+ end
1559
+
1560
+ it "adds the document to the target" do
1561
+ expect(person.preferences.count).to eq(1)
1562
+ end
1563
+
1564
+ context "when documents already exist on the relation" do
1565
+
1566
+ let(:preference_two) do
1567
+ Preference.new
1568
+ end
1569
+
1570
+ before do
1571
+ person.preferences.concat([ preference_two ])
1572
+ end
1573
+
1574
+ it "adds the documents to the relation" do
1575
+ expect(person.preferences).to eq([ preference, preference_two ])
1576
+ end
1577
+
1578
+ it "sets the foreign key on the relation" do
1579
+ expect(person.preference_ids).to eq([ preference.id, preference_two.id ])
1580
+ end
1581
+
1582
+ it "sets the foreign key on the inverse relation" do
1583
+ expect(preference_two.person_ids).to eq([ person.id ])
1584
+ end
1585
+
1586
+ it "sets the base on the inverse relation" do
1587
+ expect(preference_two.people).to eq([ person ])
1588
+ end
1589
+
1590
+ it "sets the same instance on the inverse relation" do
1591
+ expect(preference_two.people.first).to eql(person)
1592
+ end
1593
+
1594
+ it "saves the target" do
1595
+ expect(preference).to_not be_new_record
1596
+ end
1597
+
1598
+ it "adds the document to the target" do
1599
+ expect(person.preferences.count).to eq(2)
1600
+ end
1601
+ end
1602
+ end
1603
+
1604
+ context "when both sides have been persisted" do
1605
+
1606
+ let(:person) do
1607
+ Person.create!
1608
+ end
1609
+
1610
+ let(:event) do
1611
+ Event.create!
1612
+ end
1613
+
1614
+ before do
1615
+ person.administrated_events.concat([ event ])
1616
+ end
1617
+
1618
+ it "sets the front side of the relation" do
1619
+ expect(person.administrated_events).to eq([ event ])
1620
+ end
1621
+
1622
+ it "sets the inverse side of the relation" do
1623
+ expect(event.administrators(true)).to eq([ person ])
1624
+ end
1625
+
1626
+ context "when reloading" do
1627
+
1628
+ it "sets the front side of the relation" do
1629
+ expect(person.reload.administrated_events).to eq([ event ])
1630
+ end
1631
+
1632
+ it "sets the inverse side of the relation" do
1633
+ expect(event.reload.administrators).to eq([ person ])
1634
+ end
1635
+ end
1636
+
1637
+ context "when performing a new database query" do
1638
+
1639
+ let(:loaded_person) do
1640
+ Person.find(person.id)
1641
+ end
1642
+
1643
+ let(:loaded_event) do
1644
+ Event.find(event.id)
1645
+ end
1646
+
1647
+ it "sets the front side of the relation" do
1648
+ expect(loaded_person.administrated_events).to eq([ event ])
1649
+ end
1650
+
1651
+ it "sets the inverse side of the relation" do
1652
+ expect(loaded_event.administrators).to eq([ person ])
1653
+ end
1654
+ end
1655
+ end
1656
+
1657
+ context "when the relation also includes a has_many relation" do
1658
+
1659
+ let(:artwork) do
1660
+ Artwork.create!
1661
+ end
1662
+
1663
+ let(:exhibition) do
1664
+ Exhibition.create!
1665
+ end
1666
+
1667
+ let(:exhibitor) do
1668
+ Exhibitor.create!(exhibition: exhibition)
1669
+ end
1670
+
1671
+ before do
1672
+ artwork.exhibitors.concat([ exhibitor ])
1673
+ end
1674
+
1675
+ it "creates a single artwork object" do
1676
+ expect(Artwork.count).to eq(1)
1677
+ end
1678
+ end
1679
+
1680
+ context "when the relation is self referencing" do
1681
+
1682
+ let(:tag_one) do
1683
+ Tag.create!(text: "one")
1684
+ end
1685
+
1686
+ let(:tag_two) do
1687
+ Tag.create!(text: "two")
1688
+ end
1689
+
1690
+ before do
1691
+ tag_one.related.concat([ tag_two ])
1692
+ end
1693
+
1694
+ it "sets the front side of the relation" do
1695
+ expect(tag_one.related).to eq([ tag_two ])
1696
+ end
1697
+
1698
+ it "sets the inverse side of the relation" do
1699
+ expect(tag_two.related(true)).to eq([ tag_one ])
1700
+ end
1701
+
1702
+ context "when reloading" do
1703
+
1704
+ it "sets the front side of the relation" do
1705
+ expect(tag_one.reload.related).to eq([ tag_two ])
1706
+ end
1707
+
1708
+ it "sets the inverse side of the relation" do
1709
+ expect(tag_two.reload.related).to eq([ tag_one ])
1710
+ end
1711
+ end
1712
+
1713
+ context "when performing a new database query" do
1714
+
1715
+ let(:loaded_tag_one) do
1716
+ Tag.find(tag_one.id)
1717
+ end
1718
+
1719
+ let(:loaded_tag_two) do
1720
+ Tag.find(tag_two.id)
1721
+ end
1722
+
1723
+ it "sets the front side of the relation" do
1724
+ expect(loaded_tag_one.related).to eq([ tag_two ])
1725
+ end
1726
+
1727
+ it "sets the inverse side of the relation" do
1728
+ expect(loaded_tag_two.related).to eq([ tag_one ])
1729
+ end
1730
+ end
1731
+ end
1732
+ end
1733
+ end
1734
+
1735
+ describe "#count" do
1736
+
1737
+ let(:person) do
1738
+ Person.create!
1739
+ end
1740
+
1741
+ context "when nothing exists on the relation" do
1742
+
1743
+ context "when the document is destroyed" do
1744
+
1745
+ before do
1746
+ Meat.create!
1747
+ end
1748
+
1749
+ let!(:sandwich) do
1750
+ Sandwich.create!
1751
+ end
1752
+
1753
+ it "returns zero" do
1754
+ sandwich.destroy
1755
+ expect(sandwich.meats.count).to eq(0)
1756
+ end
1757
+ end
1758
+ end
1759
+
1760
+ describe "#any?" do
1761
+
1762
+ let(:person) do
1763
+ Person.create!
1764
+ end
1765
+
1766
+ context "when nothing exists on the relation" do
1767
+
1768
+ context "when no document is added" do
1769
+
1770
+ let!(:sandwich) do
1771
+ Sandwich.create!
1772
+ end
1773
+
1774
+ it "returns false" do
1775
+ expect(sandwich.meats.any?).to be false
1776
+ end
1777
+ end
1778
+
1779
+ context "when the document is destroyed" do
1780
+
1781
+ before do
1782
+ Meat.create!
1783
+ end
1784
+
1785
+ let!(:sandwich) do
1786
+ Sandwich.create!
1787
+ end
1788
+
1789
+ it "returns false" do
1790
+ sandwich.destroy
1791
+ expect(sandwich.meats.any?).to be false
1792
+ end
1793
+ end
1794
+ end
1795
+ end
1796
+
1797
+ context "when documents have been persisted" do
1798
+
1799
+ let!(:preference) do
1800
+ person.preferences.create!(name: "setting")
1801
+ end
1802
+
1803
+ it "returns the number of persisted documents" do
1804
+ expect(person.preferences.count).to eq(1)
1805
+ end
1806
+ end
1807
+
1808
+ context "when appending to a loaded relation" do
1809
+
1810
+ let!(:preference) do
1811
+ person.preferences.create!(name: "setting")
1812
+ end
1813
+
1814
+ before do
1815
+ person.preferences.count
1816
+ person.preferences << Preference.create!(name: "two")
1817
+ end
1818
+
1819
+ it "returns the number of persisted documents" do
1820
+ expect(person.preferences.count).to eq(2)
1821
+ end
1822
+ end
1823
+
1824
+ context "when documents have not been persisted" do
1825
+
1826
+ let!(:preference) do
1827
+ person.preferences.build(name: "settings")
1828
+ end
1829
+
1830
+ it "returns 0" do
1831
+ expect(person.preferences.count).to eq(0)
1832
+ end
1833
+ end
1834
+
1835
+ context "when new documents exist in the database" do
1836
+
1837
+ context "when the documents are part of the relation" do
1838
+
1839
+ before do
1840
+ Preference.create!(person_ids: [ person.id ])
1841
+ end
1842
+
1843
+ it "returns the count from the db" do
1844
+ expect(person.reload.preferences.count).to eq(1)
1845
+ end
1846
+ end
1847
+
1848
+ context "when the documents are not part of the relation" do
1849
+
1850
+ before do
1851
+ Preference.create!
1852
+ end
1853
+
1854
+ it "returns the count from the db" do
1855
+ expect(person.preferences.count).to eq(0)
1856
+ end
1857
+ end
1858
+ end
1859
+
1860
+ context "when the inverse relation is not defined" do
1861
+
1862
+ context "when documents have been persisted" do
1863
+
1864
+ let!(:house) do
1865
+ person.houses.create!(name: "Wayne Manor")
1866
+ end
1867
+
1868
+ it "returns the number of persisted documents" do
1869
+ expect(person.houses.count).to eq(1)
1870
+ end
1871
+ end
1872
+
1873
+ context "when documents have not been persisted" do
1874
+
1875
+ let!(:house) do
1876
+ person.houses.build(name: "Ryugyong Hotel")
1877
+ end
1878
+
1879
+ it "returns 0" do
1880
+ expect(person.preferences.count).to eq(0)
1881
+ end
1882
+ end
1883
+ end
1884
+ end
1885
+
1886
+ describe "#any?" do
1887
+
1888
+ let(:sandwich) do
1889
+ Sandwich.create!
1890
+ end
1891
+
1892
+ context "when nothing exists on the relation" do
1893
+
1894
+ context "when no document is added" do
1895
+
1896
+ let!(:sandwich) do
1897
+ Sandwich.create!
1898
+ end
1899
+
1900
+ it "returns false" do
1901
+ expect(sandwich.meats.any?).to be false
1902
+ end
1903
+ end
1904
+
1905
+ context "when the document is destroyed" do
1906
+
1907
+ before do
1908
+ Meat.create!
1909
+ end
1910
+
1911
+ let!(:sandwich) do
1912
+ Sandwich.create!
1913
+ end
1914
+
1915
+ it "returns false" do
1916
+ sandwich.destroy
1917
+ expect(sandwich.meats.any?).to be false
1918
+ end
1919
+ end
1920
+ end
1921
+
1922
+ context "when appending to a relation and _loaded/_unloaded are empty" do
1923
+
1924
+ let!(:sandwich) do
1925
+ Sandwich.create!
1926
+ end
1927
+
1928
+ before do
1929
+ sandwich.meats << Meat.new
1930
+ end
1931
+
1932
+ it "returns true" do
1933
+ expect(sandwich.meats.any?).to be true
1934
+ end
1935
+ end
1936
+
1937
+ context "when appending to a relation in a transaction" do
1938
+ require_transaction_support
1939
+
1940
+ let!(:sandwich) do
1941
+ Sandwich.create!
1942
+ end
1943
+
1944
+ it "returns true" do
1945
+ sandwich.with_session do |session|
1946
+ session.with_transaction do
1947
+ expect{ sandwich.meats << Meat.new }.to_not raise_error
1948
+ expect(sandwich.meats.any?).to be true
1949
+ end
1950
+ end
1951
+ end
1952
+ end
1953
+
1954
+ context "when documents have been persisted" do
1955
+
1956
+ let!(:meat) do
1957
+ sandwich.meats.create!
1958
+ end
1959
+
1960
+ it "returns true" do
1961
+ expect(sandwich.meats.any?).to be true
1962
+ end
1963
+ end
1964
+
1965
+ context "when documents have not been persisted" do
1966
+
1967
+ let!(:meat) do
1968
+ sandwich.meats.build
1969
+ end
1970
+
1971
+ it "returns false" do
1972
+ expect(sandwich.meats.any?).to be true
1973
+ end
1974
+ end
1975
+
1976
+ context "when new documents exist in the database" do
1977
+ before do
1978
+ Meat.create!(sandwiches: [sandwich])
1979
+ end
1980
+
1981
+ it "returns true" do
1982
+ expect(sandwich.meats.any?).to be true
1983
+ end
1984
+ end
1985
+ end
1986
+
1987
+ [ :create, :create! ].each do |method|
1988
+
1989
+ describe "##{method}" do
1990
+
1991
+ context "when the relation is not polymorphic" do
1992
+
1993
+ context "when using string keys" do
1994
+
1995
+ let(:agent) do
1996
+ Agent.create!(number: "007")
1997
+ end
1998
+
1999
+ before do
2000
+ agent.accounts.send(method, name: "test again")
2001
+ end
2002
+
2003
+ it "does not convert the string key to an object id" do
2004
+ expect(agent.account_ids).to eq([ "test-again" ])
2005
+ end
2006
+ end
2007
+
2008
+ context "when the parent is a new record" do
2009
+
2010
+ let(:person) do
2011
+ Person.new
2012
+ end
2013
+
2014
+ it "raises an unsaved document error" do
2015
+ expect {
2016
+ person.preferences.send(method, name: "Testing")
2017
+ }.to raise_error(Mongoid::Errors::UnsavedDocument)
2018
+ end
2019
+ end
2020
+
2021
+ context "when the parent is not a new record" do
2022
+
2023
+ let(:person) do
2024
+ Person.send(method)
2025
+ end
2026
+
2027
+ let!(:preference) do
2028
+ person.preferences.send(method, name: "Testing")
2029
+ end
2030
+
2031
+ it "sets the foreign key on the relation" do
2032
+ expect(person.preference_ids).to eq([ preference.id ])
2033
+ end
2034
+
2035
+ it "sets the foreign key on the inverse relation" do
2036
+ expect(preference.person_ids).to eq([ person.id ])
2037
+ end
2038
+
2039
+ it "adds the document" do
2040
+ expect(person.preferences).to eq([ preference ])
2041
+ end
2042
+
2043
+ it "sets the base on the inverse relation" do
2044
+ expect(preference.people).to eq([ person ])
2045
+ end
2046
+
2047
+ it "sets the attributes" do
2048
+ expect(preference.name).to eq("Testing")
2049
+ end
2050
+
2051
+ it "saves the target" do
2052
+ expect(preference).to be_persisted
2053
+ end
2054
+
2055
+ it "adds the document to the target" do
2056
+ expect(person.preferences.count).to eq(1)
2057
+ end
2058
+
2059
+ it "does not duplicate documents" do
2060
+ expect(person.reload.preferences.count).to eq(1)
2061
+ end
2062
+
2063
+ it "does not duplicate ids" do
2064
+ expect(person.reload.preference_ids.count).to eq(1)
2065
+ end
2066
+ end
2067
+ end
2068
+ end
2069
+ end
2070
+
2071
+ describe "#create!" do
2072
+
2073
+ context "when validation fails" do
2074
+
2075
+ let(:person) do
2076
+ Person.create!
2077
+ end
2078
+
2079
+ context "when the relation is not polymorphic" do
2080
+
2081
+ it "raises an error" do
2082
+ expect {
2083
+ person.preferences.create!(name: "a")
2084
+ }.to raise_error(Mongoid::Errors::Validations)
2085
+ end
2086
+ end
2087
+ end
2088
+ end
2089
+
2090
+ describe "#delete" do
2091
+
2092
+ let(:person) do
2093
+ Person.create!
2094
+ end
2095
+
2096
+ let(:preference_one) do
2097
+ Preference.create!(name: "Testing")
2098
+ end
2099
+
2100
+ let(:preference_two) do
2101
+ Preference.create!(name: "Test")
2102
+ end
2103
+
2104
+ before do
2105
+ person.preferences << [ preference_one, preference_two ]
2106
+ end
2107
+
2108
+ context "when the document exists" do
2109
+
2110
+ let!(:deleted) do
2111
+ person.preferences.delete(preference_one)
2112
+ end
2113
+
2114
+ it "removes the document from the relation" do
2115
+ expect(person.preferences).to eq([ preference_two ])
2116
+ end
2117
+
2118
+ it "returns the document" do
2119
+ expect(deleted).to eq(preference_one)
2120
+ end
2121
+
2122
+ it "removes the document key from the foreign key" do
2123
+ expect(person.preference_ids).to eq([ preference_two.id ])
2124
+ end
2125
+
2126
+ it "removes the inverse reference" do
2127
+ expect(deleted.reload.people).to be_empty
2128
+ end
2129
+
2130
+ it "removes the base id from the inverse keys" do
2131
+ expect(deleted.reload.person_ids).to be_empty
2132
+ end
2133
+
2134
+ context "and person and preferences are reloaded" do
2135
+
2136
+ before do
2137
+ person.reload
2138
+ preference_one.reload
2139
+ preference_two.reload
2140
+ end
2141
+
2142
+ it "nullifies the deleted preference" do
2143
+ expect(person.preferences).to eq([ preference_two ])
2144
+ end
2145
+
2146
+ it "retains the ids for one preference" do
2147
+ expect(person.preference_ids).to eq([ preference_two.id ])
2148
+ end
2149
+ end
2150
+ end
2151
+
2152
+ context "when the document does not exist" do
2153
+
2154
+ let!(:deleted) do
2155
+ person.preferences.delete(Preference.new)
2156
+ end
2157
+
2158
+ it "returns nil" do
2159
+ expect(deleted).to be_nil
2160
+ end
2161
+
2162
+ it "does not modify the relation" do
2163
+ expect(person.preferences).to eq([ preference_one, preference_two ])
2164
+ end
2165
+
2166
+ it "does not modify the keys" do
2167
+ expect(person.preference_ids).to eq([ preference_one.id, preference_two.id ])
2168
+ end
2169
+ end
2170
+
2171
+ context "when :dependent => :nullify is set" do
2172
+
2173
+ context "when :inverse_of is set" do
2174
+
2175
+ let(:event) do
2176
+ Event.create!
2177
+ end
2178
+
2179
+ before do
2180
+ person.administrated_events << [ event ]
2181
+ end
2182
+
2183
+ it "deletes the document" do
2184
+ expect(event.delete).to be true
2185
+ end
2186
+ end
2187
+ end
2188
+
2189
+ context "when the relationships are self referencing" do
2190
+
2191
+ let(:tag_one) do
2192
+ Tag.create!(text: "one")
2193
+ end
2194
+
2195
+ let(:tag_two) do
2196
+ Tag.create!(text: "two")
2197
+ end
2198
+
2199
+ before do
2200
+ tag_one.related << tag_two
2201
+ end
2202
+
2203
+ context "when deleting without reloading" do
2204
+
2205
+ let!(:deleted) do
2206
+ tag_one.related.delete(tag_two)
2207
+ end
2208
+
2209
+ it "deletes the document from the relation" do
2210
+ expect(tag_one.related).to be_empty
2211
+ end
2212
+
2213
+ it "deletes the foreign key from the relation" do
2214
+ expect(tag_one.related_ids).to be_empty
2215
+ end
2216
+
2217
+ it "removes the reference from the inverse" do
2218
+ expect(deleted.related).to be_empty
2219
+ end
2220
+
2221
+ it "removes the foreign keys from the inverse" do
2222
+ expect(deleted.related_ids).to be_empty
2223
+ end
2224
+ end
2225
+
2226
+ context "when deleting with reloading" do
2227
+
2228
+ context "when deleting from the front side" do
2229
+
2230
+ let(:reloaded) do
2231
+ tag_one.reload
2232
+ end
2233
+
2234
+ let!(:deleted) do
2235
+ reloaded.related.delete(tag_two)
2236
+ end
2237
+
2238
+ it "deletes the document from the relation" do
2239
+ expect(reloaded.related).to be_empty
2240
+ end
2241
+
2242
+ it "deletes the foreign key from the relation" do
2243
+ expect(reloaded.related_ids).to be_empty
2244
+ end
2245
+
2246
+ it "removes the reference from the inverse" do
2247
+ expect(deleted.related).to be_empty
2248
+ end
2249
+
2250
+ it "removes the foreign keys from the inverse" do
2251
+ expect(deleted.related_ids).to be_empty
2252
+ end
2253
+ end
2254
+
2255
+ context "when deleting from the inverse side" do
2256
+
2257
+ let(:reloaded) do
2258
+ tag_two.reload
2259
+ end
2260
+
2261
+ let!(:deleted) do
2262
+ reloaded.related.delete(tag_one)
2263
+ end
2264
+
2265
+ it "deletes the document from the relation" do
2266
+ expect(reloaded.related).to be_empty
2267
+ end
2268
+
2269
+ it "deletes the foreign key from the relation" do
2270
+ expect(reloaded.related_ids).to be_empty
2271
+ end
2272
+
2273
+ it "removes the foreign keys from the inverse" do
2274
+ expect(deleted.related_ids).to be_empty
2275
+ end
2276
+ end
2277
+ end
2278
+ end
2279
+
2280
+ context "when the association has callbacks" do
2281
+
2282
+ let(:post) do
2283
+ Post.new
2284
+ end
2285
+
2286
+ let(:tag) do
2287
+ Tag.new
2288
+ end
2289
+
2290
+ before do
2291
+ post.tags << tag
2292
+ end
2293
+
2294
+ context "when the callback is a before_remove" do
2295
+
2296
+ context "when there are no errors" do
2297
+
2298
+ before do
2299
+ post.tags.delete tag
2300
+ end
2301
+
2302
+ it "executes the callback" do
2303
+ expect(post.before_remove_called).to be true
2304
+ end
2305
+
2306
+ it "removes the document from the relation" do
2307
+ expect(post.tags).to be_empty
2308
+ end
2309
+ end
2310
+
2311
+ context "when errors are raised" do
2312
+
2313
+ before do
2314
+ expect(post).to receive(:before_remove_tag).and_raise
2315
+ begin; post.tags.delete(tag); rescue; end
2316
+ end
2317
+
2318
+ it "does not remove the document from the relation" do
2319
+ expect(post.tags).to eq([ tag ])
2320
+ end
2321
+ end
2322
+ end
2323
+
2324
+ context "when the callback is an after_remove" do
2325
+
2326
+ context "when no errors are raised" do
2327
+
2328
+ before do
2329
+ post.tags.delete(tag)
2330
+ end
2331
+
2332
+ it "executes the callback" do
2333
+ expect(post.after_remove_called).to be true
2334
+ end
2335
+
2336
+ it "removes the document from the relation" do
2337
+ expect(post.tags).to be_empty
2338
+ end
2339
+ end
2340
+
2341
+ context "when errors are raised" do
2342
+
2343
+ before do
2344
+ expect(post).to receive(:after_remove_tag).and_raise
2345
+ begin; post.tags.delete(tag); rescue; end
2346
+ end
2347
+
2348
+ it "removes the document from the relation" do
2349
+ expect(post.tags).to be_empty
2350
+ end
2351
+ end
2352
+ end
2353
+ end
2354
+ end
2355
+
2356
+ [ :delete_all, :destroy_all ].each do |method|
2357
+
2358
+ describe "##{method}" do
2359
+
2360
+ context "when the relation is not polymorphic" do
2361
+
2362
+ context "when conditions are provided" do
2363
+
2364
+ let(:person) do
2365
+ Person.create!
2366
+ end
2367
+
2368
+ let!(:preference_one) do
2369
+ person.preferences.create!(name: "Testing")
2370
+ end
2371
+
2372
+ let!(:preference_two) do
2373
+ person.preferences.create!(name: "Test")
2374
+ end
2375
+
2376
+ let!(:deleted) do
2377
+ person.preferences.send(
2378
+ method,
2379
+ { name: "Testing" }
2380
+ )
2381
+ end
2382
+
2383
+ it "removes the correct preferences" do
2384
+ expect(person.preferences.count).to eq(1)
2385
+ end
2386
+
2387
+ it "deletes the documents from the database" do
2388
+ expect(Preference.where(name: "Testing").count).to eq(0)
2389
+ end
2390
+
2391
+ it "returns the number of documents deleted" do
2392
+ expect(deleted).to eq(1)
2393
+ end
2394
+
2395
+ it "removes the ids from the foreign key" do
2396
+ expect(person.preference_ids).to eq([ preference_two.id ])
2397
+ end
2398
+ end
2399
+
2400
+ context "when conditions are not provided" do
2401
+
2402
+ let(:person) do
2403
+ Person.create!.tap do |person|
2404
+ person.preferences.create!(name: "Testing")
2405
+ person.preferences.create!(name: "Test")
2406
+ end
2407
+ end
2408
+
2409
+ let!(:deleted) do
2410
+ person.preferences.send(method)
2411
+ end
2412
+
2413
+ it "removes the correct preferences" do
2414
+ expect(person.preferences.count).to eq(0)
2415
+ end
2416
+
2417
+ it "deletes the documents from the database" do
2418
+ expect(Preference.count).to eq(0)
2419
+ end
2420
+
2421
+ it "returns the number of documents deleted" do
2422
+ expect(deleted).to eq(2)
2423
+ end
2424
+ end
2425
+ end
2426
+ end
2427
+ end
2428
+
2429
+ describe ".embedded?" do
2430
+
2431
+ it "returns false" do
2432
+ expect(described_class).to_not be_embedded
2433
+ end
2434
+ end
2435
+
2436
+ describe "#exists?" do
2437
+
2438
+ let!(:person) do
2439
+ Person.create!
2440
+ end
2441
+
2442
+ context "when documents exist in the database" do
2443
+
2444
+ before do
2445
+ person.preferences.create!
2446
+ end
2447
+
2448
+ it "returns true" do
2449
+ expect(person.preferences.exists?).to be true
2450
+ end
2451
+ end
2452
+
2453
+ context "when no documents exist in the database" do
2454
+
2455
+ before do
2456
+ person.preferences.build
2457
+ end
2458
+
2459
+ it "returns false" do
2460
+ expect(person.preferences.exists?).to be false
2461
+ end
2462
+ end
2463
+ end
2464
+
2465
+ describe "#find" do
2466
+
2467
+ context "when the relation is not polymorphic" do
2468
+
2469
+ let(:person) do
2470
+ Person.create!
2471
+ end
2472
+
2473
+ let!(:preference_one) do
2474
+ person.preferences.create!(name: "Test")
2475
+ end
2476
+
2477
+ let!(:preference_two) do
2478
+ person.preferences.create!(name: "OMG I has relations")
2479
+ end
2480
+
2481
+ let!(:unrelated_pref) do
2482
+ Preference.create!(name: "orphan annie")
2483
+ end
2484
+
2485
+ let!(:unrelated_pref_two) do
2486
+ Preference.create!(name: "orphan two")
2487
+ end
2488
+
2489
+ context "when providing an id" do
2490
+
2491
+ context "when the id matches" do
2492
+
2493
+ let(:preference) do
2494
+ person.preferences.find(preference_one.id)
2495
+ end
2496
+
2497
+ it "returns the matching document" do
2498
+ expect(preference).to eq(preference_one)
2499
+ end
2500
+ end
2501
+
2502
+ context "when the id matches an unreferenced document" do
2503
+
2504
+ let(:preference) do
2505
+ person.preferences.find(unrelated_pref.id)
2506
+ end
2507
+
2508
+ it "raises an error" do
2509
+ expect {
2510
+ preference
2511
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2512
+ end
2513
+ end
2514
+
2515
+ context "when the id does not match" do
2516
+
2517
+ context "when config set to raise error" do
2518
+
2519
+ before do
2520
+ Mongoid.raise_not_found_error = true
2521
+ end
2522
+
2523
+ it "raises an error" do
2524
+ expect {
2525
+ person.preferences.find(BSON::ObjectId.new)
2526
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2527
+ end
2528
+ end
2529
+
2530
+ context "when config set not to raise error" do
2531
+
2532
+ let(:preference) do
2533
+ person.preferences.find(BSON::ObjectId.new)
2534
+ end
2535
+
2536
+ before do
2537
+ Mongoid.raise_not_found_error = false
2538
+ end
2539
+
2540
+ after do
2541
+ Mongoid.raise_not_found_error = true
2542
+ end
2543
+
2544
+ it "returns nil" do
2545
+ expect(preference).to be_nil
2546
+ end
2547
+ end
2548
+ end
2549
+ end
2550
+
2551
+ context "when providing an array of ids" do
2552
+
2553
+ context "when the ids match" do
2554
+
2555
+ let(:preferences) do
2556
+ person.preferences.find([ preference_one.id, preference_two.id ])
2557
+ end
2558
+
2559
+ it "returns the matching documents" do
2560
+ expect(preferences).to eq([ preference_one, preference_two ])
2561
+ end
2562
+ end
2563
+
2564
+ context "when the ids match unreferenced documents" do
2565
+
2566
+ let(:preferences) do
2567
+ person.preferences.find(
2568
+ [ unrelated_pref.id, unrelated_pref_two.id ]
2569
+ )
2570
+ end
2571
+
2572
+ it "raises an error" do
2573
+ expect {
2574
+ preferences
2575
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2576
+ end
2577
+ end
2578
+
2579
+ context "when the ids do not match" do
2580
+
2581
+ context "when config set to raise error" do
2582
+
2583
+ before do
2584
+ Mongoid.raise_not_found_error = true
2585
+ end
2586
+
2587
+ it "raises an error" do
2588
+ expect {
2589
+ person.preferences.find([ BSON::ObjectId.new ])
2590
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
2591
+ end
2592
+ end
2593
+
2594
+ context "when config set not to raise error" do
2595
+
2596
+ let(:preferences) do
2597
+ person.preferences.find([ BSON::ObjectId.new ])
2598
+ end
2599
+
2600
+ before do
2601
+ Mongoid.raise_not_found_error = false
2602
+ end
2603
+
2604
+ after do
2605
+ Mongoid.raise_not_found_error = true
2606
+ end
2607
+
2608
+ it "returns an empty array" do
2609
+ expect(preferences).to be_empty
2610
+ end
2611
+ end
2612
+ end
2613
+ end
2614
+ end
2615
+ end
2616
+
2617
+ describe "#find_or_create_by" do
2618
+
2619
+ context "when the relation is not polymorphic" do
2620
+
2621
+ let(:person) do
2622
+ Person.create!
2623
+ end
2624
+
2625
+ let!(:preference) do
2626
+ person.preferences.create!(name: "Testing")
2627
+ end
2628
+
2629
+ context "when the document exists" do
2630
+
2631
+ let(:found) do
2632
+ person.preferences.find_or_create_by(name: "Testing")
2633
+ end
2634
+
2635
+ it "returns the document" do
2636
+ expect(found).to eq(preference)
2637
+ end
2638
+ end
2639
+
2640
+ context "when the document does not exist" do
2641
+
2642
+ let(:found) do
2643
+ person.preferences.find_or_create_by(name: "Test")
2644
+ end
2645
+
2646
+ it "sets the new document attributes" do
2647
+ expect(found.name).to eq("Test")
2648
+ end
2649
+
2650
+ it "returns a newly persisted document" do
2651
+ expect(found).to be_persisted
2652
+ end
2653
+ end
2654
+ end
2655
+ end
2656
+
2657
+ describe "#find_or_create_by!" do
2658
+
2659
+ context "when the relation is not polymorphic" do
2660
+
2661
+ let(:person) do
2662
+ Person.create!
2663
+ end
2664
+
2665
+ let!(:preference) do
2666
+ person.preferences.create!(name: "Testing")
2667
+ end
2668
+
2669
+ context "when the document exists" do
2670
+
2671
+ let(:found) do
2672
+ person.preferences.find_or_create_by!(name: "Testing")
2673
+ end
2674
+
2675
+ it "returns the document" do
2676
+ expect(found).to eq(preference)
2677
+ end
2678
+ end
2679
+
2680
+ context "when the document does not exist" do
2681
+
2682
+ let(:found) do
2683
+ person.preferences.find_or_create_by!(name: "Test")
2684
+ end
2685
+
2686
+ it "sets the new document attributes" do
2687
+ expect(found.name).to eq("Test")
2688
+ end
2689
+
2690
+ it "returns a newly persisted document" do
2691
+ expect(found).to be_persisted
2692
+ end
2693
+
2694
+ context "when validation fails" do
2695
+
2696
+ it "raises an error" do
2697
+ expect {
2698
+ person.preferences.find_or_create_by!(name: "A")
2699
+ }.to raise_error(Mongoid::Errors::Validations)
2700
+ end
2701
+ end
2702
+ end
2703
+ end
2704
+ end
2705
+
2706
+ describe "#find_or_initialize_by" do
2707
+
2708
+ context "when the relation is not polymorphic" do
2709
+
2710
+ let(:person) do
2711
+ Person.create!
2712
+ end
2713
+
2714
+ let!(:preference) do
2715
+ person.preferences.create!(name: "Testing")
2716
+ end
2717
+
2718
+ context "when the document exists" do
2719
+
2720
+ let(:found) do
2721
+ person.preferences.find_or_initialize_by(name: "Testing")
2722
+ end
2723
+
2724
+ it "returns the document" do
2725
+ expect(found).to eq(preference)
2726
+ end
2727
+ end
2728
+
2729
+ context "when the document does not exist" do
2730
+
2731
+ let(:found) do
2732
+ person.preferences.find_or_initialize_by(name: "Test")
2733
+ end
2734
+
2735
+ it "sets the new document attributes" do
2736
+ expect(found.name).to eq("Test")
2737
+ end
2738
+
2739
+ it "returns a non persisted document" do
2740
+ expect(found).to_not be_persisted
2741
+ end
2742
+ end
2743
+ end
2744
+ end
2745
+
2746
+ describe "#max" do
2747
+
2748
+ let(:person) do
2749
+ Person.create!
2750
+ end
2751
+
2752
+ let(:preference_one) do
2753
+ Preference.create!(ranking: 5)
2754
+ end
2755
+
2756
+ let(:preference_two) do
2757
+ Preference.create!(ranking: 10)
2758
+ end
2759
+
2760
+ before do
2761
+ person.preferences.push(preference_one, preference_two)
2762
+ end
2763
+
2764
+ let(:max) do
2765
+ person.preferences.max do |a,b|
2766
+ a.ranking <=> b.ranking
2767
+ end
2768
+ end
2769
+
2770
+ it "returns the document with the max value of the supplied field" do
2771
+ expect(max).to eq(preference_two)
2772
+ end
2773
+ end
2774
+
2775
+ describe "#max_by" do
2776
+
2777
+ let(:person) do
2778
+ Person.create!
2779
+ end
2780
+
2781
+ let(:preference_one) do
2782
+ Preference.create!(ranking: 5)
2783
+ end
2784
+
2785
+ let(:preference_two) do
2786
+ Preference.create!(ranking: 10)
2787
+ end
2788
+
2789
+ before do
2790
+ person.preferences.push(preference_one, preference_two)
2791
+ end
2792
+
2793
+ let(:max) do
2794
+ person.preferences.max_by(&:ranking)
2795
+ end
2796
+
2797
+ it "returns the document with the max value of the supplied field" do
2798
+ expect(max).to eq(preference_two)
2799
+ end
2800
+ end
2801
+
2802
+ describe "#method_missing" do
2803
+
2804
+ let!(:person) do
2805
+ Person.create!
2806
+ end
2807
+
2808
+ let!(:preference_one) do
2809
+ person.preferences.create!(name: "First", value: "Posting")
2810
+ end
2811
+
2812
+ let!(:preference_two) do
2813
+ person.preferences.create!(name: "Second", value: "Testing")
2814
+ end
2815
+
2816
+ let!(:unrelated) do
2817
+ Preference.create!(name: "Third")
2818
+ end
2819
+
2820
+ context "when providing a single criteria" do
2821
+
2822
+ let(:preferences) do
2823
+ person.preferences.where(name: "First")
2824
+ end
2825
+
2826
+ it "applies the criteria to the documents" do
2827
+ expect(preferences).to eq([ preference_one ])
2828
+ end
2829
+
2830
+ context 'when providing a collation' do
2831
+ min_server_version '3.4'
2832
+
2833
+ let(:preferences) do
2834
+ person.preferences.where(name: "FIRST").collation(locale: 'en_US', strength: 2).to_a
2835
+ end
2836
+
2837
+ it "applies the collation option to the query" do
2838
+ expect(preferences).to eq([ preference_one ])
2839
+ end
2840
+ end
2841
+ end
2842
+
2843
+ context "when providing a criteria on id" do
2844
+
2845
+ let(:preferences) do
2846
+ person.preferences.where(_id: unrelated.id)
2847
+ end
2848
+
2849
+ it "does not return unrelated documents" do
2850
+ expect(preferences).to be_empty
2851
+ end
2852
+ end
2853
+
2854
+ context "when providing a criteria class method" do
2855
+
2856
+ let(:preferences) do
2857
+ person.preferences.posting
2858
+ end
2859
+
2860
+ it "applies the criteria to the documents" do
2861
+ expect(preferences).to eq([ preference_one ])
2862
+ end
2863
+ end
2864
+
2865
+ context "when chaining criteria" do
2866
+
2867
+ let(:preferences) do
2868
+ person.preferences.posting.where(:name.in => [ "First" ])
2869
+ end
2870
+
2871
+ it "applies the criteria to the documents" do
2872
+ expect(preferences).to eq([ preference_one ])
2873
+ end
2874
+ end
2875
+
2876
+ context "when delegating methods" do
2877
+
2878
+ describe "#distinct" do
2879
+
2880
+ let(:values) do
2881
+ person.preferences.distinct(:name)
2882
+ end
2883
+
2884
+ it "returns the distinct values for the fields" do
2885
+ expect(values).to include("First")
2886
+ expect(values).to include("Second")
2887
+ end
2888
+
2889
+ context "when the inverse relation is not defined" do
2890
+
2891
+ let!(:house) do
2892
+ person.houses.create!(name: "Wayne Manor")
2893
+ end
2894
+
2895
+ it "returns the distinct values for the fields" do
2896
+ expect(person.houses.distinct(:name)).to eq([ house.name ])
2897
+ end
2898
+ end
2899
+ end
2900
+ end
2901
+ end
2902
+
2903
+ describe "#min" do
2904
+
2905
+ let(:person) do
2906
+ Person.create!
2907
+ end
2908
+
2909
+ let(:preference_one) do
2910
+ Preference.create!(ranking: 5)
2911
+ end
2912
+
2913
+ let(:preference_two) do
2914
+ Preference.create!(ranking: 10)
2915
+ end
2916
+
2917
+ before do
2918
+ person.preferences.push(preference_one, preference_two)
2919
+ end
2920
+
2921
+ let(:min) do
2922
+ person.preferences.min do |a, b|
2923
+ a.ranking <=> b.ranking
2924
+ end
2925
+ end
2926
+
2927
+ it "returns the min value of the supplied field" do
2928
+ expect(min).to eq(preference_one)
2929
+ end
2930
+ end
2931
+
2932
+ describe "#min_by" do
2933
+
2934
+ let(:person) do
2935
+ Person.create!
2936
+ end
2937
+
2938
+ let(:preference_one) do
2939
+ Preference.create!(ranking: 5)
2940
+ end
2941
+
2942
+ let(:preference_two) do
2943
+ Preference.create!(ranking: 10)
2944
+ end
2945
+
2946
+ before do
2947
+ person.preferences.push(preference_one, preference_two)
2948
+ end
2949
+
2950
+ let(:min) do
2951
+ person.preferences.min_by(&:ranking)
2952
+ end
2953
+
2954
+ it "returns the min value of the supplied field" do
2955
+ expect(min).to eq(preference_one)
2956
+ end
2957
+ end
2958
+
2959
+ describe "#nil?" do
2960
+
2961
+ it "returns false" do
2962
+ expect(Person.new.preferences).to_not be_nil
2963
+ end
2964
+ end
2965
+
2966
+ describe "#nullify_all" do
2967
+
2968
+ let(:person) do
2969
+ Person.create!
2970
+ end
2971
+
2972
+ let!(:preference_one) do
2973
+ person.preferences.create!(name: "One")
2974
+ end
2975
+
2976
+ let!(:preference_two) do
2977
+ person.preferences.create!(name: "Two")
2978
+ end
2979
+
2980
+ before do
2981
+ person.preferences.nullify_all
2982
+ end
2983
+
2984
+ it "removes the foreign key from the base document" do
2985
+ [ preference_one, preference_two ].each do |preference|
2986
+ expect(person.preference_ids).to_not include(preference.id)
2987
+ end
2988
+ end
2989
+
2990
+ it "removes the foreign key from the target documents" do
2991
+ [ preference_one, preference_two ].each do |preference|
2992
+ expect(preference.person_ids).to_not include(person.id)
2993
+ end
2994
+ end
2995
+
2996
+ it "removes the reference from the base document" do
2997
+ [ preference_one, preference_two ].each do |preference|
2998
+ expect(person.preferences).to_not include(preference)
2999
+ end
3000
+ end
3001
+
3002
+ it "removes the reference from the target documents" do
3003
+ [ preference_one, preference_two ].each do |preference|
3004
+ expect(preference.people).to_not include(person)
3005
+ end
3006
+ end
3007
+
3008
+ it "saves the documents" do
3009
+ expect(preference_one.reload.people).to_not include(person)
3010
+ end
3011
+ end
3012
+
3013
+ describe "#respond_to?" do
3014
+
3015
+ let(:person) do
3016
+ Person.new
3017
+ end
3018
+
3019
+ let(:preferences) do
3020
+ person.preferences
3021
+ end
3022
+
3023
+ Array.public_instance_methods.sort.each do |method|
3024
+
3025
+ context "when checking Array##{method}" do
3026
+
3027
+ before do
3028
+ expect([].respond_to?(method)).to be true
3029
+ end
3030
+
3031
+ it "returns true" do
3032
+ expect(preferences.respond_to?(method)).to be true
3033
+ end
3034
+ end
3035
+ end
3036
+
3037
+ Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy.public_instance_methods.sort.each do |method|
3038
+
3039
+ context "when checking Proxy##{method}" do
3040
+
3041
+ it "returns true" do
3042
+ expect(preferences.respond_to?(method)).to be true
3043
+ end
3044
+ end
3045
+ end
3046
+
3047
+ Preference.scopes.keys.sort.each do |method|
3048
+
3049
+ context "when checking scope #{method}" do
3050
+
3051
+ it "returns true" do
3052
+ expect(preferences.respond_to?(method)).to be true
3053
+ end
3054
+ end
3055
+ end
3056
+ end
3057
+
3058
+ describe "#scoped" do
3059
+
3060
+ let(:scoped) do
3061
+ person.preferences.scoped
3062
+ end
3063
+
3064
+ context 'when association is empty' do
3065
+
3066
+ let(:person) do
3067
+ Person.new
3068
+ end
3069
+
3070
+ it "returns the relation criteria" do
3071
+ expect(scoped).to be_a(Mongoid::Criteria)
3072
+ end
3073
+
3074
+ it "returns with an empty selector" do
3075
+ expect(scoped.selector).to eq("_id" => { "$in" => [] })
3076
+ end
3077
+ end
3078
+
3079
+ context 'when association is not empty' do
3080
+
3081
+ let(:person) do
3082
+ Person.create!(preferences: [
3083
+ Preference.new(id: 123),
3084
+ ])
3085
+ end
3086
+
3087
+ it "returns with a selector including association element ids" do
3088
+ expect(scoped.selector).to eq("_id" => { "$in" => [123] })
3089
+ end
3090
+ end
3091
+ end
3092
+
3093
+ [ :size, :length ].each do |method|
3094
+
3095
+ describe "##{method}" do
3096
+
3097
+ let(:person) do
3098
+ Person.create!
3099
+ end
3100
+
3101
+ context "when documents have been persisted" do
3102
+
3103
+ let!(:preference) do
3104
+ person.preferences.create!(name: "Testing")
3105
+ end
3106
+
3107
+ it "returns the number of documents" do
3108
+ expect(person.preferences.send(method)).to eq(1)
3109
+ end
3110
+ end
3111
+
3112
+ context "when documents have not been persisted" do
3113
+
3114
+ before do
3115
+ person.preferences.build(name: "Test")
3116
+ person.preferences.create!(name: "Test 2")
3117
+ end
3118
+
3119
+ it "returns the total number of documents" do
3120
+ expect(person.preferences.send(method)).to eq(2)
3121
+ end
3122
+ end
3123
+ end
3124
+ end
3125
+
3126
+ describe "#unscoped" do
3127
+
3128
+ context "when the relation has no default scope" do
3129
+
3130
+ let!(:person) do
3131
+ Person.create!
3132
+ end
3133
+
3134
+ let!(:preference_one) do
3135
+ person.preferences.create!(name: "first")
3136
+ end
3137
+
3138
+ let!(:preference_two) do
3139
+ Preference.create!(name: "second")
3140
+ end
3141
+
3142
+ let(:unscoped) do
3143
+ person.preferences.unscoped
3144
+ end
3145
+
3146
+ it "returns only the associated documents" do
3147
+ expect(unscoped).to eq([ preference_one ])
3148
+ end
3149
+ end
3150
+
3151
+ context "when the relation has a default scope" do
3152
+
3153
+ let!(:person) do
3154
+ Person.create!
3155
+ end
3156
+
3157
+ let!(:house_one) do
3158
+ person.houses.create!(name: "first")
3159
+ end
3160
+
3161
+ let!(:house_two) do
3162
+ House.create!(name: "second")
3163
+ end
3164
+
3165
+ let(:unscoped) do
3166
+ person.houses.unscoped
3167
+ end
3168
+
3169
+ it "only returns associated documents" do
3170
+ expect(unscoped).to eq([ house_one ])
3171
+ end
3172
+
3173
+ it "removes the default scoping options" do
3174
+ expect(unscoped.options).to eq({})
3175
+ end
3176
+ end
3177
+ end
3178
+
3179
+ context "when setting the ids directly after the documents" do
3180
+
3181
+ let!(:person) do
3182
+ Person.create!(title: "The Boss")
3183
+ end
3184
+
3185
+ let!(:girlfriend_house) do
3186
+ House.create!(name: "Girlfriend")
3187
+ end
3188
+
3189
+ let!(:wife_house) do
3190
+ House.create!(name: "Wife")
3191
+ end
3192
+
3193
+ let!(:exwife_house) do
3194
+ House.create!(name: "Ex-Wife")
3195
+ end
3196
+
3197
+ before do
3198
+ person.update_attributes!(
3199
+ houses: [ wife_house, exwife_house, girlfriend_house ]
3200
+ )
3201
+ person.update_attributes!(house_ids: [ girlfriend_house.id ])
3202
+ end
3203
+
3204
+ context "when reloading" do
3205
+
3206
+ it "properly sets the references" do
3207
+ expect(person.houses(true)).to eq([ girlfriend_house ])
3208
+ end
3209
+ end
3210
+ end
3211
+
3212
+ context "when setting both sides in a single call" do
3213
+
3214
+ context "when the documents are new" do
3215
+
3216
+ let(:user) do
3217
+ User.new(name: "testing")
3218
+ end
3219
+
3220
+ let(:business) do
3221
+ Business.new(name: "serious", owners: [ user ])
3222
+ end
3223
+
3224
+ before do
3225
+ user.businesses = [ business ]
3226
+ end
3227
+
3228
+ it "sets the businesses" do
3229
+ expect(user.businesses).to eq([ business ])
3230
+ end
3231
+
3232
+ it "sets the inverse users" do
3233
+ expect(user.businesses.first.owners.first).to eq(user)
3234
+ end
3235
+
3236
+ it "sets the inverse businesses" do
3237
+ expect(business.owners).to eq([ user ])
3238
+ end
3239
+ end
3240
+
3241
+ context "when one side is persisted" do
3242
+
3243
+ let!(:user) do
3244
+ User.new(name: "testing")
3245
+ end
3246
+
3247
+ let!(:business) do
3248
+ Business.create!(name: "serious", owners: [ user ])
3249
+ end
3250
+
3251
+ before do
3252
+ user.businesses = [ business ]
3253
+ end
3254
+
3255
+ it "sets the businesses" do
3256
+ expect(user.businesses).to eq([ business ])
3257
+ end
3258
+
3259
+ it "sets the inverse users" do
3260
+ expect(user.businesses.first.owners.first).to eq(user)
3261
+ end
3262
+
3263
+ it "sets the inverse businesses" do
3264
+ expect(business.owners).to eq([ user ])
3265
+ end
3266
+
3267
+ context "when reloading" do
3268
+
3269
+ before do
3270
+ user.reload
3271
+ business.reload
3272
+ end
3273
+
3274
+ it "persists the businesses" do
3275
+ expect(user.businesses).to eq([ business ])
3276
+ end
3277
+
3278
+ it "persists the inverse users" do
3279
+ expect(user.businesses.first.owners.first).to eq(user)
3280
+ end
3281
+
3282
+ it "persists the inverse businesses" do
3283
+ expect(business.owners).to eq([ user ])
3284
+ end
3285
+ end
3286
+ end
3287
+
3288
+ context "when the documents are persisted" do
3289
+
3290
+ let(:user) do
3291
+ User.create!(name: "tst")
3292
+ end
3293
+
3294
+ let(:business) do
3295
+ Business.create!(name: "srs", owners: [ user ])
3296
+ end
3297
+
3298
+ before do
3299
+ user.businesses = [ business ]
3300
+ end
3301
+
3302
+ it "sets the businesses" do
3303
+ expect(user.businesses).to eq([ business ])
3304
+ end
3305
+
3306
+ it "sets the inverse users" do
3307
+ expect(user.businesses.first.owners.first).to eq(user)
3308
+ end
3309
+
3310
+ it "sets the inverse businesses" do
3311
+ expect(business.owners).to eq([ user ])
3312
+ end
3313
+
3314
+ context "when reloading" do
3315
+
3316
+ before do
3317
+ user.reload
3318
+ business.reload
3319
+ end
3320
+
3321
+ it "persists the businesses" do
3322
+ expect(user.businesses).to eq([ business ])
3323
+ end
3324
+
3325
+ it "persists the inverse users" do
3326
+ expect(user.businesses.first.owners.first).to eq(user)
3327
+ end
3328
+
3329
+ it "persists the inverse businesses" do
3330
+ expect(business.owners).to eq([ user ])
3331
+ end
3332
+ end
3333
+ end
3334
+ end
3335
+
3336
+ context "when binding the relation multiple times" do
3337
+
3338
+ let(:person) do
3339
+ Person.create!
3340
+ end
3341
+
3342
+ let(:preference) do
3343
+ person.preferences.create!(name: "testing")
3344
+ end
3345
+
3346
+ before do
3347
+ 2.times do
3348
+ person.preferences.each do |preference|
3349
+ expect(preference.person_ids).to eq([ person.id ])
3350
+ end
3351
+ end
3352
+ end
3353
+
3354
+ it "does not duplicate foreign keys" do
3355
+ expect(person.preference_ids).to eq([ preference.id ])
3356
+ end
3357
+ end
3358
+
3359
+ context "when the association has order criteria" do
3360
+
3361
+ let(:person) do
3362
+ Person.create!
3363
+ end
3364
+
3365
+ let(:preference_one) do
3366
+ OrderedPreference.create!(name: 'preference-1', value: 10)
3367
+ end
3368
+
3369
+ let(:preference_two) do
3370
+ OrderedPreference.create!(name: 'preference-2', value: 20)
3371
+ end
3372
+
3373
+ let(:preference_three) do
3374
+ OrderedPreference.create!(name: 'preference-3', value: 20)
3375
+ end
3376
+
3377
+ before do
3378
+ person.ordered_preferences.nullify_all
3379
+ person.ordered_preferences.push(preference_one, preference_two, preference_three)
3380
+ end
3381
+
3382
+ it "orders the documents" do
3383
+ expect(person.ordered_preferences(true)).to eq(
3384
+ [preference_two, preference_three, preference_one]
3385
+ )
3386
+ end
3387
+
3388
+ it "chains default criteria with additional" do
3389
+ expect(person.ordered_preferences.order_by(:name.desc).to_a).to eq(
3390
+ [preference_three, preference_two, preference_one]
3391
+ )
3392
+ end
3393
+ end
3394
+
3395
+ context "when the parent is not a new record and freshly loaded" do
3396
+
3397
+ let(:person) do
3398
+ Person.create!
3399
+ end
3400
+
3401
+ let(:preference) do
3402
+ Preference.new
3403
+ end
3404
+
3405
+ before do
3406
+ person.preferences = [ preference ]
3407
+ person.save!
3408
+ person.reload
3409
+ person.preferences = nil
3410
+ end
3411
+
3412
+ it "sets the relation to an empty array" do
3413
+ expect(person.preferences).to be_empty
3414
+ end
3415
+
3416
+ it "removes the foreign key values" do
3417
+ expect(person.preference_ids).to be_empty
3418
+ end
3419
+
3420
+ it "does not delete the target from the database" do
3421
+ expect {
3422
+ preference.reload
3423
+ }.not_to raise_error
3424
+ end
3425
+ end
3426
+
3427
+ context "when reloading the relation" do
3428
+
3429
+ let!(:person) do
3430
+ Person.create!
3431
+ end
3432
+
3433
+ let!(:preference_one) do
3434
+ Preference.create!(name: "one")
3435
+ end
3436
+
3437
+ let!(:preference_two) do
3438
+ Preference.create!(name: "two")
3439
+ end
3440
+
3441
+ before do
3442
+ person.preferences << preference_one
3443
+ end
3444
+
3445
+ context "when the relation references the same documents" do
3446
+
3447
+ before do
3448
+ Preference.collection.find({ _id: preference_one.id }).
3449
+ update_one({ "$set" => { name: "reloaded" }})
3450
+ end
3451
+
3452
+ let(:reloaded) do
3453
+ person.preferences(true)
3454
+ end
3455
+
3456
+ it "reloads the document from the database" do
3457
+ expect(reloaded.first.name).to eq("reloaded")
3458
+ end
3459
+ end
3460
+
3461
+ context "when the relation references different documents" do
3462
+
3463
+ before do
3464
+ person.preferences << preference_two
3465
+ end
3466
+
3467
+ let(:reloaded) do
3468
+ person.preferences(true)
3469
+ end
3470
+
3471
+ it "reloads the new document from the database" do
3472
+ expect(reloaded).to eq([ preference_one, preference_two ])
3473
+ end
3474
+ end
3475
+ end
3476
+
3477
+ context "when adding to a relation via a field setter" do
3478
+
3479
+ context "when the document is new" do
3480
+
3481
+ let!(:person) do
3482
+ Person.create!(preference_names: "one, two")
3483
+ end
3484
+
3485
+ let(:preference_one) do
3486
+ person.reload.preferences.first
3487
+ end
3488
+
3489
+ let(:preference_two) do
3490
+ person.reload.preferences.last
3491
+ end
3492
+
3493
+ it "persists the first preference" do
3494
+ expect(preference_one).to_not be_nil
3495
+ end
3496
+
3497
+ it "sets the first inverse" do
3498
+ expect(preference_one.people).to eq([ person ])
3499
+ end
3500
+
3501
+ it "persists the second preference" do
3502
+ expect(preference_two).to_not be_nil
3503
+ end
3504
+
3505
+ it "sets the second inverse keys" do
3506
+ expect(preference_two.people).to eq([ person ])
3507
+ end
3508
+ end
3509
+ end
3510
+
3511
+ context "when changing the order of existing ids" do
3512
+
3513
+ let(:person) do
3514
+ Person.new
3515
+ end
3516
+
3517
+ let(:preference_one) do
3518
+ Preference.create!(name: "one")
3519
+ end
3520
+
3521
+ let(:preference_two) do
3522
+ Preference.create!(name: "two")
3523
+ end
3524
+
3525
+ before do
3526
+ person.preference_ids = [ preference_one.id, preference_two.id ]
3527
+ person.save!
3528
+ end
3529
+
3530
+ context "and the order is changed" do
3531
+
3532
+ before do
3533
+ person.preference_ids = [ preference_two.id, preference_one.id ]
3534
+ person.save!
3535
+ end
3536
+
3537
+ let(:reloaded) do
3538
+ Person.find(person.id)
3539
+ end
3540
+
3541
+ it "persists the change in id order" do
3542
+ expect(reloaded.preference_ids).to eq(
3543
+ [ preference_two.id, preference_one.id ]
3544
+ )
3545
+ end
3546
+ end
3547
+
3548
+ context "and the order is changed and an element is added" do
3549
+
3550
+ let(:preference_three) do
3551
+ Preference.create!(name: "three")
3552
+ end
3553
+
3554
+ before do
3555
+ person.preference_ids =
3556
+ [ preference_two.id, preference_one.id, preference_three.id ]
3557
+ person.save!
3558
+ end
3559
+
3560
+ let(:reloaded) do
3561
+ Person.find(person.id)
3562
+ end
3563
+
3564
+ it "also persists the change in id order" do
3565
+ expect(reloaded.preference_ids).to eq(
3566
+ [ preference_two.id, preference_one.id, preference_three.id ]
3567
+ )
3568
+ end
3569
+ end
3570
+
3571
+ context "and the order is changed and an element is removed" do
3572
+
3573
+ let(:preference_three) do
3574
+ Preference.create!(name: "three")
3575
+ end
3576
+
3577
+ before do
3578
+ person.preference_ids =
3579
+ [ preference_one.id, preference_two.id, preference_three.id ]
3580
+ person.save!
3581
+ person.preference_ids =
3582
+ [ preference_three.id, preference_two.id ]
3583
+ person.save!
3584
+ end
3585
+
3586
+ let(:reloaded) do
3587
+ Person.find(person.id)
3588
+ end
3589
+
3590
+ it "also persists the change in id order" do
3591
+ expect(reloaded.preference_ids).to eq(
3592
+ [ preference_three.id, preference_two.id ]
3593
+ )
3594
+ end
3595
+ end
3596
+ end
3597
+
3598
+ context "when adding a document" do
3599
+
3600
+ let(:person) do
3601
+ Person.new
3602
+ end
3603
+
3604
+ let(:preference_one) do
3605
+ Preference.new
3606
+ end
3607
+
3608
+ let(:first_add) do
3609
+ person.preferences.push(preference_one)
3610
+ end
3611
+
3612
+ context "when chaining a second add" do
3613
+
3614
+ let(:preference_two) do
3615
+ Preference.new
3616
+ end
3617
+
3618
+ let(:result) do
3619
+ first_add.push(preference_two)
3620
+ end
3621
+
3622
+ it "adds both documents" do
3623
+ expect(result).to eq([ preference_one, preference_two ])
3624
+ end
3625
+ end
3626
+ end
3627
+
3628
+ context "when setting the relation via the foreign key" do
3629
+
3630
+ context "when the relation exists" do
3631
+
3632
+ let!(:person) do
3633
+ Person.create!
3634
+ end
3635
+
3636
+ let!(:pref_one) do
3637
+ person.preferences.create!
3638
+ end
3639
+
3640
+ let!(:pref_two) do
3641
+ Preference.create!
3642
+ end
3643
+
3644
+ before do
3645
+ person.preference_ids = [ pref_two.id ]
3646
+ end
3647
+
3648
+ it "sets the new documents on the relation" do
3649
+ expect(person.preferences).to eq([ pref_two ])
3650
+ end
3651
+ end
3652
+ end
3653
+
3654
+ context "when using a different primary key" do
3655
+
3656
+ let(:dog) do
3657
+ Dog.create!(name: 'Doggie')
3658
+ end
3659
+
3660
+ let(:cat) do
3661
+ Cat.create!(name: 'Kitty')
3662
+ end
3663
+
3664
+ let(:another_cat) do
3665
+ Cat.create!(name: 'Kitten')
3666
+ end
3667
+
3668
+ let(:fire_hydrant) do
3669
+ FireHydrant.create!(location: '221B Baker Street')
3670
+ end
3671
+
3672
+ context "when adding to a one-way many to many" do
3673
+
3674
+ before do
3675
+ fire_hydrant.cats.push(cat)
3676
+ end
3677
+
3678
+ it "adds the pk value to the fk set" do
3679
+ expect(fire_hydrant.cat_ids).to eq([cat.name])
3680
+ end
3681
+ end
3682
+
3683
+ context "when adding multiple documents to a one-way many to many" do
3684
+
3685
+ before do
3686
+ fire_hydrant.cats.push([cat, another_cat])
3687
+ end
3688
+
3689
+ it "adds the pk values to the fk set" do
3690
+ expect(fire_hydrant.cat_ids).to eq([cat.name, another_cat.name])
3691
+ end
3692
+ end
3693
+
3694
+ context "when adding a new document to a one-way many to many" do
3695
+
3696
+ before do
3697
+ fire_hydrant.cats.build name: 'Kitten'
3698
+ end
3699
+
3700
+ it "adds the pk values to the fk set" do
3701
+ expect(fire_hydrant.cat_ids).to eq(['Kitten'])
3702
+ end
3703
+ end
3704
+
3705
+ context "when adding to a two-way many to many" do
3706
+
3707
+ before do
3708
+ fire_hydrant.dogs.push(dog)
3709
+ end
3710
+
3711
+ it "adds the pk value to the fk set" do
3712
+ expect(fire_hydrant.dog_ids).to eq([dog.name])
3713
+ end
3714
+
3715
+ it "adds the base pk value to the inverse fk set" do
3716
+ expect(dog.fire_hydrant_ids).to eq([fire_hydrant.location])
3717
+ end
3718
+ end
3719
+
3720
+ context "when deleting from a two-way many to many" do
3721
+
3722
+ before do
3723
+ dog.fire_hydrants.push(fire_hydrant)
3724
+ fire_hydrant.dogs.delete(dog)
3725
+ end
3726
+
3727
+ it "removes the pk value from the fk set" do
3728
+ expect(fire_hydrant.dog_ids).to eq([])
3729
+ end
3730
+
3731
+ it "removes the base pk value from the inverse fk set" do
3732
+ expect(dog.fire_hydrant_ids).to eq([])
3733
+ end
3734
+ end
3735
+ end
3736
+
3737
+ context "HABTM" do
3738
+ before do
3739
+ class Project
3740
+ include Mongoid::Document
3741
+
3742
+ field :n, type: String, as: :name
3743
+
3744
+ has_and_belongs_to_many :distributors,
3745
+ foreign_key: :d_ids,
3746
+ inverse_of: 'p'
3747
+ end
3748
+
3749
+ class Distributor
3750
+ include Mongoid::Document
3751
+
3752
+ field :n, type: String, as: :name
3753
+
3754
+ has_and_belongs_to_many :projects,
3755
+ foreign_key: :p_ids,
3756
+ inverse_of: 'd'
3757
+ end
3758
+ end
3759
+
3760
+ it "should assign relation from both sides" do
3761
+ p1 = Project.create! name: 'Foo'
3762
+ p2 = Project.create! name: 'Bar'
3763
+ d1 = Distributor.create! name: 'Rock'
3764
+ d2 = Distributor.create! name: 'Soul'
3765
+
3766
+ p1.distributors << d1
3767
+ expect(p1.d_ids).to match_array([d1.id])
3768
+ expect(d1.p_ids).to match_array([p1.id])
3769
+ d2.projects << p2
3770
+ expect(d2.p_ids).to match_array([p2.id])
3771
+ expect(p2.d_ids).to match_array([d2.id])
3772
+ end
3773
+ end
3774
+
3775
+ # This test is for MONGOID-5344 which tests that the initial call to
3776
+ # signature_ids refers to the same array as subsequent calls to signature_ids.
3777
+ # Prior to the change in that ticket, this test broke because the array
3778
+ # returned from write_attribute (which is triggered the first time the
3779
+ # foreign key array is referenced, to set the default), refers to a different
3780
+ # array to the one stored in the attributes hash. This happened because,
3781
+ # when retrieving a document from the database, the attributes hash is actually
3782
+ # a BSON::Document, which applies a transformation to the array before
3783
+ # storing it.
3784
+ context "when executing concat on foreign key array from the db" do
3785
+ config_override :legacy_attributes, false
3786
+
3787
+ before do
3788
+ HabtmmContract.create!
3789
+ HabtmmSignature.create!
3790
+ end
3791
+
3792
+ let!(:contract) { HabtmmContract.first }
3793
+ let!(:signature) { HabtmmSignature.first }
3794
+
3795
+ before do
3796
+ contract.signature_ids.concat([signature.id])
3797
+ end
3798
+
3799
+ it "works on the first attempt" do
3800
+ expect(contract.signature_ids).to eq([signature.id])
3801
+ end
3802
+ end
3803
+ end