mongoid 6.4.4 → 7.5.1

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