mongoid 6.4.4 → 7.3.2

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