mongoid 5.4.1 → 7.4.0

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