mongoid 3.1.4 → 3.1.5

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