mongoid 3.1.4 → 3.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,1508 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Dirty do
4
+
5
+ describe "#attribute_change" do
6
+
7
+ context "when the attribute has changed from the persisted value" do
8
+
9
+ context "when using the setter" do
10
+
11
+ let(:person) do
12
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
13
+ end
14
+
15
+ before do
16
+ person.title = "Captain Obvious"
17
+ end
18
+
19
+ it "returns an array of the old value and new value" do
20
+ person.send(:attribute_change, "title").should eq(
21
+ [ "Grand Poobah", "Captain Obvious" ]
22
+ )
23
+ end
24
+
25
+ it "allows access via (attribute)_change" do
26
+ person.title_change.should eq(
27
+ [ "Grand Poobah", "Captain Obvious" ]
28
+ )
29
+ end
30
+
31
+ context "when the field is aliased" do
32
+
33
+ let(:person) do
34
+ Person.new(test: "Aliased 1").tap(&:move_changes)
35
+ end
36
+
37
+ before do
38
+ person.test = "Aliased 2"
39
+ end
40
+
41
+ it "returns an array of the old value and new value" do
42
+ person.send(:attribute_change, "test").should eq(
43
+ [ "Aliased 1", "Aliased 2" ]
44
+ )
45
+ end
46
+
47
+ it "allows access via (attribute)_change" do
48
+ person.test_change.should eq(
49
+ [ "Aliased 1", "Aliased 2" ]
50
+ )
51
+ end
52
+ end
53
+ end
54
+
55
+ context "when using [] methods" do
56
+
57
+ let(:person) do
58
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
59
+ end
60
+
61
+ before do
62
+ person[:title] = "Captain Obvious"
63
+ end
64
+
65
+ it "returns an array of the old value and new value" do
66
+ person.send(:attribute_change, "title").should eq(
67
+ [ "Grand Poobah", "Captain Obvious" ]
68
+ )
69
+ end
70
+
71
+ it "allows access via (attribute)_change" do
72
+ person.title_change.should eq(
73
+ [ "Grand Poobah", "Captain Obvious" ]
74
+ )
75
+ end
76
+ end
77
+ end
78
+
79
+ context "when the attribute has changed from the default value" do
80
+
81
+ context "when using the setter" do
82
+
83
+ let(:person) do
84
+ Person.new(pets: true)
85
+ end
86
+
87
+ it "returns an array of nil and new value" do
88
+ person.send(:attribute_change, "pets").should eq([ nil, true ])
89
+ end
90
+
91
+ it "allows access via (attribute)_change" do
92
+ person.pets_change.should eq([ nil, true ])
93
+ end
94
+ end
95
+
96
+ context "when using [] methods" do
97
+
98
+ context "when the field is defined" do
99
+
100
+ let(:person) do
101
+ Person.new
102
+ end
103
+
104
+ before do
105
+ person[:pets] = true
106
+ end
107
+
108
+ it "returns an array of nil and new value" do
109
+ person.send(:attribute_change, "pets").should eq([ nil, true ])
110
+ end
111
+
112
+ it "allows access via (attribute)_change" do
113
+ person.pets_change.should eq([ nil, true ])
114
+ end
115
+ end
116
+
117
+ context "when the field is not defined" do
118
+
119
+ let(:person) do
120
+ Person.new
121
+ end
122
+
123
+ before do
124
+ person[:a] = "test"
125
+ end
126
+
127
+ it "returns an array of nil and new value" do
128
+ person.send(:attribute_change, "a").should eq([ nil, "test" ])
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ context "when the attribute changes multiple times" do
135
+
136
+ let(:person) do
137
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
138
+ end
139
+
140
+ before do
141
+ person.title = "Captain Obvious"
142
+ person.title = "Dark Helmet"
143
+ end
144
+
145
+ it "returns an array of the original value and new value" do
146
+ person.send(:attribute_change, "title").should eq(
147
+ [ "Grand Poobah", "Dark Helmet" ]
148
+ )
149
+ end
150
+
151
+ it "allows access via (attribute)_change" do
152
+ person.title_change.should eq(
153
+ [ "Grand Poobah", "Dark Helmet" ]
154
+ )
155
+ end
156
+ end
157
+
158
+ context "when the attribute is modified in place" do
159
+
160
+ context "when the attribute is an array" do
161
+
162
+ let(:person) do
163
+ Person.new(aliases: [ "Grand Poobah" ]).tap(&:move_changes)
164
+ end
165
+
166
+ before do
167
+ person.aliases[0] = "Dark Helmet"
168
+ end
169
+
170
+ it "returns an array of the original value and new value" do
171
+ person.send(:attribute_change, "aliases").should eq(
172
+ [[ "Grand Poobah" ], [ "Dark Helmet" ]]
173
+ )
174
+ end
175
+
176
+ it "allows access via (attribute)_change" do
177
+ person.aliases_change.should eq(
178
+ [[ "Grand Poobah" ], [ "Dark Helmet" ]]
179
+ )
180
+ end
181
+
182
+ context "when the attribute changes multiple times" do
183
+
184
+ before do
185
+ person.aliases << "Colonel Sanders"
186
+ end
187
+
188
+ it "returns an array of the original value and new value" do
189
+ person.send(:attribute_change, "aliases").should eq(
190
+ [[ "Grand Poobah" ], [ "Dark Helmet", "Colonel Sanders" ]]
191
+ )
192
+ end
193
+ end
194
+ end
195
+
196
+ context "when the attribute is a hash" do
197
+
198
+ let(:person) do
199
+ Person.new(map: { location: "Home" }).tap(&:move_changes)
200
+ end
201
+
202
+ before do
203
+ person.map[:location] = "Work"
204
+ end
205
+
206
+ it "returns an array of the original value and new value" do
207
+ person.send(:attribute_change, "map").should eq(
208
+ [{ location: "Home" }, { location: "Work" }]
209
+ )
210
+ end
211
+
212
+ it "allows access via (attribute)_change" do
213
+ person.map_change.should eq(
214
+ [{ location: "Home" }, { location: "Work" }]
215
+ )
216
+ end
217
+
218
+ context "when the attribute changes multiple times" do
219
+
220
+ before do
221
+ person.map[:lat] = 20.0
222
+ end
223
+
224
+ it "returns an array of the original value and new value" do
225
+ person.send(:attribute_change, "map").should eq(
226
+ [{ location: "Home" }, { location: "Work", lat: 20.0 }]
227
+ )
228
+ end
229
+ end
230
+
231
+ context "when the values are arrays" do
232
+
233
+ let(:map) do
234
+ {
235
+ "stack1" => [ 1, 2, 3, 4 ],
236
+ "stack2" => [ 1, 2, 3, 4 ],
237
+ "stack3" => [ 1, 2, 3, 4 ]
238
+ }
239
+ end
240
+
241
+ before do
242
+ person.map = map
243
+ person.move_changes
244
+ end
245
+
246
+ context "when reordering the arrays inline" do
247
+
248
+ before do
249
+ person.map["stack1"].reverse!
250
+ end
251
+
252
+ it "flags the attribute as changed" do
253
+ person.send(:attribute_change, "map").should eq(
254
+ [
255
+ {
256
+ "stack1" => [ 1, 2, 3, 4 ],
257
+ "stack2" => [ 1, 2, 3, 4 ],
258
+ "stack3" => [ 1, 2, 3, 4 ]
259
+ },
260
+ {
261
+ "stack1" => [ 4, 3, 2, 1 ],
262
+ "stack2" => [ 1, 2, 3, 4 ],
263
+ "stack3" => [ 1, 2, 3, 4 ]
264
+ },
265
+ ]
266
+ )
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ context "when the attribute has not changed from the persisted value" do
274
+
275
+ let(:person) do
276
+ Person.new(title: nil)
277
+ end
278
+
279
+ it "returns nil" do
280
+ person.send(:attribute_change, "title").should be_nil
281
+ end
282
+ end
283
+
284
+ context "when the attribute has not changed from the default value" do
285
+
286
+ context "when the attribute differs from the persisted value" do
287
+
288
+ let(:person) do
289
+ Person.new
290
+ end
291
+
292
+ it "returns the change" do
293
+ person.send(:attribute_change, "pets").should eq([ nil, false ])
294
+ end
295
+ end
296
+
297
+ context "when the attribute does not differ from the persisted value" do
298
+
299
+ let(:person) do
300
+ Person.instantiate("pets" => false)
301
+ end
302
+
303
+ it "returns nil" do
304
+ person.send(:attribute_change, "pets").should be_nil
305
+ end
306
+ end
307
+ end
308
+
309
+ context "when the attribute has been set with the same value" do
310
+
311
+ let(:person) do
312
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
313
+ end
314
+
315
+ before do
316
+ person.title = "Grand Poobah"
317
+ end
318
+
319
+ it "returns an empty array" do
320
+ person.send(:attribute_change, "title").should be_nil
321
+ end
322
+ end
323
+
324
+ context "when the attribute is removed" do
325
+
326
+ let(:person) do
327
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
328
+ end
329
+
330
+ before do
331
+ person.remove_attribute(:title)
332
+ end
333
+
334
+ it "returns an empty array" do
335
+ person.send(:attribute_change, "title").should eq(
336
+ [ "Grand Poobah", nil ]
337
+ )
338
+ end
339
+ end
340
+ end
341
+
342
+ describe "#attribute_changed?" do
343
+
344
+ context "when the attribute has changed from the persisted value" do
345
+
346
+ let(:person) do
347
+ Person.new(title: "Grand Poobah")
348
+ end
349
+
350
+ before do
351
+ person.title = "Captain Obvious"
352
+ end
353
+
354
+ it "returns true" do
355
+ person.send(:attribute_changed?, "title").should be_true
356
+ end
357
+
358
+ it "allows access via (attribute)_changed?" do
359
+ person.title_changed?.should be_true
360
+ end
361
+
362
+ context "when the field is aliased" do
363
+
364
+ let(:person) do
365
+ Person.new(test: "Aliased 1")
366
+ end
367
+
368
+ before do
369
+ person.test = "Aliased 2"
370
+ end
371
+
372
+ it "returns true" do
373
+ person.send(:attribute_changed?, "test").should be_true
374
+ end
375
+
376
+ it "allows access via (attribute)_changed?" do
377
+ person.test_changed?.should be_true
378
+ end
379
+ end
380
+ end
381
+
382
+ context "when the attribute has changed from the default value" do
383
+
384
+ let(:person) do
385
+ Person.new
386
+ end
387
+
388
+ before do
389
+ person.pets = true
390
+ end
391
+
392
+ it "returns true" do
393
+ person.send(:attribute_changed?, "pets").should be_true
394
+ end
395
+
396
+ it "allows access via (attribute)_changed?" do
397
+ person.pets_changed?.should be_true
398
+ end
399
+ end
400
+
401
+ context "when the attribute has not changed the persisted value" do
402
+
403
+ let!(:person) do
404
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
405
+ end
406
+
407
+ it "returns false" do
408
+ person.send(:attribute_changed?, "title").should be_false
409
+ end
410
+ end
411
+
412
+ context "when the attribute has not changed from the default value" do
413
+
414
+ context "when the attribute is not enumerable" do
415
+
416
+ context "when the attribute differs from the persisted value" do
417
+
418
+ let!(:person) do
419
+ Person.new
420
+ end
421
+
422
+ it "returns true" do
423
+ person.send(:attribute_changed?, "pets").should be_true
424
+ end
425
+ end
426
+
427
+ context "when the attribute does not differ from the persisted value" do
428
+
429
+ let!(:person) do
430
+ Person.instantiate("pets" => false)
431
+ end
432
+
433
+ it "returns false" do
434
+ person.send(:attribute_changed?, "pets").should be_false
435
+ end
436
+ end
437
+ end
438
+
439
+ context "when the attribute is an array" do
440
+
441
+ let!(:person) do
442
+ Person.new(aliases: [ "Bond" ])
443
+ end
444
+
445
+ context "when the array is only accessed" do
446
+
447
+ before do
448
+ person.move_changes
449
+ person.aliases
450
+ end
451
+
452
+ it "returns false" do
453
+ person.should_not be_aliases_changed
454
+ end
455
+ end
456
+ end
457
+
458
+ context "when the attribute is a hash" do
459
+
460
+ let!(:person) do
461
+ Person.new(map: { key: "value" })
462
+ end
463
+
464
+ context "when the hash is only accessed" do
465
+
466
+ before do
467
+ person.move_changes
468
+ person.map
469
+ end
470
+
471
+ it "returns false" do
472
+ person.should_not be_map_changed
473
+ end
474
+ end
475
+ end
476
+ end
477
+ end
478
+
479
+ describe "#attribute_changed_from_default?" do
480
+
481
+ context "when the attribute differs from the default value" do
482
+
483
+ let(:person) do
484
+ Person.new(age: 33)
485
+ end
486
+
487
+ it "returns true" do
488
+ person.should be_age_changed_from_default
489
+ end
490
+ end
491
+
492
+ context "when the attribute is the same as the default" do
493
+
494
+ let(:person) do
495
+ Person.new
496
+ end
497
+
498
+ it "returns false" do
499
+ person.should_not be_age_changed_from_default
500
+ end
501
+ end
502
+ end
503
+
504
+ describe "#attribute_was" do
505
+
506
+ context "when the attribute has changed from the persisted value" do
507
+
508
+ let(:person) do
509
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
510
+ end
511
+
512
+ before do
513
+ person.title = "Captain Obvious"
514
+ end
515
+
516
+ it "returns the old value" do
517
+ person.send(:attribute_was, "title").should eq("Grand Poobah")
518
+ end
519
+
520
+ it "allows access via (attribute)_was" do
521
+ person.title_was.should eq("Grand Poobah")
522
+ end
523
+
524
+ context "when the field is aliased" do
525
+
526
+ let(:person) do
527
+ Person.new(test: "Aliased 1").tap(&:move_changes)
528
+ end
529
+
530
+ before do
531
+ person.test = "Aliased 2"
532
+ end
533
+
534
+ it "returns the old value" do
535
+ person.send(:attribute_was, "test").should eq("Aliased 1")
536
+ end
537
+
538
+ it "allows access via (attribute)_was" do
539
+ person.test_was.should eq("Aliased 1")
540
+ end
541
+ end
542
+ end
543
+
544
+ context "when the attribute has changed from the default value" do
545
+
546
+ let(:person) do
547
+ Person.new
548
+ end
549
+
550
+ before do
551
+ person.pets = true
552
+ end
553
+
554
+ it "returns the default value" do
555
+ person.send(:attribute_was, "pets").should be_false
556
+ end
557
+
558
+ it "allows access via (attribute)_was" do
559
+ person.pets_was.should be_false
560
+ end
561
+ end
562
+
563
+ context "when the attribute has not changed from the persisted value" do
564
+
565
+ let!(:person) do
566
+ Person.new(title: "Grand Poobah").tap(&:move_changes)
567
+ end
568
+
569
+ it "returns the original value" do
570
+ person.send(:attribute_was, "title").should eq("Grand Poobah")
571
+ end
572
+ end
573
+
574
+ context "when the attribute has not changed from the default value" do
575
+
576
+ let(:person) do
577
+ Person.new
578
+ end
579
+
580
+ it "returns the default value" do
581
+ person.send(:attribute_was, "pets").should be_false
582
+ end
583
+ end
584
+ end
585
+
586
+ describe "#attribute_will_change!" do
587
+
588
+ let(:aliases) do
589
+ [ "007" ]
590
+ end
591
+
592
+ let(:person) do
593
+ Person.new(aliases: aliases, test: "Aliased 1")
594
+ end
595
+
596
+ before do
597
+ person.changed_attributes.clear
598
+ end
599
+
600
+ context "when the value has not changed" do
601
+
602
+ before do
603
+ person.aliases_will_change!
604
+ end
605
+
606
+ let(:changes) do
607
+ person.changes
608
+ end
609
+
610
+ it "does not return the value in the changes" do
611
+ changes.should be_empty
612
+ end
613
+
614
+ it "is not flagged as changed" do
615
+ person.should_not be_changed
616
+ end
617
+ end
618
+
619
+ context "when the value has changed" do
620
+
621
+ before do
622
+ person.aliases_will_change!
623
+ person.aliases << "008"
624
+ end
625
+
626
+ let(:changes) do
627
+ person.changes
628
+ end
629
+
630
+ it "returns the value in the changes" do
631
+ changes.should eq({ "aliases" => [[ "007" ], [ "007", "008" ]] })
632
+ end
633
+ end
634
+
635
+ context "when the value is duplicable" do
636
+
637
+ context "when the attribute has not been cloned" do
638
+
639
+ before do
640
+ person.aliases_will_change!
641
+ end
642
+
643
+ let(:changed) do
644
+ person.changed_attributes
645
+ end
646
+
647
+ it "clones the value" do
648
+ changed["aliases"].should_not equal(aliases)
649
+ end
650
+
651
+ it "puts the old value in the changes" do
652
+ changed["aliases"].should eq(aliases)
653
+ end
654
+ end
655
+
656
+ context "when the attribute has been flagged" do
657
+
658
+ before do
659
+ person.changed_attributes["aliases"] = aliases
660
+ aliases.should_receive(:clone).never
661
+ person.aliases_will_change!
662
+ end
663
+
664
+ let(:changed) do
665
+ person.changed_attributes
666
+ end
667
+
668
+ it "does not clone the value" do
669
+ changed["aliases"].should equal(aliases)
670
+ end
671
+
672
+ it "retains the first value in the changes" do
673
+ changed["aliases"].should eq(aliases)
674
+ end
675
+ end
676
+ end
677
+ end
678
+
679
+ describe "#changed" do
680
+
681
+ context "when the document has changed" do
682
+
683
+ let(:person) do
684
+ Person.instantiate(title: "Grand Poobah")
685
+ end
686
+
687
+ before do
688
+ person.title = "Captain Obvious"
689
+ end
690
+
691
+ it "returns an array of changed field names" do
692
+ person.changed.should include("title")
693
+ end
694
+ end
695
+
696
+ context "when the document has not changed" do
697
+
698
+ let(:person) do
699
+ Person.instantiate({})
700
+ end
701
+
702
+ it "does not include non changed fields" do
703
+ person.changed.should_not include("title")
704
+ end
705
+ end
706
+
707
+ context "when the document is embedded" do
708
+
709
+ let(:person) do
710
+ Person.create
711
+ end
712
+
713
+ let!(:name) do
714
+ person.create_name(first_name: "Layne", last_name: "Staley")
715
+ end
716
+
717
+ context "when changing attributes via []" do
718
+
719
+ before do
720
+ person.name["a"] = "testing"
721
+ end
722
+
723
+ it "returns true" do
724
+ person.name.should be_changed
725
+ end
726
+ end
727
+ end
728
+ end
729
+
730
+ describe "#changed?" do
731
+
732
+ context "when the document has changed" do
733
+
734
+ let(:person) do
735
+ Person.new(title: "Grand Poobah")
736
+ end
737
+
738
+ before do
739
+ person.title = "Captain Obvious"
740
+ end
741
+
742
+ it "returns true" do
743
+ person.should be_changed
744
+ end
745
+ end
746
+
747
+ context "when a hash field has been accessed" do
748
+
749
+ context "when the field has not changed" do
750
+
751
+ let(:person) do
752
+ Person.create(map: { name: "value" })
753
+ end
754
+
755
+ before do
756
+ person.map
757
+ end
758
+
759
+ it "returns false" do
760
+ person.should_not be_changed
761
+ end
762
+ end
763
+
764
+ context "when the field is changed" do
765
+
766
+ let(:person) do
767
+ Person.create(map: { name: "value" })
768
+ end
769
+
770
+ before do
771
+ person.map = { name: "another" }
772
+ end
773
+
774
+ it "returns true" do
775
+ person.should be_changed
776
+ end
777
+ end
778
+
779
+ context "when a dynamic field is changed in place" do
780
+
781
+ let(:person) do
782
+ Person.create(other_name: { full: {first: 'first', last: 'last'} })
783
+ end
784
+
785
+ before do
786
+ Mongoid.configure.allow_dynamic_fields = true
787
+ person.other_name[:full][:first] = 'Name'
788
+ end
789
+
790
+ it "returns true" do
791
+ person.changes.should_not be_empty
792
+ person.should be_changed
793
+ end
794
+ end
795
+ end
796
+
797
+ context "when the document has not changed" do
798
+
799
+ let(:acolyte) do
800
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
801
+ end
802
+
803
+ it "returns false" do
804
+ acolyte.should_not be_changed
805
+ end
806
+ end
807
+
808
+ context "when a child has changed" do
809
+
810
+ let(:person) do
811
+ Person.create
812
+ end
813
+
814
+ let!(:address) do
815
+ person.addresses.create(street: "hobrecht")
816
+ end
817
+
818
+ before do
819
+ address.number = 10
820
+ end
821
+
822
+ it "returns true" do
823
+ person.should be_changed
824
+ end
825
+ end
826
+
827
+ context "when a deeply embedded child has changed" do
828
+
829
+ let(:person) do
830
+ Person.create
831
+ end
832
+
833
+ let(:address) do
834
+ person.addresses.create(street: "hobrecht")
835
+ end
836
+
837
+ let!(:location) do
838
+ address.locations.create(name: "home")
839
+ end
840
+
841
+ before do
842
+ location.name = "work"
843
+ end
844
+
845
+ it "returns true" do
846
+ person.should be_changed
847
+ end
848
+ end
849
+
850
+ context "when a child is new" do
851
+
852
+ let(:person) do
853
+ Person.create
854
+ end
855
+
856
+ let!(:address) do
857
+ person.addresses.build(street: "hobrecht")
858
+ end
859
+
860
+ it "returns true" do
861
+ person.should be_changed
862
+ end
863
+ end
864
+
865
+ context "when a deeply embedded child is new" do
866
+
867
+ let(:person) do
868
+ Person.create
869
+ end
870
+
871
+ let(:address) do
872
+ person.addresses.create(street: "hobrecht")
873
+ end
874
+
875
+ let!(:location) do
876
+ address.locations.build(name: "home")
877
+ end
878
+
879
+ it "returns true" do
880
+ person.should be_changed
881
+ end
882
+ end
883
+ end
884
+
885
+ describe "#changes" do
886
+
887
+ context "when the document has changed" do
888
+
889
+ let(:person) do
890
+ Person.instantiate(title: "Grand Poobah")
891
+ end
892
+
893
+ before do
894
+ person.title = "Captain Obvious"
895
+ end
896
+
897
+ it "returns a hash of changes" do
898
+ person.changes["title"].should eq(
899
+ [ nil, "Captain Obvious" ]
900
+ )
901
+ end
902
+
903
+ it "returns a hash with indifferent access" do
904
+ person.changes["title"].should eq(
905
+ [ nil, "Captain Obvious" ]
906
+ )
907
+ end
908
+ end
909
+
910
+ context "when the document has not changed" do
911
+
912
+ let(:acolyte) do
913
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
914
+ end
915
+
916
+ it "returns an empty hash" do
917
+ acolyte.changes.should be_empty
918
+ end
919
+ end
920
+ end
921
+
922
+ describe "#setters" do
923
+
924
+ context "when the document has changed" do
925
+
926
+ let(:person) do
927
+ Person.new(aliases: [ "007" ]).tap do |p|
928
+ p.new_record = false
929
+ p.move_changes
930
+ end
931
+ end
932
+
933
+ context "when an array field has changed" do
934
+
935
+ context "when the array has values removed" do
936
+
937
+ before do
938
+ person.aliases.delete_one("007")
939
+ end
940
+
941
+ let!(:setters) do
942
+ person.setters
943
+ end
944
+
945
+ it "contains array changes in the setters" do
946
+ setters.should eq({ "aliases" => [] })
947
+ end
948
+ end
949
+
950
+ context "when the array has values added" do
951
+
952
+ before do
953
+ person.aliases << "008"
954
+ end
955
+
956
+ let!(:setters) do
957
+ person.setters
958
+ end
959
+
960
+ it "contains array changes in the setters" do
961
+ setters.should eq({ "aliases" => [ "007", "008" ] })
962
+ end
963
+ end
964
+
965
+ context "when the array has changed completely" do
966
+
967
+ before do
968
+ person.aliases << "008"
969
+ person.aliases.delete_one("007")
970
+ end
971
+
972
+ let!(:setters) do
973
+ person.setters
974
+ end
975
+
976
+ it "does not contain array changes in the setters" do
977
+ setters.should eq({ "aliases" => [ "008" ]})
978
+ end
979
+ end
980
+ end
981
+
982
+ context "when the document is a root document" do
983
+
984
+ let(:person) do
985
+ Person.instantiate(title: "Grand Poobah")
986
+ end
987
+
988
+ before do
989
+ person.title = "Captain Obvious"
990
+ end
991
+
992
+ it "returns a hash of field names and new values" do
993
+ person.setters["title"].should eq("Captain Obvious")
994
+ end
995
+ end
996
+
997
+ context "when the document is embedded" do
998
+
999
+ let(:person) do
1000
+ Person.instantiate(title: "Grand Poobah")
1001
+ end
1002
+
1003
+ let(:address) do
1004
+ Address.instantiate(street: "Oxford St")
1005
+ end
1006
+
1007
+ before do
1008
+ person.addresses << address
1009
+ person.instance_variable_set(:@new_record, false)
1010
+ address.instance_variable_set(:@new_record, false)
1011
+ address.street = "Bond St"
1012
+ end
1013
+
1014
+ it "returns a hash of field names and new values" do
1015
+ address.setters.should eq(
1016
+ { "addresses.0.street" => "Bond St" }
1017
+ )
1018
+ end
1019
+
1020
+ context "when the document is embedded multiple levels" do
1021
+
1022
+ let(:location) do
1023
+ Location.new(name: "Home")
1024
+ end
1025
+
1026
+ before do
1027
+ location.instance_variable_set(:@new_record, false)
1028
+ address.locations << location
1029
+ location.name = "Work"
1030
+ end
1031
+
1032
+ it "returns the proper hash with locations" do
1033
+ location.setters.should eq(
1034
+ { "addresses.0.locations.0.name" => "Work" }
1035
+ )
1036
+ end
1037
+ end
1038
+ end
1039
+ end
1040
+
1041
+ context "when the document has not changed" do
1042
+
1043
+ let(:acolyte) do
1044
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
1045
+ end
1046
+
1047
+ it "returns an empty hash" do
1048
+ acolyte.setters.should be_empty
1049
+ end
1050
+ end
1051
+ end
1052
+
1053
+ describe "#previous_changes" do
1054
+
1055
+ let(:person) do
1056
+ Person.new(title: "Grand Poobah")
1057
+ end
1058
+
1059
+ before do
1060
+ person.title = "Captain Obvious"
1061
+ end
1062
+
1063
+ context "when the document has been saved" do
1064
+
1065
+ before do
1066
+ person.save!
1067
+ end
1068
+
1069
+ it "returns the changes before the save" do
1070
+ person.previous_changes["title"].should eq(
1071
+ [ nil, "Captain Obvious" ]
1072
+ )
1073
+ end
1074
+ end
1075
+
1076
+ context "when the document has not been saved" do
1077
+
1078
+ it "returns an empty hash" do
1079
+ person.previous_changes.should be_empty
1080
+ end
1081
+ end
1082
+ end
1083
+
1084
+ describe "#move_changes" do
1085
+
1086
+ let(:person) do
1087
+ Person.new(title: "Sir")
1088
+ end
1089
+
1090
+ before do
1091
+ person.atomic_pulls["addresses"] = Address.new
1092
+ person.atomic_unsets << Address.new
1093
+ person.delayed_atomic_sets["addresses"] = Address.new
1094
+ person.move_changes
1095
+ end
1096
+
1097
+ it "clears the atomic pulls" do
1098
+ person.atomic_pulls.should be_empty
1099
+ end
1100
+
1101
+ it "clears the atomic unsets" do
1102
+ person.atomic_unsets.should be_empty
1103
+ end
1104
+
1105
+ it "clears the delayed atomic sets" do
1106
+ person.delayed_atomic_sets.should be_empty
1107
+ end
1108
+
1109
+ it "clears the changed attributes" do
1110
+ person.changed_attributes.should be_empty
1111
+ end
1112
+ end
1113
+
1114
+ describe "#reset_attribute!" do
1115
+
1116
+ context "when the attribute has changed" do
1117
+
1118
+ let(:person) do
1119
+ Person.instantiate(title: "Grand Poobah")
1120
+ end
1121
+
1122
+ before do
1123
+ person.title = "Captain Obvious"
1124
+ person.send(:reset_attribute!, "title")
1125
+ end
1126
+
1127
+ it "resets the value to the original" do
1128
+ person.title.should be_nil
1129
+ end
1130
+
1131
+ it "allows access via reset_(attribute)!" do
1132
+ person.title.should be_nil
1133
+ end
1134
+
1135
+ it "removes the field from the changes" do
1136
+ person.changed.should_not include("title")
1137
+ end
1138
+
1139
+ context "when the field is aliased" do
1140
+
1141
+ let(:person) do
1142
+ Person.instantiate(test: "Aliased 1")
1143
+ end
1144
+
1145
+ before do
1146
+ person.test = "Aliased 2"
1147
+ person.send(:reset_attribute!, "test")
1148
+ end
1149
+
1150
+ it "resets the value to the original" do
1151
+ person.test.should be_nil
1152
+ end
1153
+
1154
+ it "removes the field from the changes" do
1155
+ person.changed.should_not include("test")
1156
+ end
1157
+ end
1158
+ end
1159
+
1160
+ context "when the attribute has not changed" do
1161
+
1162
+ let(:person) do
1163
+ Person.instantiate(title: "Grand Poobah")
1164
+ end
1165
+
1166
+ before do
1167
+ person.send(:reset_attribute!, "title")
1168
+ end
1169
+
1170
+ it "does nothing" do
1171
+ person.title.should be_nil
1172
+ end
1173
+ end
1174
+ end
1175
+
1176
+ context "when fields have been defined pre-dirty inclusion" do
1177
+
1178
+ let(:document) do
1179
+ Dokument.new
1180
+ end
1181
+
1182
+ it "defines a _change method" do
1183
+ document.updated_at_change.should be_nil
1184
+ end
1185
+
1186
+ it "defines a _changed? method" do
1187
+ document.updated_at_changed?.should be_false
1188
+ end
1189
+
1190
+ it "defines a _changes method" do
1191
+ document.updated_at_was.should be_nil
1192
+ end
1193
+ end
1194
+
1195
+ context "when only embedded documents change" do
1196
+
1197
+ let!(:person) do
1198
+ Person.create
1199
+ end
1200
+
1201
+ context "when the child is an embeds one" do
1202
+
1203
+ context "when the child is new" do
1204
+
1205
+ let!(:name) do
1206
+ person.build_name(first_name: "Gordon", last_name: "Ramsay")
1207
+ end
1208
+
1209
+ it "flags the parent as changed" do
1210
+ person.should be_changed
1211
+ end
1212
+ end
1213
+
1214
+ context "when the child is modified" do
1215
+
1216
+ let!(:name) do
1217
+ person.create_name(first_name: "Gordon", last_name: "Ramsay")
1218
+ end
1219
+
1220
+ before do
1221
+ name.first_name = "G"
1222
+ end
1223
+
1224
+ it "flags the parent as changed" do
1225
+ person.should be_changed
1226
+ end
1227
+ end
1228
+
1229
+ context "when the child is not modified" do
1230
+
1231
+ let!(:name) do
1232
+ person.create_name(first_name: "Gordon", last_name: "Ramsay")
1233
+ end
1234
+
1235
+ it "does not flag the parent as changed" do
1236
+ person.should_not be_changed
1237
+ end
1238
+ end
1239
+ end
1240
+
1241
+ context "when the child is an embeds many" do
1242
+
1243
+ context "when a child is new" do
1244
+
1245
+ let!(:address) do
1246
+ person.addresses.build(street: "jakobstr.")
1247
+ end
1248
+
1249
+ it "flags the parent as changed" do
1250
+ person.should be_changed
1251
+ end
1252
+ end
1253
+
1254
+ context "when a child is modified" do
1255
+
1256
+ let!(:address) do
1257
+ person.addresses.create(street: "jakobstr.")
1258
+ end
1259
+
1260
+ before do
1261
+ address.city = "Berlin"
1262
+ end
1263
+
1264
+ it "flags the parent as changed" do
1265
+ person.should be_changed
1266
+ end
1267
+ end
1268
+
1269
+ context "when no child is modified" do
1270
+
1271
+ let!(:address) do
1272
+ person.addresses.create(street: "skalitzerstr.")
1273
+ end
1274
+
1275
+ it "does not flag the parent as changed" do
1276
+ person.should_not be_changed
1277
+ end
1278
+ end
1279
+ end
1280
+ end
1281
+
1282
+ context "when changing a hash of hashes" do
1283
+
1284
+ let!(:person) do
1285
+ Person.create(map: { "test" => {}})
1286
+ end
1287
+
1288
+ before do
1289
+ person.map["test"]["value"] = 10
1290
+ end
1291
+
1292
+ it "records the changes" do
1293
+ person.changes.should eq(
1294
+ { "map" => [{ "test" => {}}, { "test" => { "value" => 10 }}]}
1295
+ )
1296
+ end
1297
+ end
1298
+
1299
+ context "when modifying a many to many key" do
1300
+
1301
+ let!(:person) do
1302
+ Person.create
1303
+ end
1304
+
1305
+ let!(:preference) do
1306
+ Preference.create(name: "dirty")
1307
+ end
1308
+
1309
+ before do
1310
+ person.update_attributes(preference_ids: [ preference.id ])
1311
+ end
1312
+
1313
+ it "records the foreign key dirty changes" do
1314
+ person.previous_changes["preference_ids"].should eq(
1315
+ [nil, [ preference.id ]]
1316
+ )
1317
+ end
1318
+ end
1319
+
1320
+ context "when accessing an array field" do
1321
+
1322
+ let!(:person) do
1323
+ Person.create
1324
+ end
1325
+
1326
+ let(:from_db) do
1327
+ Person.find(person.id)
1328
+ end
1329
+
1330
+ context "when the field is not changed" do
1331
+
1332
+ before do
1333
+ from_db.preference_ids
1334
+ end
1335
+
1336
+ it "flags the change" do
1337
+ from_db.changes["preference_ids"].should eq([ nil, []])
1338
+ end
1339
+
1340
+ it "does not include the changes in the setters" do
1341
+ from_db.setters.should be_empty
1342
+ end
1343
+ end
1344
+ end
1345
+
1346
+ context "when reloading an unchanged document" do
1347
+
1348
+ let!(:person) do
1349
+ Person.create
1350
+ end
1351
+
1352
+ let(:from_db) do
1353
+ Person.find(person.id)
1354
+ end
1355
+
1356
+ before do
1357
+ from_db.reload
1358
+ end
1359
+
1360
+ it "clears the changed attributes" do
1361
+ from_db.changed_attributes.should be_empty
1362
+ end
1363
+ end
1364
+
1365
+ context "when fields are getting changed" do
1366
+
1367
+ let(:person) do
1368
+ Person.create(
1369
+ title: "MC",
1370
+ some_dynamic_field: 'blah'
1371
+ )
1372
+ end
1373
+
1374
+ before do
1375
+ person.title = "DJ"
1376
+ person.write_attribute(:ssn, "222-22-2222")
1377
+ person.some_dynamic_field = 'bloop'
1378
+ end
1379
+
1380
+ it "marks the document as changed" do
1381
+ person.should be_changed
1382
+ end
1383
+
1384
+ it "marks field changes" do
1385
+ person.changes.should eq({
1386
+ "title" => [ "MC", "DJ" ],
1387
+ "ssn" => [ nil, "222-22-2222" ],
1388
+ "some_dynamic_field" => [ "blah", "bloop" ]
1389
+ })
1390
+ end
1391
+
1392
+ it "marks changed fields" do
1393
+ person.changed.should =~ [ "title", "ssn", "some_dynamic_field" ]
1394
+ end
1395
+
1396
+ it "marks the field as changed" do
1397
+ person.title_changed?.should be_true
1398
+ end
1399
+
1400
+ it "stores previous field values" do
1401
+ person.title_was.should eq("MC")
1402
+ end
1403
+
1404
+ it "marks field changes" do
1405
+ person.title_change.should eq([ "MC", "DJ" ])
1406
+ end
1407
+
1408
+ it "allows reset of field changes" do
1409
+ person.reset_title!
1410
+ person.title.should eq("MC")
1411
+ person.changed.should =~ [ "ssn", "some_dynamic_field" ]
1412
+ end
1413
+
1414
+ context "after a save" do
1415
+
1416
+ before do
1417
+ person.save!
1418
+ end
1419
+
1420
+ it "clears changes" do
1421
+ person.should_not be_changed
1422
+ end
1423
+
1424
+ it "stores previous changes" do
1425
+ person.previous_changes["title"].should eq([ "MC", "DJ" ])
1426
+ person.previous_changes["ssn"].should eq([ nil, "222-22-2222" ])
1427
+ end
1428
+ end
1429
+
1430
+ context "when the previous value is nil" do
1431
+
1432
+ before do
1433
+ person.score = 100
1434
+ person.reset_score!
1435
+ end
1436
+
1437
+ it "removes the attribute from the document" do
1438
+ person.score.should be_nil
1439
+ end
1440
+ end
1441
+ end
1442
+
1443
+ context "when accessing dirty attributes in callbacks" do
1444
+
1445
+ context "when the document is persisted" do
1446
+
1447
+ let!(:acolyte) do
1448
+ Acolyte.create(name: "callback-test")
1449
+ end
1450
+
1451
+ before do
1452
+ Acolyte.set_callback(:save, :after, if: :callback_test?) do |doc|
1453
+ doc[:changed_in_callback] = doc.changes.dup
1454
+ end
1455
+ end
1456
+
1457
+ after do
1458
+ Acolyte._save_callbacks.reject! do |callback|
1459
+ callback.kind == :after
1460
+ end
1461
+ end
1462
+
1463
+ it "retains the changes until after all callbacks" do
1464
+ acolyte.update_attribute(:status, "testing")
1465
+ acolyte.changed_in_callback.should eq({ "status" => [ nil, "testing" ] })
1466
+ end
1467
+ end
1468
+
1469
+ context "when the document is new" do
1470
+
1471
+ let!(:acolyte) do
1472
+ Acolyte.new(name: "callback-test")
1473
+ end
1474
+
1475
+ before do
1476
+ Acolyte.set_callback(:save, :after, if: :callback_test?) do |doc|
1477
+ doc[:changed_in_callback] = doc.changes.dup
1478
+ end
1479
+ end
1480
+
1481
+ after do
1482
+ Acolyte._save_callbacks.reject! do |callback|
1483
+ callback.kind == :after
1484
+ end
1485
+ end
1486
+
1487
+ it "retains the changes until after all callbacks" do
1488
+ acolyte.save
1489
+ acolyte.changed_in_callback["name"].should eq([ nil, "callback-test" ])
1490
+ end
1491
+ end
1492
+ end
1493
+
1494
+ context "when associations are getting changed" do
1495
+
1496
+ let(:person) do
1497
+ Person.create(addresses: [ Address.new ])
1498
+ end
1499
+
1500
+ before do
1501
+ person.addresses = [ Address.new ]
1502
+ end
1503
+
1504
+ it "does not set the association to nil when hitting the database" do
1505
+ person.setters.should_not eq({ "addresses" => nil })
1506
+ end
1507
+ end
1508
+ end