mongoid 5.4.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1354) 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 +33 -19
  6. data/Rakefile +75 -5
  7. data/lib/config/locales/en.yml +180 -64
  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 +207 -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 +498 -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 +29 -53
  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 +47 -52
  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 +24 -7
  81. data/lib/mongoid/attributes.rb +110 -106
  82. data/lib/mongoid/cacheable.rb +33 -0
  83. data/lib/mongoid/changeable.rb +39 -57
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +62 -258
  86. data/lib/mongoid/clients/sessions.rb +125 -0
  87. data/lib/mongoid/clients/storage_options.rb +9 -81
  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 +13 -73
  91. data/lib/mongoid/composable.rb +33 -10
  92. data/lib/mongoid/config/environment.rb +36 -14
  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 +112 -39
  98. data/lib/mongoid/contextual/aggregable/memory.rb +17 -12
  99. data/lib/mongoid/contextual/aggregable/mongo.rb +26 -27
  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 +31 -33
  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 +12 -36
  106. data/lib/mongoid/contextual/memory.rb +34 -64
  107. data/lib/mongoid/contextual/mongo.rb +228 -113
  108. data/lib/mongoid/contextual/none.rb +51 -23
  109. data/lib/mongoid/contextual/queryable.rb +2 -3
  110. data/lib/mongoid/contextual.rb +7 -9
  111. data/lib/mongoid/copyable.rb +32 -19
  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 +4 -7
  116. data/lib/mongoid/criteria/modifiable.rb +38 -24
  117. data/lib/mongoid/criteria/options.rb +24 -0
  118. data/lib/mongoid/criteria/permission.rb +2 -1
  119. data/lib/mongoid/criteria/queryable/aggregable.rb +109 -0
  120. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  121. data/lib/mongoid/criteria/queryable/extensions/array.rb +162 -0
  122. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +36 -0
  123. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +33 -0
  124. data/lib/mongoid/criteria/queryable/extensions/date.rb +58 -0
  125. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +47 -0
  126. data/lib/mongoid/criteria/queryable/extensions/hash.rb +177 -0
  127. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +75 -0
  128. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +81 -0
  129. data/lib/mongoid/criteria/queryable/extensions/object.rb +181 -0
  130. data/lib/mongoid/criteria/queryable/extensions/range.rb +94 -0
  131. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +72 -0
  132. data/lib/mongoid/criteria/queryable/extensions/set.rb +33 -0
  133. data/lib/mongoid/criteria/queryable/extensions/string.rb +122 -0
  134. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +72 -0
  135. data/lib/mongoid/criteria/queryable/extensions/time.rb +55 -0
  136. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +61 -0
  137. data/lib/mongoid/criteria/queryable/extensions.rb +25 -0
  138. data/lib/mongoid/criteria/queryable/key.rb +177 -0
  139. data/lib/mongoid/criteria/queryable/macroable.rb +26 -0
  140. data/lib/mongoid/criteria/queryable/mergeable.rb +413 -0
  141. data/lib/mongoid/criteria/queryable/optional.rb +386 -0
  142. data/lib/mongoid/criteria/queryable/options.rb +136 -0
  143. data/lib/mongoid/criteria/queryable/pipeline.rb +106 -0
  144. data/lib/mongoid/criteria/queryable/selectable.rb +943 -0
  145. data/lib/mongoid/criteria/queryable/selector.rb +202 -0
  146. data/lib/mongoid/criteria/queryable/smash.rb +95 -0
  147. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  148. data/lib/mongoid/criteria/queryable.rb +85 -0
  149. data/lib/mongoid/criteria/scopable.rb +27 -19
  150. data/lib/mongoid/criteria.rb +93 -76
  151. data/lib/mongoid/document.rb +62 -109
  152. data/lib/mongoid/equality.rb +29 -12
  153. data/lib/mongoid/errors/ambiguous_relationship.rb +5 -6
  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 +2 -9
  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 +4 -7
  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 +26 -0
  179. data/lib/mongoid/errors/invalid_query.rb +40 -0
  180. data/lib/mongoid/errors/invalid_relation.rb +61 -0
  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 +21 -0
  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 +18 -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 +17 -17
  216. data/lib/mongoid/extensions/boolean.rb +3 -5
  217. data/lib/mongoid/extensions/date.rb +17 -13
  218. data/lib/mongoid/extensions/date_time.rb +4 -12
  219. data/lib/mongoid/extensions/decimal128.rb +3 -6
  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 +57 -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 +4 -4
  230. data/lib/mongoid/extensions/set.rb +2 -7
  231. data/lib/mongoid/extensions/string.rb +27 -44
  232. data/lib/mongoid/extensions/symbol.rb +2 -7
  233. data/lib/mongoid/extensions/time.rb +16 -10
  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 -11
  237. data/lib/mongoid/factory.rb +60 -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 +50 -14
  242. data/lib/mongoid/fields/validators.rb +2 -1
  243. data/lib/mongoid/fields.rb +118 -67
  244. data/lib/mongoid/findable.rb +60 -24
  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 +26 -36
  248. data/lib/mongoid/inspectable.rb +4 -11
  249. data/lib/mongoid/interceptable.rb +27 -57
  250. data/lib/mongoid/loggable.rb +13 -16
  251. data/lib/mongoid/matchable.rb +5 -146
  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 +9 -24
  285. data/lib/mongoid/persistable/deletable.rb +16 -29
  286. data/lib/mongoid/persistable/destroyable.rb +12 -15
  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 +61 -19
  295. data/lib/mongoid/persistable/unsettable.rb +8 -8
  296. data/lib/mongoid/persistable/updatable.rb +38 -33
  297. data/lib/mongoid/persistable/upsertable.rb +5 -9
  298. data/lib/mongoid/persistable.rb +137 -45
  299. data/lib/mongoid/persistence_context.rb +222 -0
  300. data/lib/mongoid/positional.rb +3 -6
  301. data/lib/mongoid/query_cache.rb +141 -110
  302. data/lib/mongoid/railtie.rb +20 -17
  303. data/lib/mongoid/railties/controller_runtime.rb +88 -0
  304. data/lib/mongoid/railties/database.rake +9 -0
  305. data/lib/mongoid/reloadable.rb +14 -19
  306. data/lib/mongoid/scopable.rb +11 -38
  307. data/lib/mongoid/selectable.rb +8 -17
  308. data/lib/mongoid/serializable.rb +29 -34
  309. data/lib/mongoid/shardable.rb +80 -17
  310. data/lib/mongoid/stateful.rb +4 -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 +88 -7
  314. data/lib/mongoid/threaded/lifecycle.rb +2 -21
  315. data/lib/mongoid/threaded.rb +70 -49
  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 +181 -61
  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 +26 -40
  333. data/lib/mongoid/validatable.rb +16 -35
  334. data/lib/mongoid/version.rb +3 -2
  335. data/lib/mongoid.rb +35 -17
  336. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  337. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +54 -21
  338. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  339. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  340. data/lib/rails/generators/mongoid_generator.rb +2 -1
  341. data/lib/rails/mongoid.rb +4 -5
  342. data/spec/README.md +33 -0
  343. data/spec/config/mongoid.yml +28 -2
  344. data/spec/integration/app_spec.rb +343 -0
  345. data/spec/integration/associations/belongs_to_spec.rb +15 -0
  346. data/spec/integration/associations/embedded_dirty_spec.rb +29 -0
  347. data/spec/integration/associations/embedded_spec.rb +268 -0
  348. data/spec/integration/associations/embeds_many_spec.rb +206 -0
  349. data/spec/integration/associations/embeds_one_spec.rb +23 -0
  350. data/spec/integration/associations/foreign_key_spec.rb +98 -0
  351. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  352. data/spec/integration/associations/has_many_spec.rb +128 -0
  353. data/spec/integration/associations/has_one_spec.rb +176 -0
  354. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  355. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  356. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  357. data/spec/integration/associations/scope_option_spec.rb +101 -0
  358. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  359. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  360. data/spec/integration/callbacks_models.rb +61 -0
  361. data/spec/integration/callbacks_spec.rb +228 -0
  362. data/spec/integration/contextual/empty_spec.rb +141 -0
  363. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  364. data/spec/integration/criteria/date_field_spec.rb +40 -0
  365. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  366. data/spec/integration/criteria/logical_spec.rb +124 -0
  367. data/spec/integration/criteria/range_spec.rb +265 -0
  368. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  369. data/spec/integration/discriminator_key_spec.rb +353 -0
  370. data/spec/integration/discriminator_value_spec.rb +206 -0
  371. data/spec/integration/document_spec.rb +51 -0
  372. data/spec/integration/i18n_fallbacks_spec.rb +89 -0
  373. data/spec/integration/matcher_examples_spec.rb +758 -0
  374. data/spec/integration/matcher_operator_data/all.yml +140 -0
  375. data/spec/integration/matcher_operator_data/and.yml +93 -0
  376. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  377. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  378. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  379. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  380. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  381. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  382. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  383. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  384. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  385. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  386. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  387. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  388. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  389. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  390. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  391. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  392. data/spec/integration/matcher_operator_data/in.yml +210 -0
  393. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  394. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  395. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  396. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  397. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  398. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  399. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  400. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  401. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  402. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  403. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  404. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  405. data/spec/integration/matcher_operator_data/not.yml +196 -0
  406. data/spec/integration/matcher_operator_data/or.yml +137 -0
  407. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  408. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  409. data/spec/integration/matcher_operator_data/size.yml +174 -0
  410. data/spec/integration/matcher_operator_data/type.yml +70 -0
  411. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  412. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  413. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  414. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  415. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  416. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  417. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  418. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  419. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  420. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  421. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  422. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  423. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  424. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  425. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  426. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  427. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  428. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  429. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  430. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  431. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  432. data/spec/integration/matcher_operator_spec.rb +124 -0
  433. data/spec/integration/matcher_spec.rb +283 -0
  434. data/spec/integration/server_query_spec.rb +141 -0
  435. data/spec/integration/shardable_spec.rb +148 -0
  436. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  437. data/spec/lite_spec_helper.rb +83 -0
  438. data/spec/mongoid/association/accessors_spec.rb +1067 -0
  439. data/spec/mongoid/association/auto_save_spec.rb +403 -0
  440. data/spec/mongoid/association/builders_spec.rb +255 -0
  441. data/spec/mongoid/association/constrainable_spec.rb +117 -0
  442. data/spec/mongoid/association/counter_cache_spec.rb +452 -0
  443. data/spec/mongoid/association/depending_spec.rb +959 -0
  444. data/spec/mongoid/association/eager_spec.rb +281 -0
  445. data/spec/mongoid/association/embedded/cyclic_spec.rb +180 -0
  446. data/spec/mongoid/association/embedded/dirty_spec.rb +67 -0
  447. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +173 -0
  448. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +36 -0
  449. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +559 -0
  450. data/spec/mongoid/association/embedded/embedded_in_spec.rb +903 -0
  451. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +56 -0
  452. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +106 -0
  453. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +4652 -0
  454. data/spec/mongoid/association/embedded/embeds_many_models.rb +69 -0
  455. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +51 -0
  456. data/spec/mongoid/association/embedded/embeds_many_spec.rb +864 -0
  457. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +79 -0
  458. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +81 -0
  459. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +1025 -0
  460. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +8 -0
  461. data/spec/mongoid/association/embedded/embeds_one_models.rb +54 -0
  462. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  463. data/spec/mongoid/association/embedded/embeds_one_spec.rb +956 -0
  464. data/spec/mongoid/association/macros_spec.rb +1116 -0
  465. data/spec/mongoid/association/nested/many_spec.rb +232 -0
  466. data/spec/mongoid/association/nested/one_spec.rb +253 -0
  467. data/spec/mongoid/association/options_spec.rb +1323 -0
  468. data/spec/mongoid/association/polymorphic_spec.rb +162 -0
  469. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +243 -0
  470. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +238 -0
  471. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +412 -0
  472. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +1373 -0
  473. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  474. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2046 -0
  475. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +180 -0
  476. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +148 -0
  477. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +196 -0
  478. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +76 -0
  479. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +3773 -0
  480. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +67 -0
  481. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  482. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1071 -0
  483. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +155 -0
  484. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +142 -0
  485. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +290 -0
  486. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2232 -0
  487. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  488. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +4092 -0
  489. data/spec/mongoid/association/referenced/has_many_models.rb +95 -0
  490. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  491. data/spec/mongoid/association/referenced/has_many_spec.rb +1248 -0
  492. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +133 -0
  493. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +159 -0
  494. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +193 -0
  495. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +1142 -0
  496. data/spec/mongoid/association/referenced/has_one_models.rb +97 -0
  497. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  498. data/spec/mongoid/association/referenced/has_one_spec.rb +1383 -0
  499. data/spec/mongoid/association/reflections_spec.rb +92 -0
  500. data/spec/mongoid/association/syncable_spec.rb +499 -0
  501. data/spec/mongoid/association_spec.rb +191 -0
  502. data/spec/mongoid/atomic/modifiers_spec.rb +52 -3
  503. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  504. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  505. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  506. data/spec/mongoid/atomic/paths_spec.rb +107 -12
  507. data/spec/mongoid/atomic_spec.rb +36 -11
  508. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  509. data/spec/mongoid/attributes/nested_spec.rb +115 -91
  510. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  511. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  512. data/spec/mongoid/attributes/projector_spec.rb +44 -0
  513. data/spec/mongoid/attributes/readonly_spec.rb +111 -111
  514. data/spec/mongoid/attributes_spec.rb +501 -33
  515. data/spec/mongoid/cacheable_spec.rb +114 -0
  516. data/spec/mongoid/changeable_spec.rb +118 -35
  517. data/spec/mongoid/clients/factory_spec.rb +176 -34
  518. data/spec/mongoid/clients/options_spec.rb +431 -98
  519. data/spec/mongoid/clients/sessions_spec.rb +335 -0
  520. data/spec/mongoid/clients/transactions_spec.rb +415 -0
  521. data/spec/mongoid/clients_spec.rb +318 -114
  522. data/spec/mongoid/composable_spec.rb +9 -0
  523. data/spec/mongoid/config/environment_spec.rb +88 -8
  524. data/spec/mongoid/config/options_spec.rb +22 -3
  525. data/spec/mongoid/config_spec.rb +371 -13
  526. data/spec/mongoid/contextual/aggregable/memory_spec.rb +53 -11
  527. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  528. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  529. data/spec/mongoid/contextual/atomic_spec.rb +245 -84
  530. data/spec/mongoid/contextual/geo_near_spec.rb +31 -19
  531. data/spec/mongoid/contextual/map_reduce_spec.rb +24 -7
  532. data/spec/mongoid/contextual/memory_spec.rb +44 -23
  533. data/spec/mongoid/contextual/mongo_spec.rb +780 -155
  534. data/spec/mongoid/contextual/none_spec.rb +14 -71
  535. data/spec/mongoid/copyable_spec.rb +297 -23
  536. data/spec/mongoid/copyable_spec_models.rb +47 -0
  537. data/spec/mongoid/criteria/findable_spec.rb +77 -20
  538. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  539. data/spec/mongoid/criteria/marshalable_spec.rb +2 -0
  540. data/spec/mongoid/criteria/modifiable_spec.rb +506 -50
  541. data/spec/mongoid/criteria/options_spec.rb +31 -0
  542. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +372 -0
  543. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  544. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +525 -0
  545. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +61 -0
  546. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +60 -0
  547. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +215 -0
  548. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +332 -0
  549. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +423 -0
  550. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +60 -0
  551. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +67 -0
  552. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +329 -0
  553. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +67 -0
  554. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +79 -0
  555. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +53 -0
  556. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +110 -0
  557. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +370 -0
  558. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +91 -0
  559. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +92 -0
  560. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +41 -0
  561. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +347 -0
  562. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +169 -0
  563. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +395 -0
  564. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +376 -0
  565. data/spec/mongoid/criteria/queryable/key_spec.rb +96 -0
  566. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +182 -0
  567. data/spec/mongoid/criteria/queryable/optional_spec.rb +1801 -0
  568. data/spec/mongoid/criteria/queryable/options_spec.rb +362 -0
  569. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +214 -0
  570. data/spec/mongoid/criteria/queryable/queryable_spec.rb +139 -0
  571. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2069 -0
  572. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  573. data/spec/mongoid/criteria/queryable/selectable_spec.rb +2297 -0
  574. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  575. data/spec/mongoid/criteria/queryable/selector_spec.rb +883 -0
  576. data/spec/mongoid/criteria/queryable/smash_spec.rb +32 -0
  577. data/spec/mongoid/criteria/queryable/storable_spec.rb +226 -0
  578. data/spec/mongoid/criteria/scopable_spec.rb +210 -0
  579. data/spec/mongoid/criteria_projection_spec.rb +410 -0
  580. data/spec/mongoid/criteria_spec.rb +876 -402
  581. data/spec/mongoid/document_fields_spec.rb +113 -0
  582. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  583. data/spec/mongoid/document_query_spec.rb +89 -0
  584. data/spec/mongoid/document_spec.rb +214 -104
  585. data/spec/mongoid/equality_spec.rb +144 -41
  586. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  587. data/spec/mongoid/errors/callback_spec.rb +2 -0
  588. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  589. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  590. data/spec/mongoid/errors/document_not_found_spec.rb +2 -0
  591. data/spec/mongoid/errors/eager_load_spec.rb +2 -0
  592. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  593. data/spec/mongoid/errors/invalid_config_file_spec.rb +31 -0
  594. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  595. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  596. data/spec/mongoid/errors/invalid_field_spec.rb +2 -0
  597. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  598. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  599. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  600. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  601. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  602. data/spec/mongoid/errors/invalid_relation_spec.rb +39 -0
  603. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  604. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  605. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  606. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  607. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  608. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  609. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  610. data/spec/mongoid/errors/mongoid_error_spec.rb +28 -11
  611. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  612. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  613. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  614. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  615. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  616. data/spec/mongoid/errors/no_environment_spec.rb +2 -0
  617. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  618. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  619. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  620. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  621. data/spec/mongoid/errors/readonly_document_spec.rb +2 -0
  622. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  623. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +2 -0
  624. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  625. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  626. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  627. data/spec/mongoid/errors/validations_spec.rb +2 -0
  628. data/spec/mongoid/extensions/array_spec.rb +36 -58
  629. data/spec/mongoid/extensions/big_decimal_spec.rb +323 -19
  630. data/spec/mongoid/extensions/binary_spec.rb +2 -0
  631. data/spec/mongoid/extensions/boolean_spec.rb +16 -0
  632. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +335 -0
  633. data/spec/mongoid/extensions/date_spec.rb +8 -164
  634. data/spec/mongoid/extensions/date_time_spec.rb +19 -66
  635. data/spec/mongoid/extensions/decimal128_spec.rb +3 -1
  636. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  637. data/spec/mongoid/extensions/float_spec.rb +25 -4
  638. data/spec/mongoid/extensions/hash_spec.rb +138 -1
  639. data/spec/mongoid/extensions/integer_spec.rb +22 -3
  640. data/spec/mongoid/extensions/module_spec.rb +2 -0
  641. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  642. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  643. data/spec/mongoid/extensions/object_spec.rb +27 -31
  644. data/spec/mongoid/extensions/range_spec.rb +9 -0
  645. data/spec/mongoid/extensions/regexp_spec.rb +25 -0
  646. data/spec/mongoid/extensions/set_spec.rb +2 -0
  647. data/spec/mongoid/extensions/string_spec.rb +113 -31
  648. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  649. data/spec/mongoid/extensions/symbol_spec.rb +2 -0
  650. data/spec/mongoid/extensions/time_spec.rb +31 -6
  651. data/spec/mongoid/extensions/time_with_zone_spec.rb +35 -6
  652. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  653. data/spec/mongoid/extensions_spec.rb +16 -2
  654. data/spec/mongoid/factory_spec.rb +304 -15
  655. data/spec/mongoid/fields/foreign_key_spec.rb +26 -32
  656. data/spec/mongoid/fields/localized_spec.rb +6 -4
  657. data/spec/mongoid/fields/standard_spec.rb +2 -0
  658. data/spec/mongoid/fields_spec.rb +420 -38
  659. data/spec/mongoid/findable_spec.rb +98 -19
  660. data/spec/mongoid/indexable/specification_spec.rb +2 -0
  661. data/spec/mongoid/indexable_spec.rb +69 -17
  662. data/spec/mongoid/inspectable_spec.rb +39 -2
  663. data/spec/mongoid/interceptable_spec.rb +273 -114
  664. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  665. data/spec/mongoid/loggable_spec.rb +2 -0
  666. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  667. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  668. data/spec/mongoid/matcher/extract_attribute_spec.rb +40 -0
  669. data/spec/mongoid/persistable/creatable_spec.rb +119 -29
  670. data/spec/mongoid/persistable/deletable_spec.rb +307 -11
  671. data/spec/mongoid/persistable/destroyable_spec.rb +225 -12
  672. data/spec/mongoid/persistable/incrementable_spec.rb +29 -13
  673. data/spec/mongoid/persistable/logical_spec.rb +19 -3
  674. data/spec/mongoid/persistable/poppable_spec.rb +19 -3
  675. data/spec/mongoid/persistable/pullable_spec.rb +36 -6
  676. data/spec/mongoid/persistable/pushable_spec.rb +91 -7
  677. data/spec/mongoid/persistable/renamable_spec.rb +18 -2
  678. data/spec/mongoid/persistable/savable_spec.rb +218 -50
  679. data/spec/mongoid/persistable/settable_spec.rb +213 -32
  680. data/spec/mongoid/persistable/unsettable_spec.rb +19 -3
  681. data/spec/mongoid/persistable/updatable_spec.rb +222 -21
  682. data/spec/mongoid/persistable/upsertable_spec.rb +4 -2
  683. data/spec/mongoid/persistable_spec.rb +116 -25
  684. data/spec/mongoid/persistence_context_spec.rb +696 -0
  685. data/spec/mongoid/positional_spec.rb +3 -1
  686. data/spec/mongoid/query_cache_middleware_spec.rb +68 -0
  687. data/spec/mongoid/query_cache_spec.rb +647 -45
  688. data/spec/mongoid/relations/proxy_spec.rb +126 -98
  689. data/spec/mongoid/reloadable_spec.rb +346 -17
  690. data/spec/mongoid/scopable_spec.rb +82 -22
  691. data/spec/mongoid/selectable_spec.rb +8 -6
  692. data/spec/mongoid/serializable_spec.rb +160 -79
  693. data/spec/mongoid/shardable_models.rb +61 -0
  694. data/spec/mongoid/shardable_spec.rb +145 -26
  695. data/spec/mongoid/stateful_spec.rb +3 -1
  696. data/spec/mongoid/tasks/database_rake_spec.rb +15 -13
  697. data/spec/mongoid/tasks/database_spec.rb +3 -1
  698. data/spec/mongoid/threaded_spec.rb +72 -2
  699. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  700. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  701. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  702. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  703. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  704. data/spec/mongoid/timestamps_spec.rb +8 -6
  705. data/spec/mongoid/touchable_spec.rb +588 -0
  706. data/spec/mongoid/touchable_spec_models.rb +53 -0
  707. data/spec/mongoid/traversable_spec.rb +1167 -1
  708. data/spec/mongoid/validatable/associated_spec.rb +3 -1
  709. data/spec/mongoid/validatable/format_spec.rb +2 -0
  710. data/spec/mongoid/validatable/length_spec.rb +2 -0
  711. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  712. data/spec/mongoid/validatable/presence_spec.rb +33 -26
  713. data/spec/mongoid/validatable/uniqueness_spec.rb +119 -81
  714. data/spec/mongoid/validatable_spec.rb +21 -3
  715. data/spec/mongoid_spec.rb +2 -0
  716. data/spec/rails/controller_extension/controller_runtime_spec.rb +112 -0
  717. data/spec/rails/mongoid_spec.rb +4 -2
  718. data/spec/shared/LICENSE +20 -0
  719. data/spec/shared/bin/get-mongodb-download-url +17 -0
  720. data/spec/shared/bin/s3-copy +45 -0
  721. data/spec/shared/bin/s3-upload +69 -0
  722. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  723. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  724. data/spec/shared/lib/mrss/constraints.rb +386 -0
  725. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  726. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  727. data/spec/shared/lib/mrss/lite_constraints.rb +199 -0
  728. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  729. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  730. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  731. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  732. data/spec/shared/lib/mrss/utils.rb +15 -0
  733. data/spec/shared/share/Dockerfile.erb +339 -0
  734. data/spec/shared/share/haproxy-1.conf +16 -0
  735. data/spec/shared/share/haproxy-2.conf +17 -0
  736. data/spec/shared/shlib/distro.sh +74 -0
  737. data/spec/shared/shlib/server.sh +379 -0
  738. data/spec/shared/shlib/set_env.sh +132 -0
  739. data/spec/spec_helper.rb +133 -53
  740. data/spec/support/authorization.rb +2 -0
  741. data/spec/support/client_registry.rb +9 -0
  742. data/spec/support/constraints.rb +53 -0
  743. data/spec/support/expectations.rb +21 -3
  744. data/spec/support/helpers.rb +11 -0
  745. data/spec/support/macros.rb +42 -0
  746. data/spec/support/models/account.rb +38 -0
  747. data/spec/support/models/acolyte.rb +19 -0
  748. data/spec/support/models/actor.rb +20 -0
  749. data/spec/support/models/actress.rb +4 -0
  750. data/spec/support/models/address.rb +85 -0
  751. data/spec/support/models/address_component.rb +7 -0
  752. data/spec/support/models/address_number.rb +8 -0
  753. data/spec/support/models/agency.rb +7 -0
  754. data/spec/support/models/agent.rb +18 -0
  755. data/spec/support/models/album.rb +20 -0
  756. data/spec/support/models/alert.rb +9 -0
  757. data/spec/support/models/animal.rb +28 -0
  758. data/spec/support/models/answer.rb +8 -0
  759. data/spec/support/models/appointment.rb +9 -0
  760. data/spec/support/models/armrest.rb +9 -0
  761. data/spec/support/models/array_field.rb +7 -0
  762. data/spec/support/models/article.rb +14 -0
  763. data/spec/support/models/artist.rb +91 -0
  764. data/spec/support/models/artwork.rb +6 -0
  765. data/spec/support/models/audible_sound.rb +3 -0
  766. data/spec/support/models/audio.rb +7 -0
  767. data/spec/support/models/augmentation.rb +13 -0
  768. data/spec/support/models/author.rb +8 -0
  769. data/spec/support/models/baby.rb +6 -0
  770. data/spec/support/models/band.rb +37 -0
  771. data/spec/support/models/bar.rb +12 -0
  772. data/spec/support/models/basic.rb +8 -0
  773. data/spec/support/models/bed.rb +3 -0
  774. data/spec/support/models/big_palette.rb +4 -0
  775. data/spec/support/models/birthday.rb +15 -0
  776. data/spec/support/models/bolt.rb +7 -0
  777. data/spec/support/models/bomb.rb +6 -0
  778. data/spec/support/models/book.rb +18 -0
  779. data/spec/support/models/breed.rb +6 -0
  780. data/spec/support/models/browser.rb +8 -0
  781. data/spec/support/models/building.rb +8 -0
  782. data/spec/support/models/building_address.rb +9 -0
  783. data/spec/support/models/bus.rb +9 -0
  784. data/spec/support/models/business.rb +7 -0
  785. data/spec/support/models/callback_test.rb +11 -0
  786. data/spec/support/models/canvas.rb +27 -0
  787. data/spec/support/models/car.rb +3 -0
  788. data/spec/support/models/cat.rb +10 -0
  789. data/spec/support/models/category.rb +10 -0
  790. data/spec/support/models/child.rb +6 -0
  791. data/spec/support/models/child_doc.rb +24 -0
  792. data/spec/support/models/church.rb +8 -0
  793. data/spec/support/models/circle.rb +5 -0
  794. data/spec/support/models/circuit.rb +6 -0
  795. data/spec/support/models/circus.rb +9 -0
  796. data/spec/support/models/code.rb +13 -0
  797. data/spec/support/models/coding/pull_request.rb +11 -0
  798. data/spec/support/models/coding.rb +3 -0
  799. data/spec/support/models/comment.rb +18 -0
  800. data/spec/support/models/company.rb +7 -0
  801. data/spec/support/models/consumption_period.rb +9 -0
  802. data/spec/support/models/contextable_item.rb +7 -0
  803. data/spec/support/models/contractor.rb +7 -0
  804. data/spec/support/models/cookie.rb +8 -0
  805. data/spec/support/models/country_code.rb +12 -0
  806. data/spec/support/models/courier_job.rb +6 -0
  807. data/spec/support/models/crate.rb +12 -0
  808. data/spec/support/models/customer.rb +10 -0
  809. data/spec/support/models/customer_address.rb +11 -0
  810. data/spec/support/models/deed.rb +7 -0
  811. data/spec/support/models/definition.rb +11 -0
  812. data/spec/support/models/delegating_patient.rb +15 -0
  813. data/spec/support/models/description.rb +13 -0
  814. data/spec/support/models/dictionary.rb +18 -0
  815. data/spec/support/models/division.rb +12 -0
  816. data/spec/support/models/doctor.rb +14 -0
  817. data/spec/support/models/dog.rb +9 -0
  818. data/spec/support/models/dokument.rb +8 -0
  819. data/spec/support/models/draft.rb +11 -0
  820. data/spec/support/models/dragon.rb +6 -0
  821. data/spec/support/models/driver.rb +9 -0
  822. data/spec/support/models/drug.rb +8 -0
  823. data/spec/support/models/dungeon.rb +6 -0
  824. data/spec/support/models/edit.rb +7 -0
  825. data/spec/support/models/email.rb +8 -0
  826. data/spec/support/models/employer.rb +7 -0
  827. data/spec/support/models/entry.rb +8 -0
  828. data/spec/support/models/eraser.rb +3 -0
  829. data/spec/support/models/even.rb +9 -0
  830. data/spec/support/models/event.rb +24 -0
  831. data/spec/support/models/exhibition.rb +6 -0
  832. data/spec/support/models/exhibitor.rb +8 -0
  833. data/spec/support/models/explosion.rb +6 -0
  834. data/spec/support/models/eye.rb +11 -0
  835. data/spec/support/models/eye_bowl.rb +11 -0
  836. data/spec/support/models/face.rb +10 -0
  837. data/spec/support/models/favorite.rb +8 -0
  838. data/spec/support/models/filesystem.rb +7 -0
  839. data/spec/support/models/fire_hydrant.rb +8 -0
  840. data/spec/support/models/firefox.rb +6 -0
  841. data/spec/support/models/fish.rb +9 -0
  842. data/spec/support/models/folder.rb +9 -0
  843. data/spec/support/models/folder_item.rb +11 -0
  844. data/spec/support/models/fruits.rb +36 -0
  845. data/spec/support/models/game.rb +21 -0
  846. data/spec/support/models/ghost.rb +9 -0
  847. data/spec/support/models/guitar.rb +4 -0
  848. data/spec/support/models/hole.rb +12 -0
  849. data/spec/support/models/home.rb +6 -0
  850. data/spec/support/models/house.rb +8 -0
  851. data/spec/support/models/html_writer.rb +5 -0
  852. data/spec/support/models/id_key.rb +8 -0
  853. data/spec/support/models/idnodef.rb +7 -0
  854. data/spec/support/models/image.rb +24 -0
  855. data/spec/support/models/implant.rb +18 -0
  856. data/spec/support/models/instrument.rb +8 -0
  857. data/spec/support/models/item.rb +10 -0
  858. data/spec/support/models/jar.rb +9 -0
  859. data/spec/support/models/kaleidoscope.rb +8 -0
  860. data/spec/support/models/kangaroo.rb +6 -0
  861. data/spec/support/models/label.rb +50 -0
  862. data/spec/support/models/language.rb +7 -0
  863. data/spec/support/models/lat_lng.rb +17 -0
  864. data/spec/support/models/league.rb +13 -0
  865. data/spec/support/models/learner.rb +4 -0
  866. data/spec/support/models/line_item.rb +8 -0
  867. data/spec/support/models/location.rb +10 -0
  868. data/spec/support/models/login.rb +10 -0
  869. data/spec/support/models/manufacturer.rb +9 -0
  870. data/spec/support/models/meat.rb +6 -0
  871. data/spec/support/models/membership.rb +6 -0
  872. data/spec/support/models/message.rb +13 -0
  873. data/spec/support/models/minim.rb +6 -0
  874. data/spec/support/models/mixed_drink.rb +6 -0
  875. data/spec/support/models/mop.rb +24 -0
  876. data/spec/support/models/movie.rb +15 -0
  877. data/spec/support/models/my_hash.rb +4 -0
  878. data/spec/support/models/name.rb +26 -0
  879. data/spec/support/models/name_only.rb +8 -0
  880. data/spec/support/models/node.rb +7 -0
  881. data/spec/support/models/note.rb +19 -0
  882. data/spec/support/models/nut.rb +7 -0
  883. data/spec/support/models/odd.rb +9 -0
  884. data/spec/support/models/order.rb +12 -0
  885. data/spec/support/models/ordered_post.rb +13 -0
  886. data/spec/support/models/ordered_preference.rb +8 -0
  887. data/spec/support/models/oscar.rb +16 -0
  888. data/spec/support/models/other_owner_object.rb +4 -0
  889. data/spec/support/models/override.rb +18 -0
  890. data/spec/support/models/ownable.rb +8 -0
  891. data/spec/support/models/owner.rb +10 -0
  892. data/spec/support/models/pack.rb +5 -0
  893. data/spec/support/models/page.rb +18 -0
  894. data/spec/support/models/page_question.rb +6 -0
  895. data/spec/support/models/palette.rb +9 -0
  896. data/spec/support/models/parent.rb +7 -0
  897. data/spec/support/models/parent_doc.rb +8 -0
  898. data/spec/support/models/passport.rb +13 -0
  899. data/spec/support/models/patient.rb +11 -0
  900. data/spec/support/models/pdf_writer.rb +5 -0
  901. data/spec/support/models/pencil.rb +3 -0
  902. data/spec/support/models/person.rb +230 -0
  903. data/spec/support/models/pet.rb +25 -0
  904. data/spec/support/models/pet_owner.rb +8 -0
  905. data/spec/support/models/phone.rb +13 -0
  906. data/spec/support/models/piano.rb +4 -0
  907. data/spec/support/models/pizza.rb +9 -0
  908. data/spec/support/models/player.rb +37 -0
  909. data/spec/support/models/post.rb +52 -0
  910. data/spec/support/models/post_genre.rb +8 -0
  911. data/spec/support/models/powerup.rb +13 -0
  912. data/spec/support/models/preference.rb +11 -0
  913. data/spec/support/models/princess.rb +12 -0
  914. data/spec/support/models/product.rb +19 -0
  915. data/spec/support/models/profile.rb +17 -0
  916. data/spec/support/models/pronunciation.rb +7 -0
  917. data/spec/support/models/pub.rb +8 -0
  918. data/spec/support/models/publication/encyclopedia.rb +11 -0
  919. data/spec/support/models/publication/review.rb +13 -0
  920. data/spec/support/models/publication.rb +4 -0
  921. data/spec/support/models/purchase.rb +6 -0
  922. data/spec/support/models/purchased_item.rb +10 -0
  923. data/spec/support/models/question.rb +10 -0
  924. data/spec/support/models/quiz.rb +9 -0
  925. data/spec/support/models/rating.rb +10 -0
  926. data/spec/support/models/record.rb +54 -0
  927. data/spec/support/models/registry.rb +6 -0
  928. data/spec/support/models/role.rb +9 -0
  929. data/spec/support/models/root_category.rb +6 -0
  930. data/spec/support/models/sandwich.rb +11 -0
  931. data/spec/support/models/scheduler.rb +9 -0
  932. data/spec/support/models/scribe.rb +7 -0
  933. data/spec/support/models/sealer.rb +7 -0
  934. data/spec/support/models/seat.rb +24 -0
  935. data/spec/support/models/seo.rb +9 -0
  936. data/spec/support/models/series.rb +7 -0
  937. data/spec/support/models/server.rb +15 -0
  938. data/spec/support/models/service.rb +24 -0
  939. data/spec/support/models/shape.rb +14 -0
  940. data/spec/support/models/shelf.rb +7 -0
  941. data/spec/support/models/shipment_address.rb +5 -0
  942. data/spec/support/models/shipping_container.rb +7 -0
  943. data/spec/support/models/shipping_pack.rb +5 -0
  944. data/spec/support/models/shirt.rb +11 -0
  945. data/spec/support/models/shop.rb +8 -0
  946. data/spec/support/models/short_agent.rb +6 -0
  947. data/spec/support/models/short_quiz.rb +7 -0
  948. data/spec/support/models/simple.rb +7 -0
  949. data/spec/support/models/slave.rb +8 -0
  950. data/spec/support/models/song.rb +10 -0
  951. data/spec/support/models/sound.rb +7 -0
  952. data/spec/support/models/spacer.rb +7 -0
  953. data/spec/support/models/square.rb +6 -0
  954. data/spec/support/models/staff.rb +9 -0
  955. data/spec/support/models/store_as_dup_test1.rb +7 -0
  956. data/spec/support/models/store_as_dup_test2.rb +7 -0
  957. data/spec/support/models/store_as_dup_test3.rb +7 -0
  958. data/spec/support/models/store_as_dup_test4.rb +7 -0
  959. data/spec/support/models/strategy.rb +5 -0
  960. data/spec/support/models/sub_item.rb +5 -0
  961. data/spec/support/models/subscription.rb +7 -0
  962. data/spec/support/models/survey.rb +7 -0
  963. data/spec/support/models/symptom.rb +8 -0
  964. data/spec/support/models/system_role.rb +7 -0
  965. data/spec/support/models/tag.rb +10 -0
  966. data/spec/support/models/target.rb +7 -0
  967. data/spec/support/models/template.rb +7 -0
  968. data/spec/support/models/thing.rb +11 -0
  969. data/spec/support/models/threadlocker.rb +7 -0
  970. data/spec/support/models/title.rb +5 -0
  971. data/spec/support/models/tool.rb +10 -0
  972. data/spec/support/models/topping.rb +7 -0
  973. data/spec/support/models/toy.rb +9 -0
  974. data/spec/support/models/track.rb +40 -0
  975. data/spec/support/models/translation.rb +7 -0
  976. data/spec/support/models/tree.rb +11 -0
  977. data/spec/support/models/truck.rb +7 -0
  978. data/spec/support/models/updatable.rb +7 -0
  979. data/spec/support/models/user.rb +23 -0
  980. data/spec/support/models/user_account.rb +12 -0
  981. data/spec/support/models/validation_callback.rb +12 -0
  982. data/spec/support/models/vehicle.rb +18 -0
  983. data/spec/support/models/version.rb +7 -0
  984. data/spec/support/models/vertex.rb +8 -0
  985. data/spec/support/models/vet_visit.rb +7 -0
  986. data/spec/support/models/video.rb +15 -0
  987. data/spec/support/models/video_game.rb +3 -0
  988. data/spec/support/models/washer.rb +7 -0
  989. data/spec/support/models/weapon.rb +13 -0
  990. data/spec/support/models/wiki_page.rb +17 -0
  991. data/spec/support/models/word.rb +17 -0
  992. data/spec/support/models/word_origin.rb +13 -0
  993. data/spec/support/models/writer.rb +13 -0
  994. data/spec/support/shared/time.rb +53 -0
  995. data/spec/support/spec_config.rb +60 -0
  996. data.tar.gz.sig +0 -0
  997. metadata +1347 -813
  998. metadata.gz.sig +0 -0
  999. data/lib/mongoid/clients/thread_options.rb +0 -19
  1000. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  1001. data/lib/mongoid/matchable/all.rb +0 -27
  1002. data/lib/mongoid/matchable/and.rb +0 -30
  1003. data/lib/mongoid/matchable/default.rb +0 -72
  1004. data/lib/mongoid/matchable/exists.rb +0 -23
  1005. data/lib/mongoid/matchable/gt.rb +0 -21
  1006. data/lib/mongoid/matchable/gte.rb +0 -21
  1007. data/lib/mongoid/matchable/in.rb +0 -24
  1008. data/lib/mongoid/matchable/lt.rb +0 -21
  1009. data/lib/mongoid/matchable/lte.rb +0 -21
  1010. data/lib/mongoid/matchable/ne.rb +0 -21
  1011. data/lib/mongoid/matchable/nin.rb +0 -22
  1012. data/lib/mongoid/matchable/or.rb +0 -33
  1013. data/lib/mongoid/matchable/regexp.rb +0 -27
  1014. data/lib/mongoid/matchable/size.rb +0 -21
  1015. data/lib/mongoid/railties/document.rb +0 -12
  1016. data/lib/mongoid/relations/accessors.rb +0 -264
  1017. data/lib/mongoid/relations/auto_save.rb +0 -86
  1018. data/lib/mongoid/relations/binding.rb +0 -218
  1019. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  1020. data/lib/mongoid/relations/bindings/embedded/many.rb +0 -43
  1021. data/lib/mongoid/relations/bindings/embedded/one.rb +0 -45
  1022. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  1023. data/lib/mongoid/relations/bindings/referenced/many.rb +0 -38
  1024. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  1025. data/lib/mongoid/relations/bindings/referenced/one.rb +0 -44
  1026. data/lib/mongoid/relations/bindings.rb +0 -9
  1027. data/lib/mongoid/relations/builder.rb +0 -57
  1028. data/lib/mongoid/relations/builders/embedded/in.rb +0 -29
  1029. data/lib/mongoid/relations/builders/embedded/many.rb +0 -36
  1030. data/lib/mongoid/relations/builders/embedded/one.rb +0 -30
  1031. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  1032. data/lib/mongoid/relations/builders/nested_attributes/one.rb +0 -126
  1033. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  1034. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  1035. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  1036. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  1037. data/lib/mongoid/relations/builders.rb +0 -106
  1038. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  1039. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  1040. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  1041. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  1042. data/lib/mongoid/relations/cascading.rb +0 -56
  1043. data/lib/mongoid/relations/constraint.rb +0 -55
  1044. data/lib/mongoid/relations/conversions.rb +0 -34
  1045. data/lib/mongoid/relations/counter_cache.rb +0 -150
  1046. data/lib/mongoid/relations/cyclic.rb +0 -107
  1047. data/lib/mongoid/relations/eager/base.rb +0 -153
  1048. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  1049. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  1050. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  1051. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  1052. data/lib/mongoid/relations/eager.rb +0 -41
  1053. data/lib/mongoid/relations/embedded/batchable.rb +0 -382
  1054. data/lib/mongoid/relations/embedded/in.rb +0 -229
  1055. data/lib/mongoid/relations/embedded/many.rb +0 -642
  1056. data/lib/mongoid/relations/embedded/one.rb +0 -222
  1057. data/lib/mongoid/relations/macros.rb +0 -359
  1058. data/lib/mongoid/relations/many.rb +0 -238
  1059. data/lib/mongoid/relations/marshalable.rb +0 -32
  1060. data/lib/mongoid/relations/metadata.rb +0 -1179
  1061. data/lib/mongoid/relations/nested_builder.rb +0 -74
  1062. data/lib/mongoid/relations/one.rb +0 -60
  1063. data/lib/mongoid/relations/options.rb +0 -49
  1064. data/lib/mongoid/relations/polymorphic.rb +0 -39
  1065. data/lib/mongoid/relations/proxy.rb +0 -245
  1066. data/lib/mongoid/relations/referenced/in.rb +0 -295
  1067. data/lib/mongoid/relations/referenced/many.rb +0 -808
  1068. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -472
  1069. data/lib/mongoid/relations/referenced/one.rb +0 -276
  1070. data/lib/mongoid/relations/reflections.rb +0 -64
  1071. data/lib/mongoid/relations/synchronization.rb +0 -169
  1072. data/lib/mongoid/relations/targets/enumerable.rb +0 -473
  1073. data/lib/mongoid/relations/targets.rb +0 -2
  1074. data/lib/mongoid/relations/touchable.rb +0 -94
  1075. data/lib/mongoid/relations.rb +0 -148
  1076. data/lib/support/ruby_version.rb +0 -26
  1077. data/spec/app/models/account.rb +0 -36
  1078. data/spec/app/models/acolyte.rb +0 -17
  1079. data/spec/app/models/actor.rb +0 -18
  1080. data/spec/app/models/actress.rb +0 -2
  1081. data/spec/app/models/address.rb +0 -79
  1082. data/spec/app/models/address_component.rb +0 -5
  1083. data/spec/app/models/address_number.rb +0 -6
  1084. data/spec/app/models/agency.rb +0 -5
  1085. data/spec/app/models/agent.rb +0 -14
  1086. data/spec/app/models/album.rb +0 -14
  1087. data/spec/app/models/alert.rb +0 -7
  1088. data/spec/app/models/animal.rb +0 -25
  1089. data/spec/app/models/answer.rb +0 -6
  1090. data/spec/app/models/appointment.rb +0 -7
  1091. data/spec/app/models/article.rb +0 -12
  1092. data/spec/app/models/artist.rb +0 -66
  1093. data/spec/app/models/artwork.rb +0 -4
  1094. data/spec/app/models/audio.rb +0 -5
  1095. data/spec/app/models/augmentation.rb +0 -11
  1096. data/spec/app/models/author.rb +0 -6
  1097. data/spec/app/models/baby.rb +0 -4
  1098. data/spec/app/models/band.rb +0 -28
  1099. data/spec/app/models/bar.rb +0 -10
  1100. data/spec/app/models/basic.rb +0 -6
  1101. data/spec/app/models/bed.rb +0 -1
  1102. data/spec/app/models/big_palette.rb +0 -2
  1103. data/spec/app/models/birthday.rb +0 -13
  1104. data/spec/app/models/bomb.rb +0 -4
  1105. data/spec/app/models/book.rb +0 -15
  1106. data/spec/app/models/breed.rb +0 -4
  1107. data/spec/app/models/browser.rb +0 -6
  1108. data/spec/app/models/building.rb +0 -6
  1109. data/spec/app/models/building_address.rb +0 -7
  1110. data/spec/app/models/bus.rb +0 -7
  1111. data/spec/app/models/business.rb +0 -5
  1112. data/spec/app/models/callback_test.rb +0 -9
  1113. data/spec/app/models/canvas.rb +0 -25
  1114. data/spec/app/models/car.rb +0 -1
  1115. data/spec/app/models/cat.rb +0 -8
  1116. data/spec/app/models/category.rb +0 -8
  1117. data/spec/app/models/child.rb +0 -4
  1118. data/spec/app/models/child_doc.rb +0 -22
  1119. data/spec/app/models/church.rb +0 -6
  1120. data/spec/app/models/circle.rb +0 -3
  1121. data/spec/app/models/circuit.rb +0 -4
  1122. data/spec/app/models/circus.rb +0 -7
  1123. data/spec/app/models/code.rb +0 -11
  1124. data/spec/app/models/comment.rb +0 -16
  1125. data/spec/app/models/company.rb +0 -5
  1126. data/spec/app/models/consumption_period.rb +0 -7
  1127. data/spec/app/models/contextable_item.rb +0 -5
  1128. data/spec/app/models/contractor.rb +0 -5
  1129. data/spec/app/models/cookie.rb +0 -6
  1130. data/spec/app/models/country_code.rb +0 -8
  1131. data/spec/app/models/courier_job.rb +0 -4
  1132. data/spec/app/models/definition.rb +0 -9
  1133. data/spec/app/models/description.rb +0 -11
  1134. data/spec/app/models/dictionary.rb +0 -10
  1135. data/spec/app/models/division.rb +0 -10
  1136. data/spec/app/models/doctor.rb +0 -12
  1137. data/spec/app/models/dog.rb +0 -7
  1138. data/spec/app/models/dokument.rb +0 -5
  1139. data/spec/app/models/draft.rb +0 -9
  1140. data/spec/app/models/dragon.rb +0 -4
  1141. data/spec/app/models/driver.rb +0 -7
  1142. data/spec/app/models/drug.rb +0 -6
  1143. data/spec/app/models/dungeon.rb +0 -4
  1144. data/spec/app/models/edit.rb +0 -5
  1145. data/spec/app/models/email.rb +0 -6
  1146. data/spec/app/models/employer.rb +0 -5
  1147. data/spec/app/models/entry.rb +0 -6
  1148. data/spec/app/models/eraser.rb +0 -1
  1149. data/spec/app/models/even.rb +0 -7
  1150. data/spec/app/models/event.rb +0 -22
  1151. data/spec/app/models/exhibition.rb +0 -4
  1152. data/spec/app/models/exhibitor.rb +0 -6
  1153. data/spec/app/models/explosion.rb +0 -4
  1154. data/spec/app/models/eye.rb +0 -9
  1155. data/spec/app/models/eye_bowl.rb +0 -9
  1156. data/spec/app/models/face.rb +0 -8
  1157. data/spec/app/models/favorite.rb +0 -6
  1158. data/spec/app/models/filesystem.rb +0 -5
  1159. data/spec/app/models/fire_hydrant.rb +0 -6
  1160. data/spec/app/models/firefox.rb +0 -4
  1161. data/spec/app/models/fish.rb +0 -7
  1162. data/spec/app/models/folder.rb +0 -7
  1163. data/spec/app/models/folder_item.rb +0 -9
  1164. data/spec/app/models/fruits.rb +0 -34
  1165. data/spec/app/models/game.rb +0 -19
  1166. data/spec/app/models/ghost.rb +0 -7
  1167. data/spec/app/models/home.rb +0 -4
  1168. data/spec/app/models/house.rb +0 -6
  1169. data/spec/app/models/html_writer.rb +0 -3
  1170. data/spec/app/models/id_key.rb +0 -6
  1171. data/spec/app/models/image.rb +0 -22
  1172. data/spec/app/models/implant.rb +0 -16
  1173. data/spec/app/models/item.rb +0 -8
  1174. data/spec/app/models/jar.rb +0 -7
  1175. data/spec/app/models/kaleidoscope.rb +0 -6
  1176. data/spec/app/models/kangaroo.rb +0 -4
  1177. data/spec/app/models/label.rb +0 -47
  1178. data/spec/app/models/language.rb +0 -5
  1179. data/spec/app/models/lat_lng.rb +0 -15
  1180. data/spec/app/models/league.rb +0 -11
  1181. data/spec/app/models/learner.rb +0 -2
  1182. data/spec/app/models/line_item.rb +0 -6
  1183. data/spec/app/models/location.rb +0 -8
  1184. data/spec/app/models/login.rb +0 -8
  1185. data/spec/app/models/manufacturer.rb +0 -7
  1186. data/spec/app/models/meat.rb +0 -4
  1187. data/spec/app/models/membership.rb +0 -4
  1188. data/spec/app/models/message.rb +0 -11
  1189. data/spec/app/models/mixed_drink.rb +0 -4
  1190. data/spec/app/models/movie.rb +0 -13
  1191. data/spec/app/models/my_hash.rb +0 -2
  1192. data/spec/app/models/name.rb +0 -24
  1193. data/spec/app/models/node.rb +0 -5
  1194. data/spec/app/models/note.rb +0 -17
  1195. data/spec/app/models/odd.rb +0 -7
  1196. data/spec/app/models/ordered_post.rb +0 -6
  1197. data/spec/app/models/ordered_preference.rb +0 -6
  1198. data/spec/app/models/oscar.rb +0 -15
  1199. data/spec/app/models/override.rb +0 -16
  1200. data/spec/app/models/ownable.rb +0 -6
  1201. data/spec/app/models/owner.rb +0 -6
  1202. data/spec/app/models/pack.rb +0 -3
  1203. data/spec/app/models/page.rb +0 -16
  1204. data/spec/app/models/page_question.rb +0 -4
  1205. data/spec/app/models/palette.rb +0 -7
  1206. data/spec/app/models/parent.rb +0 -5
  1207. data/spec/app/models/parent_doc.rb +0 -6
  1208. data/spec/app/models/passport.rb +0 -5
  1209. data/spec/app/models/patient.rb +0 -9
  1210. data/spec/app/models/pdf_writer.rb +0 -3
  1211. data/spec/app/models/pencil.rb +0 -1
  1212. data/spec/app/models/person.rb +0 -207
  1213. data/spec/app/models/pet.rb +0 -23
  1214. data/spec/app/models/pet_owner.rb +0 -6
  1215. data/spec/app/models/phone.rb +0 -9
  1216. data/spec/app/models/pizza.rb +0 -7
  1217. data/spec/app/models/player.rb +0 -35
  1218. data/spec/app/models/post.rb +0 -50
  1219. data/spec/app/models/post_genre.rb +0 -6
  1220. data/spec/app/models/powerup.rb +0 -11
  1221. data/spec/app/models/preference.rb +0 -9
  1222. data/spec/app/models/princess.rb +0 -8
  1223. data/spec/app/models/product.rb +0 -17
  1224. data/spec/app/models/profile.rb +0 -5
  1225. data/spec/app/models/pronunciation.rb +0 -5
  1226. data/spec/app/models/pub.rb +0 -6
  1227. data/spec/app/models/purchase.rb +0 -4
  1228. data/spec/app/models/question.rb +0 -8
  1229. data/spec/app/models/quiz.rb +0 -7
  1230. data/spec/app/models/rating.rb +0 -8
  1231. data/spec/app/models/record.rb +0 -51
  1232. data/spec/app/models/registry.rb +0 -4
  1233. data/spec/app/models/role.rb +0 -7
  1234. data/spec/app/models/root_category.rb +0 -4
  1235. data/spec/app/models/sandwich.rb +0 -9
  1236. data/spec/app/models/scheduler.rb +0 -7
  1237. data/spec/app/models/seo.rb +0 -7
  1238. data/spec/app/models/series.rb +0 -4
  1239. data/spec/app/models/server.rb +0 -13
  1240. data/spec/app/models/service.rb +0 -22
  1241. data/spec/app/models/shape.rb +0 -12
  1242. data/spec/app/models/shelf.rb +0 -5
  1243. data/spec/app/models/shipment_address.rb +0 -2
  1244. data/spec/app/models/shipping_container.rb +0 -5
  1245. data/spec/app/models/shipping_pack.rb +0 -3
  1246. data/spec/app/models/shop.rb +0 -6
  1247. data/spec/app/models/short_agent.rb +0 -4
  1248. data/spec/app/models/short_quiz.rb +0 -5
  1249. data/spec/app/models/simple.rb +0 -5
  1250. data/spec/app/models/slave.rb +0 -6
  1251. data/spec/app/models/song.rb +0 -8
  1252. data/spec/app/models/sound.rb +0 -5
  1253. data/spec/app/models/square.rb +0 -4
  1254. data/spec/app/models/staff.rb +0 -7
  1255. data/spec/app/models/store_as_dup_test1.rb +0 -5
  1256. data/spec/app/models/store_as_dup_test2.rb +0 -5
  1257. data/spec/app/models/strategy.rb +0 -3
  1258. data/spec/app/models/sub_item.rb +0 -3
  1259. data/spec/app/models/subscription.rb +0 -4
  1260. data/spec/app/models/survey.rb +0 -5
  1261. data/spec/app/models/symptom.rb +0 -6
  1262. data/spec/app/models/tag.rb +0 -8
  1263. data/spec/app/models/target.rb +0 -5
  1264. data/spec/app/models/template.rb +0 -5
  1265. data/spec/app/models/thing.rb +0 -9
  1266. data/spec/app/models/title.rb +0 -3
  1267. data/spec/app/models/tool.rb +0 -8
  1268. data/spec/app/models/topping.rb +0 -5
  1269. data/spec/app/models/track.rb +0 -38
  1270. data/spec/app/models/translation.rb +0 -5
  1271. data/spec/app/models/tree.rb +0 -9
  1272. data/spec/app/models/truck.rb +0 -3
  1273. data/spec/app/models/user.rb +0 -21
  1274. data/spec/app/models/user_account.rb +0 -10
  1275. data/spec/app/models/validation_callback.rb +0 -10
  1276. data/spec/app/models/vehicle.rb +0 -11
  1277. data/spec/app/models/version.rb +0 -5
  1278. data/spec/app/models/vet_visit.rb +0 -5
  1279. data/spec/app/models/video.rb +0 -13
  1280. data/spec/app/models/video_game.rb +0 -1
  1281. data/spec/app/models/weapon.rb +0 -11
  1282. data/spec/app/models/wiki_page.rb +0 -14
  1283. data/spec/app/models/word.rb +0 -15
  1284. data/spec/app/models/word_origin.rb +0 -11
  1285. data/spec/app/models/writer.rb +0 -11
  1286. data/spec/mongoid/extensions/origin/regexp_raw_spec.rb +0 -89
  1287. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  1288. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  1289. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1290. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1291. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1292. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1293. data/spec/mongoid/matchable/gt_spec.rb +0 -75
  1294. data/spec/mongoid/matchable/gte_spec.rb +0 -74
  1295. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1296. data/spec/mongoid/matchable/lt_spec.rb +0 -74
  1297. data/spec/mongoid/matchable/lte_spec.rb +0 -74
  1298. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1299. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1300. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1301. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1302. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1303. data/spec/mongoid/matchable_spec.rb +0 -708
  1304. data/spec/mongoid/railties/document_spec.rb +0 -24
  1305. data/spec/mongoid/relations/accessors_spec.rb +0 -821
  1306. data/spec/mongoid/relations/auto_save_spec.rb +0 -281
  1307. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +0 -171
  1308. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +0 -54
  1309. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +0 -77
  1310. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +0 -241
  1311. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +0 -153
  1312. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +0 -178
  1313. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +0 -131
  1314. data/spec/mongoid/relations/builders/embedded/in_spec.rb +0 -34
  1315. data/spec/mongoid/relations/builders/embedded/many_spec.rb +0 -132
  1316. data/spec/mongoid/relations/builders/embedded/one_spec.rb +0 -99
  1317. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +0 -233
  1318. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +0 -250
  1319. data/spec/mongoid/relations/builders/referenced/in_spec.rb +0 -230
  1320. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  1321. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  1322. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  1323. data/spec/mongoid/relations/builders_spec.rb +0 -226
  1324. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  1325. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  1326. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  1327. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  1328. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  1329. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  1330. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  1331. data/spec/mongoid/relations/counter_cache_spec.rb +0 -389
  1332. data/spec/mongoid/relations/cyclic_spec.rb +0 -178
  1333. data/spec/mongoid/relations/eager/belongs_to_spec.rb +0 -163
  1334. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +0 -117
  1335. data/spec/mongoid/relations/eager/has_many_spec.rb +0 -244
  1336. data/spec/mongoid/relations/eager/has_one_spec.rb +0 -163
  1337. data/spec/mongoid/relations/eager_spec.rb +0 -239
  1338. data/spec/mongoid/relations/embedded/dirty_spec.rb +0 -65
  1339. data/spec/mongoid/relations/embedded/in_spec.rb +0 -579
  1340. data/spec/mongoid/relations/embedded/many_spec.rb +0 -4166
  1341. data/spec/mongoid/relations/embedded/one_spec.rb +0 -1067
  1342. data/spec/mongoid/relations/macros_spec.rb +0 -631
  1343. data/spec/mongoid/relations/metadata_spec.rb +0 -1971
  1344. data/spec/mongoid/relations/options_spec.rb +0 -35
  1345. data/spec/mongoid/relations/polymorphic_spec.rb +0 -128
  1346. data/spec/mongoid/relations/referenced/in_spec.rb +0 -1326
  1347. data/spec/mongoid/relations/referenced/many_spec.rb +0 -3806
  1348. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +0 -3589
  1349. data/spec/mongoid/relations/referenced/one_spec.rb +0 -1240
  1350. data/spec/mongoid/relations/reflections_spec.rb +0 -101
  1351. data/spec/mongoid/relations/synchronization_spec.rb +0 -449
  1352. data/spec/mongoid/relations/targets/enumerable_spec.rb +0 -1717
  1353. data/spec/mongoid/relations/touchable_spec.rb +0 -362
  1354. 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