mongoid_rails4 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (659) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3213 -0
  3. data/LICENSE +20 -0
  4. data/README.md +62 -0
  5. data/Rakefile +35 -0
  6. data/lib/config/locales/en.yml +448 -0
  7. data/lib/mongoid.rb +104 -0
  8. data/lib/mongoid/atomic.rb +384 -0
  9. data/lib/mongoid/atomic/modifiers.rb +317 -0
  10. data/lib/mongoid/atomic/paths.rb +3 -0
  11. data/lib/mongoid/atomic/paths/embedded.rb +28 -0
  12. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  13. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  14. data/lib/mongoid/atomic/paths/root.rb +39 -0
  15. data/lib/mongoid/attributes.rb +284 -0
  16. data/lib/mongoid/attributes/dynamic.rb +154 -0
  17. data/lib/mongoid/attributes/nested.rb +82 -0
  18. data/lib/mongoid/attributes/processing.rb +147 -0
  19. data/lib/mongoid/attributes/readonly.rb +56 -0
  20. data/lib/mongoid/changeable.rb +379 -0
  21. data/lib/mongoid/composable.rb +104 -0
  22. data/lib/mongoid/config.rb +263 -0
  23. data/lib/mongoid/config/environment.rb +44 -0
  24. data/lib/mongoid/config/options.rb +74 -0
  25. data/lib/mongoid/config/validators.rb +3 -0
  26. data/lib/mongoid/config/validators/option.rb +25 -0
  27. data/lib/mongoid/config/validators/session.rb +140 -0
  28. data/lib/mongoid/contextual.rb +54 -0
  29. data/lib/mongoid/contextual/aggregable/memory.rb +109 -0
  30. data/lib/mongoid/contextual/aggregable/mongo.rb +147 -0
  31. data/lib/mongoid/contextual/atomic.rb +180 -0
  32. data/lib/mongoid/contextual/command.rb +61 -0
  33. data/lib/mongoid/contextual/eager.rb +158 -0
  34. data/lib/mongoid/contextual/find_and_modify.rb +69 -0
  35. data/lib/mongoid/contextual/geo_near.rb +238 -0
  36. data/lib/mongoid/contextual/map_reduce.rb +324 -0
  37. data/lib/mongoid/contextual/memory.rb +440 -0
  38. data/lib/mongoid/contextual/mongo.rb +676 -0
  39. data/lib/mongoid/contextual/queryable.rb +25 -0
  40. data/lib/mongoid/contextual/text_search.rb +180 -0
  41. data/lib/mongoid/copyable.rb +67 -0
  42. data/lib/mongoid/criteria.rb +562 -0
  43. data/lib/mongoid/criteria/findable.rb +179 -0
  44. data/lib/mongoid/criteria/inspectable.rb +25 -0
  45. data/lib/mongoid/criteria/marshalable.rb +50 -0
  46. data/lib/mongoid/criteria/modifiable.rb +189 -0
  47. data/lib/mongoid/criteria/scopable.rb +158 -0
  48. data/lib/mongoid/document.rb +361 -0
  49. data/lib/mongoid/equality.rb +66 -0
  50. data/lib/mongoid/errors.rb +40 -0
  51. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  52. data/lib/mongoid/errors/callback.rb +25 -0
  53. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  54. data/lib/mongoid/errors/document_not_found.rb +111 -0
  55. data/lib/mongoid/errors/eager_load.rb +22 -0
  56. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  57. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  58. data/lib/mongoid/errors/invalid_field.rb +64 -0
  59. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  60. data/lib/mongoid/errors/invalid_find.rb +19 -0
  61. data/lib/mongoid/errors/invalid_includes.rb +32 -0
  62. data/lib/mongoid/errors/invalid_index.rb +28 -0
  63. data/lib/mongoid/errors/invalid_options.rb +28 -0
  64. data/lib/mongoid/errors/invalid_path.rb +21 -0
  65. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  66. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  67. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  68. data/lib/mongoid/errors/invalid_time.rb +22 -0
  69. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  70. data/lib/mongoid/errors/mixed_relations.rb +32 -0
  71. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  72. data/lib/mongoid/errors/mongoid_error.rb +92 -0
  73. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  74. data/lib/mongoid/errors/no_default_session.rb +23 -0
  75. data/lib/mongoid/errors/no_environment.rb +19 -0
  76. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  77. data/lib/mongoid/errors/no_metadata.rb +21 -0
  78. data/lib/mongoid/errors/no_parent.rb +24 -0
  79. data/lib/mongoid/errors/no_session_config.rb +22 -0
  80. data/lib/mongoid/errors/no_session_database.rb +27 -0
  81. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  82. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  83. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  84. data/lib/mongoid/errors/scope_overwrite.rb +21 -0
  85. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  86. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  87. data/lib/mongoid/errors/unsaved_document.rb +19 -0
  88. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  89. data/lib/mongoid/errors/validations.rb +29 -0
  90. data/lib/mongoid/evolvable.rb +19 -0
  91. data/lib/mongoid/extensions.rb +35 -0
  92. data/lib/mongoid/extensions/array.rb +180 -0
  93. data/lib/mongoid/extensions/big_decimal.rb +69 -0
  94. data/lib/mongoid/extensions/boolean.rb +21 -0
  95. data/lib/mongoid/extensions/date.rb +77 -0
  96. data/lib/mongoid/extensions/date_time.rb +73 -0
  97. data/lib/mongoid/extensions/false_class.rb +38 -0
  98. data/lib/mongoid/extensions/float.rb +56 -0
  99. data/lib/mongoid/extensions/hash.rb +209 -0
  100. data/lib/mongoid/extensions/integer.rb +67 -0
  101. data/lib/mongoid/extensions/module.rb +28 -0
  102. data/lib/mongoid/extensions/nil_class.rb +33 -0
  103. data/lib/mongoid/extensions/object.rb +274 -0
  104. data/lib/mongoid/extensions/object_id.rb +54 -0
  105. data/lib/mongoid/extensions/range.rb +79 -0
  106. data/lib/mongoid/extensions/regexp.rb +27 -0
  107. data/lib/mongoid/extensions/set.rb +55 -0
  108. data/lib/mongoid/extensions/string.rb +199 -0
  109. data/lib/mongoid/extensions/symbol.rb +54 -0
  110. data/lib/mongoid/extensions/time.rb +88 -0
  111. data/lib/mongoid/extensions/time_with_zone.rb +56 -0
  112. data/lib/mongoid/extensions/true_class.rb +38 -0
  113. data/lib/mongoid/factory.rb +46 -0
  114. data/lib/mongoid/fields.rb +542 -0
  115. data/lib/mongoid/fields/foreign_key.rb +174 -0
  116. data/lib/mongoid/fields/localized.rb +73 -0
  117. data/lib/mongoid/fields/standard.rb +273 -0
  118. data/lib/mongoid/fields/validators.rb +2 -0
  119. data/lib/mongoid/fields/validators/macro.rb +92 -0
  120. data/lib/mongoid/findable.rb +133 -0
  121. data/lib/mongoid/identity_map.rb +163 -0
  122. data/lib/mongoid/indexable.rb +147 -0
  123. data/lib/mongoid/indexable/specification.rb +115 -0
  124. data/lib/mongoid/indexable/validators/options.rb +103 -0
  125. data/lib/mongoid/inspectable.rb +59 -0
  126. data/lib/mongoid/interceptable.rb +265 -0
  127. data/lib/mongoid/loggable.rb +69 -0
  128. data/lib/mongoid/matchable.rb +152 -0
  129. data/lib/mongoid/matchable/all.rb +27 -0
  130. data/lib/mongoid/matchable/and.rb +30 -0
  131. data/lib/mongoid/matchable/default.rb +72 -0
  132. data/lib/mongoid/matchable/exists.rb +23 -0
  133. data/lib/mongoid/matchable/gt.rb +21 -0
  134. data/lib/mongoid/matchable/gte.rb +21 -0
  135. data/lib/mongoid/matchable/in.rb +24 -0
  136. data/lib/mongoid/matchable/lt.rb +21 -0
  137. data/lib/mongoid/matchable/lte.rb +21 -0
  138. data/lib/mongoid/matchable/ne.rb +21 -0
  139. data/lib/mongoid/matchable/nin.rb +21 -0
  140. data/lib/mongoid/matchable/or.rb +33 -0
  141. data/lib/mongoid/matchable/size.rb +21 -0
  142. data/lib/mongoid/persistable.rb +207 -0
  143. data/lib/mongoid/persistable/creatable.rb +189 -0
  144. data/lib/mongoid/persistable/deletable.rb +149 -0
  145. data/lib/mongoid/persistable/destroyable.rb +55 -0
  146. data/lib/mongoid/persistable/incrementable.rb +36 -0
  147. data/lib/mongoid/persistable/logical.rb +38 -0
  148. data/lib/mongoid/persistable/poppable.rb +39 -0
  149. data/lib/mongoid/persistable/pullable.rb +55 -0
  150. data/lib/mongoid/persistable/pushable.rb +62 -0
  151. data/lib/mongoid/persistable/renamable.rb +35 -0
  152. data/lib/mongoid/persistable/savable.rb +52 -0
  153. data/lib/mongoid/persistable/settable.rb +33 -0
  154. data/lib/mongoid/persistable/unsettable.rb +36 -0
  155. data/lib/mongoid/persistable/updatable.rb +151 -0
  156. data/lib/mongoid/persistable/upsertable.rb +55 -0
  157. data/lib/mongoid/positional.rb +71 -0
  158. data/lib/mongoid/railtie.rb +156 -0
  159. data/lib/mongoid/railties/database.rake +97 -0
  160. data/lib/mongoid/railties/document.rb +12 -0
  161. data/lib/mongoid/relations.rb +162 -0
  162. data/lib/mongoid/relations/accessors.rb +299 -0
  163. data/lib/mongoid/relations/auto_save.rb +106 -0
  164. data/lib/mongoid/relations/binding.rb +218 -0
  165. data/lib/mongoid/relations/bindings.rb +9 -0
  166. data/lib/mongoid/relations/bindings/embedded/in.rb +63 -0
  167. data/lib/mongoid/relations/bindings/embedded/many.rb +50 -0
  168. data/lib/mongoid/relations/bindings/embedded/one.rb +55 -0
  169. data/lib/mongoid/relations/bindings/referenced/in.rb +65 -0
  170. data/lib/mongoid/relations/bindings/referenced/many.rb +42 -0
  171. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +67 -0
  172. data/lib/mongoid/relations/bindings/referenced/one.rb +44 -0
  173. data/lib/mongoid/relations/builder.rb +57 -0
  174. data/lib/mongoid/relations/builders.rb +104 -0
  175. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  176. data/lib/mongoid/relations/builders/embedded/many.rb +36 -0
  177. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  178. data/lib/mongoid/relations/builders/nested_attributes/many.rb +174 -0
  179. data/lib/mongoid/relations/builders/nested_attributes/one.rb +126 -0
  180. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  181. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  182. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +40 -0
  183. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  184. data/lib/mongoid/relations/cascading.rb +56 -0
  185. data/lib/mongoid/relations/cascading/delete.rb +44 -0
  186. data/lib/mongoid/relations/cascading/destroy.rb +43 -0
  187. data/lib/mongoid/relations/cascading/nullify.rb +35 -0
  188. data/lib/mongoid/relations/cascading/restrict.rb +39 -0
  189. data/lib/mongoid/relations/constraint.rb +49 -0
  190. data/lib/mongoid/relations/conversions.rb +34 -0
  191. data/lib/mongoid/relations/counter_cache.rb +105 -0
  192. data/lib/mongoid/relations/cyclic.rb +107 -0
  193. data/lib/mongoid/relations/embedded/batchable.rb +355 -0
  194. data/lib/mongoid/relations/embedded/in.rb +231 -0
  195. data/lib/mongoid/relations/embedded/many.rb +639 -0
  196. data/lib/mongoid/relations/embedded/one.rb +223 -0
  197. data/lib/mongoid/relations/macros.rb +356 -0
  198. data/lib/mongoid/relations/many.rb +208 -0
  199. data/lib/mongoid/relations/marshalable.rb +32 -0
  200. data/lib/mongoid/relations/metadata.rb +1174 -0
  201. data/lib/mongoid/relations/nested_builder.rb +74 -0
  202. data/lib/mongoid/relations/one.rb +48 -0
  203. data/lib/mongoid/relations/options.rb +48 -0
  204. data/lib/mongoid/relations/polymorphic.rb +39 -0
  205. data/lib/mongoid/relations/proxy.rb +270 -0
  206. data/lib/mongoid/relations/referenced/in.rb +297 -0
  207. data/lib/mongoid/relations/referenced/many.rb +787 -0
  208. data/lib/mongoid/relations/referenced/many_to_many.rb +486 -0
  209. data/lib/mongoid/relations/referenced/one.rb +290 -0
  210. data/lib/mongoid/relations/reflections.rb +62 -0
  211. data/lib/mongoid/relations/synchronization.rb +169 -0
  212. data/lib/mongoid/relations/targets.rb +2 -0
  213. data/lib/mongoid/relations/targets/enumerable.rb +473 -0
  214. data/lib/mongoid/relations/touchable.rb +94 -0
  215. data/lib/mongoid/reloadable.rb +95 -0
  216. data/lib/mongoid/scopable.rb +379 -0
  217. data/lib/mongoid/selectable.rb +59 -0
  218. data/lib/mongoid/serializable.rb +170 -0
  219. data/lib/mongoid/sessions.rb +330 -0
  220. data/lib/mongoid/sessions/factory.rb +129 -0
  221. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  222. data/lib/mongoid/sessions/options.rb +141 -0
  223. data/lib/mongoid/sessions/validators.rb +2 -0
  224. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  225. data/lib/mongoid/shardable.rb +65 -0
  226. data/lib/mongoid/state.rb +97 -0
  227. data/lib/mongoid/threaded.rb +383 -0
  228. data/lib/mongoid/threaded/lifecycle.rb +164 -0
  229. data/lib/mongoid/timestamps.rb +15 -0
  230. data/lib/mongoid/timestamps/created.rb +30 -0
  231. data/lib/mongoid/timestamps/created/short.rb +19 -0
  232. data/lib/mongoid/timestamps/short.rb +10 -0
  233. data/lib/mongoid/timestamps/updated.rb +39 -0
  234. data/lib/mongoid/timestamps/updated/short.rb +19 -0
  235. data/lib/mongoid/traversable.rb +192 -0
  236. data/lib/mongoid/unit_of_work.rb +61 -0
  237. data/lib/mongoid/validatable.rb +180 -0
  238. data/lib/mongoid/validatable/associated.rb +48 -0
  239. data/lib/mongoid/validatable/format.rb +20 -0
  240. data/lib/mongoid/validatable/length.rb +20 -0
  241. data/lib/mongoid/validatable/localizable.rb +30 -0
  242. data/lib/mongoid/validatable/macros.rb +94 -0
  243. data/lib/mongoid/validatable/presence.rb +86 -0
  244. data/lib/mongoid/validatable/queryable.rb +30 -0
  245. data/lib/mongoid/validatable/uniqueness.rb +330 -0
  246. data/lib/mongoid/version.rb +4 -0
  247. data/lib/rack/mongoid.rb +2 -0
  248. data/lib/rack/mongoid/middleware/identity_map.rb +39 -0
  249. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  250. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +76 -0
  251. data/lib/rails/generators/mongoid/model/model_generator.rb +25 -0
  252. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  253. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  254. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  255. data/lib/rails/generators/mongoid_generator.rb +65 -0
  256. data/lib/rails/mongoid.rb +180 -0
  257. data/lib/support/ruby_version.rb +26 -0
  258. data/spec/app/models/account.rb +28 -0
  259. data/spec/app/models/acolyte.rb +17 -0
  260. data/spec/app/models/actor.rb +18 -0
  261. data/spec/app/models/actress.rb +2 -0
  262. data/spec/app/models/address.rb +77 -0
  263. data/spec/app/models/address_component.rb +5 -0
  264. data/spec/app/models/address_number.rb +6 -0
  265. data/spec/app/models/agency.rb +5 -0
  266. data/spec/app/models/agent.rb +12 -0
  267. data/spec/app/models/album.rb +14 -0
  268. data/spec/app/models/alert.rb +5 -0
  269. data/spec/app/models/animal.rb +25 -0
  270. data/spec/app/models/answer.rb +4 -0
  271. data/spec/app/models/appointment.rb +7 -0
  272. data/spec/app/models/article.rb +10 -0
  273. data/spec/app/models/artist.rb +66 -0
  274. data/spec/app/models/artwork.rb +4 -0
  275. data/spec/app/models/audio.rb +5 -0
  276. data/spec/app/models/augmentation.rb +11 -0
  277. data/spec/app/models/author.rb +4 -0
  278. data/spec/app/models/band.rb +26 -0
  279. data/spec/app/models/bar.rb +10 -0
  280. data/spec/app/models/basic.rb +6 -0
  281. data/spec/app/models/bed.rb +1 -0
  282. data/spec/app/models/big_palette.rb +2 -0
  283. data/spec/app/models/birthday.rb +13 -0
  284. data/spec/app/models/book.rb +13 -0
  285. data/spec/app/models/breed.rb +4 -0
  286. data/spec/app/models/browser.rb +6 -0
  287. data/spec/app/models/building.rb +5 -0
  288. data/spec/app/models/building_address.rb +5 -0
  289. data/spec/app/models/bus.rb +7 -0
  290. data/spec/app/models/business.rb +5 -0
  291. data/spec/app/models/callback_recorder.rb +25 -0
  292. data/spec/app/models/callback_test.rb +9 -0
  293. data/spec/app/models/canvas.rb +25 -0
  294. data/spec/app/models/car.rb +1 -0
  295. data/spec/app/models/cat.rb +8 -0
  296. data/spec/app/models/category.rb +8 -0
  297. data/spec/app/models/child.rb +4 -0
  298. data/spec/app/models/child_doc.rb +22 -0
  299. data/spec/app/models/church.rb +4 -0
  300. data/spec/app/models/circle.rb +3 -0
  301. data/spec/app/models/circuit.rb +4 -0
  302. data/spec/app/models/circus.rb +7 -0
  303. data/spec/app/models/code.rb +5 -0
  304. data/spec/app/models/comment.rb +16 -0
  305. data/spec/app/models/contractor.rb +5 -0
  306. data/spec/app/models/cookie.rb +6 -0
  307. data/spec/app/models/country_code.rb +8 -0
  308. data/spec/app/models/definition.rb +7 -0
  309. data/spec/app/models/description.rb +11 -0
  310. data/spec/app/models/dictionary.rb +10 -0
  311. data/spec/app/models/division.rb +10 -0
  312. data/spec/app/models/doctor.rb +12 -0
  313. data/spec/app/models/dog.rb +7 -0
  314. data/spec/app/models/dokument.rb +5 -0
  315. data/spec/app/models/dragon.rb +4 -0
  316. data/spec/app/models/driver.rb +7 -0
  317. data/spec/app/models/drug.rb +6 -0
  318. data/spec/app/models/dungeon.rb +4 -0
  319. data/spec/app/models/email.rb +6 -0
  320. data/spec/app/models/employer.rb +5 -0
  321. data/spec/app/models/entry.rb +6 -0
  322. data/spec/app/models/eraser.rb +1 -0
  323. data/spec/app/models/event.rb +22 -0
  324. data/spec/app/models/exhibition.rb +4 -0
  325. data/spec/app/models/exhibitor.rb +5 -0
  326. data/spec/app/models/eye.rb +9 -0
  327. data/spec/app/models/eye_bowl.rb +9 -0
  328. data/spec/app/models/face.rb +8 -0
  329. data/spec/app/models/favorite.rb +6 -0
  330. data/spec/app/models/filesystem.rb +5 -0
  331. data/spec/app/models/fire_hydrant.rb +6 -0
  332. data/spec/app/models/firefox.rb +4 -0
  333. data/spec/app/models/fish.rb +7 -0
  334. data/spec/app/models/folder.rb +7 -0
  335. data/spec/app/models/folder_item.rb +9 -0
  336. data/spec/app/models/fruits.rb +28 -0
  337. data/spec/app/models/game.rb +19 -0
  338. data/spec/app/models/ghost.rb +7 -0
  339. data/spec/app/models/home.rb +4 -0
  340. data/spec/app/models/house.rb +6 -0
  341. data/spec/app/models/html_writer.rb +3 -0
  342. data/spec/app/models/image.rb +22 -0
  343. data/spec/app/models/implant.rb +16 -0
  344. data/spec/app/models/item.rb +8 -0
  345. data/spec/app/models/jar.rb +7 -0
  346. data/spec/app/models/label.rb +40 -0
  347. data/spec/app/models/language.rb +5 -0
  348. data/spec/app/models/lat_lng.rb +15 -0
  349. data/spec/app/models/league.rb +11 -0
  350. data/spec/app/models/learner.rb +2 -0
  351. data/spec/app/models/line_item.rb +6 -0
  352. data/spec/app/models/location.rb +8 -0
  353. data/spec/app/models/login.rb +8 -0
  354. data/spec/app/models/manufacturer.rb +7 -0
  355. data/spec/app/models/meat.rb +4 -0
  356. data/spec/app/models/membership.rb +4 -0
  357. data/spec/app/models/mixed_drink.rb +4 -0
  358. data/spec/app/models/movie.rb +13 -0
  359. data/spec/app/models/my_hash.rb +2 -0
  360. data/spec/app/models/name.rb +23 -0
  361. data/spec/app/models/node.rb +5 -0
  362. data/spec/app/models/note.rb +12 -0
  363. data/spec/app/models/ordered_post.rb +6 -0
  364. data/spec/app/models/ordered_preference.rb +6 -0
  365. data/spec/app/models/oscar.rb +15 -0
  366. data/spec/app/models/override.rb +16 -0
  367. data/spec/app/models/ownable.rb +6 -0
  368. data/spec/app/models/owner.rb +6 -0
  369. data/spec/app/models/pack.rb +3 -0
  370. data/spec/app/models/page.rb +5 -0
  371. data/spec/app/models/page_question.rb +4 -0
  372. data/spec/app/models/palette.rb +7 -0
  373. data/spec/app/models/parent.rb +5 -0
  374. data/spec/app/models/parent_doc.rb +6 -0
  375. data/spec/app/models/passport.rb +5 -0
  376. data/spec/app/models/patient.rb +9 -0
  377. data/spec/app/models/pdf_writer.rb +3 -0
  378. data/spec/app/models/pencil.rb +1 -0
  379. data/spec/app/models/person.rb +205 -0
  380. data/spec/app/models/pet.rb +23 -0
  381. data/spec/app/models/pet_owner.rb +6 -0
  382. data/spec/app/models/phone.rb +11 -0
  383. data/spec/app/models/pizza.rb +7 -0
  384. data/spec/app/models/player.rb +35 -0
  385. data/spec/app/models/post.rb +44 -0
  386. data/spec/app/models/powerup.rb +11 -0
  387. data/spec/app/models/preference.rb +9 -0
  388. data/spec/app/models/princess.rb +8 -0
  389. data/spec/app/models/product.rb +15 -0
  390. data/spec/app/models/profile.rb +5 -0
  391. data/spec/app/models/pronunciation.rb +5 -0
  392. data/spec/app/models/purchase.rb +4 -0
  393. data/spec/app/models/question.rb +8 -0
  394. data/spec/app/models/quiz.rb +7 -0
  395. data/spec/app/models/rating.rb +8 -0
  396. data/spec/app/models/record.rb +46 -0
  397. data/spec/app/models/registry.rb +4 -0
  398. data/spec/app/models/role.rb +7 -0
  399. data/spec/app/models/root_category.rb +4 -0
  400. data/spec/app/models/sandwich.rb +4 -0
  401. data/spec/app/models/scheduler.rb +7 -0
  402. data/spec/app/models/seo.rb +7 -0
  403. data/spec/app/models/series.rb +4 -0
  404. data/spec/app/models/server.rb +13 -0
  405. data/spec/app/models/service.rb +22 -0
  406. data/spec/app/models/shape.rb +12 -0
  407. data/spec/app/models/shelf.rb +5 -0
  408. data/spec/app/models/shipping_container.rb +5 -0
  409. data/spec/app/models/shipping_pack.rb +3 -0
  410. data/spec/app/models/shop.rb +6 -0
  411. data/spec/app/models/short_agent.rb +4 -0
  412. data/spec/app/models/short_quiz.rb +5 -0
  413. data/spec/app/models/slave.rb +6 -0
  414. data/spec/app/models/song.rb +8 -0
  415. data/spec/app/models/sound.rb +5 -0
  416. data/spec/app/models/square.rb +4 -0
  417. data/spec/app/models/strategy.rb +3 -0
  418. data/spec/app/models/sub_item.rb +3 -0
  419. data/spec/app/models/subscription.rb +4 -0
  420. data/spec/app/models/survey.rb +5 -0
  421. data/spec/app/models/symptom.rb +6 -0
  422. data/spec/app/models/tag.rb +8 -0
  423. data/spec/app/models/target.rb +5 -0
  424. data/spec/app/models/template.rb +5 -0
  425. data/spec/app/models/thing.rb +9 -0
  426. data/spec/app/models/title.rb +3 -0
  427. data/spec/app/models/tool.rb +8 -0
  428. data/spec/app/models/topping.rb +5 -0
  429. data/spec/app/models/track.rb +38 -0
  430. data/spec/app/models/translation.rb +5 -0
  431. data/spec/app/models/tree.rb +9 -0
  432. data/spec/app/models/truck.rb +3 -0
  433. data/spec/app/models/user.rb +21 -0
  434. data/spec/app/models/user_account.rb +10 -0
  435. data/spec/app/models/validation_callback.rb +10 -0
  436. data/spec/app/models/vehicle.rb +11 -0
  437. data/spec/app/models/version.rb +5 -0
  438. data/spec/app/models/vet_visit.rb +5 -0
  439. data/spec/app/models/video.rb +13 -0
  440. data/spec/app/models/weapon.rb +11 -0
  441. data/spec/app/models/wiki_page.rb +14 -0
  442. data/spec/app/models/word.rb +15 -0
  443. data/spec/app/models/word_origin.rb +11 -0
  444. data/spec/app/models/writer.rb +11 -0
  445. data/spec/config/mongoid.yml +38 -0
  446. data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
  447. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +118 -0
  448. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +110 -0
  449. data/spec/mongoid/atomic/paths/root_spec.rb +48 -0
  450. data/spec/mongoid/atomic/paths_spec.rb +270 -0
  451. data/spec/mongoid/atomic_spec.rb +365 -0
  452. data/spec/mongoid/attributes/nested_spec.rb +4832 -0
  453. data/spec/mongoid/attributes/readonly_spec.rb +169 -0
  454. data/spec/mongoid/attributes_spec.rb +1412 -0
  455. data/spec/mongoid/changeable_spec.rb +1507 -0
  456. data/spec/mongoid/composable_spec.rb +24 -0
  457. data/spec/mongoid/config/environment_spec.rb +83 -0
  458. data/spec/mongoid/config/options_spec.rb +56 -0
  459. data/spec/mongoid/config_spec.rb +318 -0
  460. data/spec/mongoid/contextual/aggregable/memory_spec.rb +293 -0
  461. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +455 -0
  462. data/spec/mongoid/contextual/atomic_spec.rb +529 -0
  463. data/spec/mongoid/contextual/find_and_modify_spec.rb +220 -0
  464. data/spec/mongoid/contextual/geo_near_spec.rb +405 -0
  465. data/spec/mongoid/contextual/map_reduce_spec.rb +464 -0
  466. data/spec/mongoid/contextual/memory_spec.rb +1236 -0
  467. data/spec/mongoid/contextual/mongo_spec.rb +1843 -0
  468. data/spec/mongoid/contextual/text_search_spec.rb +207 -0
  469. data/spec/mongoid/copyable_spec.rb +393 -0
  470. data/spec/mongoid/criteria/findable_spec.rb +1189 -0
  471. data/spec/mongoid/criteria/inspectable_spec.rb +27 -0
  472. data/spec/mongoid/criteria/marshalable_spec.rb +28 -0
  473. data/spec/mongoid/criteria/modifiable_spec.rb +1063 -0
  474. data/spec/mongoid/criteria/scopable_spec.rb +391 -0
  475. data/spec/mongoid/criteria_spec.rb +3821 -0
  476. data/spec/mongoid/document_spec.rb +1205 -0
  477. data/spec/mongoid/equality_spec.rb +241 -0
  478. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +29 -0
  479. data/spec/mongoid/errors/callback_spec.rb +29 -0
  480. data/spec/mongoid/errors/delete_restriction_spec.rb +29 -0
  481. data/spec/mongoid/errors/document_not_found_spec.rb +104 -0
  482. data/spec/mongoid/errors/eager_load_spec.rb +29 -0
  483. data/spec/mongoid/errors/invalid_collection_spec.rb +36 -0
  484. data/spec/mongoid/errors/invalid_config_option_spec.rb +29 -0
  485. data/spec/mongoid/errors/invalid_field_option_spec.rb +29 -0
  486. data/spec/mongoid/errors/invalid_field_spec.rb +37 -0
  487. data/spec/mongoid/errors/invalid_find_spec.rb +29 -0
  488. data/spec/mongoid/errors/invalid_includes_spec.rb +40 -0
  489. data/spec/mongoid/errors/invalid_index_spec.rb +29 -0
  490. data/spec/mongoid/errors/invalid_options_spec.rb +29 -0
  491. data/spec/mongoid/errors/invalid_path_spec.rb +23 -0
  492. data/spec/mongoid/errors/invalid_scope_spec.rb +29 -0
  493. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +17 -0
  494. data/spec/mongoid/errors/invalid_storage_options_spec.rb +29 -0
  495. data/spec/mongoid/errors/invalid_time_spec.rb +29 -0
  496. data/spec/mongoid/errors/inverse_not_found_spec.rb +29 -0
  497. data/spec/mongoid/errors/mixed_relations_spec.rb +29 -0
  498. data/spec/mongoid/errors/mixed_session_configuration_spec.rb +29 -0
  499. data/spec/mongoid/errors/mongoid_error_spec.rb +48 -0
  500. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +29 -0
  501. data/spec/mongoid/errors/no_environment_spec.rb +29 -0
  502. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +29 -0
  503. data/spec/mongoid/errors/no_metadata_spec.rb +23 -0
  504. data/spec/mongoid/errors/no_parent_spec.rb +29 -0
  505. data/spec/mongoid/errors/no_session_config_spec.rb +29 -0
  506. data/spec/mongoid/errors/no_session_database_spec.rb +29 -0
  507. data/spec/mongoid/errors/no_session_hosts_spec.rb +29 -0
  508. data/spec/mongoid/errors/no_sessions_config_spec.rb +29 -0
  509. data/spec/mongoid/errors/readonly_attribute_spec.rb +29 -0
  510. data/spec/mongoid/errors/scope_overwrite_spec.rb +29 -0
  511. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +29 -0
  512. data/spec/mongoid/errors/unknown_attribute_spec.rb +29 -0
  513. data/spec/mongoid/errors/unsaved_document_spec.rb +37 -0
  514. data/spec/mongoid/errors/unsupported_javascript_spec.rb +29 -0
  515. data/spec/mongoid/errors/validations_spec.rb +45 -0
  516. data/spec/mongoid/extensions/array_spec.rb +638 -0
  517. data/spec/mongoid/extensions/big_decimal_spec.rb +104 -0
  518. data/spec/mongoid/extensions/binary_spec.rb +60 -0
  519. data/spec/mongoid/extensions/boolean_spec.rb +135 -0
  520. data/spec/mongoid/extensions/date_spec.rb +235 -0
  521. data/spec/mongoid/extensions/date_time_spec.rb +155 -0
  522. data/spec/mongoid/extensions/false_class_spec.rb +42 -0
  523. data/spec/mongoid/extensions/float_spec.rb +133 -0
  524. data/spec/mongoid/extensions/hash_spec.rb +333 -0
  525. data/spec/mongoid/extensions/integer_spec.rb +136 -0
  526. data/spec/mongoid/extensions/module_spec.rb +42 -0
  527. data/spec/mongoid/extensions/nil_class_spec.rb +11 -0
  528. data/spec/mongoid/extensions/object_id_spec.rb +946 -0
  529. data/spec/mongoid/extensions/object_spec.rb +292 -0
  530. data/spec/mongoid/extensions/range_spec.rb +105 -0
  531. data/spec/mongoid/extensions/regexp_spec.rb +47 -0
  532. data/spec/mongoid/extensions/set_spec.rb +33 -0
  533. data/spec/mongoid/extensions/string_spec.rb +357 -0
  534. data/spec/mongoid/extensions/symbol_spec.rb +76 -0
  535. data/spec/mongoid/extensions/time_spec.rb +467 -0
  536. data/spec/mongoid/extensions/time_with_zone_spec.rb +405 -0
  537. data/spec/mongoid/extensions/true_class_spec.rb +42 -0
  538. data/spec/mongoid/extensions_spec.rb +15 -0
  539. data/spec/mongoid/factory_spec.rb +185 -0
  540. data/spec/mongoid/fields/foreign_key_spec.rb +694 -0
  541. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +184 -0
  542. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +201 -0
  543. data/spec/mongoid/fields/localized_spec.rb +386 -0
  544. data/spec/mongoid/fields/standard_spec.rb +166 -0
  545. data/spec/mongoid/fields_spec.rb +1229 -0
  546. data/spec/mongoid/findable_spec.rb +342 -0
  547. data/spec/mongoid/identity_map_spec.rb +564 -0
  548. data/spec/mongoid/indexable/specification_spec.rb +87 -0
  549. data/spec/mongoid/indexable_spec.rb +504 -0
  550. data/spec/mongoid/inspectable_spec.rb +49 -0
  551. data/spec/mongoid/interceptable_spec.rb +1564 -0
  552. data/spec/mongoid/loggable_spec.rb +21 -0
  553. data/spec/mongoid/matchable/all_spec.rb +31 -0
  554. data/spec/mongoid/matchable/and_spec.rb +162 -0
  555. data/spec/mongoid/matchable/default_spec.rb +130 -0
  556. data/spec/mongoid/matchable/exists_spec.rb +57 -0
  557. data/spec/mongoid/matchable/gt_spec.rb +75 -0
  558. data/spec/mongoid/matchable/gte_spec.rb +74 -0
  559. data/spec/mongoid/matchable/in_spec.rb +25 -0
  560. data/spec/mongoid/matchable/lt_spec.rb +74 -0
  561. data/spec/mongoid/matchable/lte_spec.rb +74 -0
  562. data/spec/mongoid/matchable/ne_spec.rb +25 -0
  563. data/spec/mongoid/matchable/nin_spec.rb +25 -0
  564. data/spec/mongoid/matchable/or_spec.rb +106 -0
  565. data/spec/mongoid/matchable/size_spec.rb +25 -0
  566. data/spec/mongoid/matchable_spec.rb +532 -0
  567. data/spec/mongoid/persistable/creatable_spec.rb +512 -0
  568. data/spec/mongoid/persistable/deletable_spec.rb +205 -0
  569. data/spec/mongoid/persistable/destroyable_spec.rb +148 -0
  570. data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
  571. data/spec/mongoid/persistable/logical_spec.rb +143 -0
  572. data/spec/mongoid/persistable/poppable_spec.rb +115 -0
  573. data/spec/mongoid/persistable/pullable_spec.rb +228 -0
  574. data/spec/mongoid/persistable/pushable_spec.rb +258 -0
  575. data/spec/mongoid/persistable/renamable_spec.rb +135 -0
  576. data/spec/mongoid/persistable/savable_spec.rb +432 -0
  577. data/spec/mongoid/persistable/settable_spec.rb +139 -0
  578. data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
  579. data/spec/mongoid/persistable/updatable_spec.rb +522 -0
  580. data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
  581. data/spec/mongoid/persistable_spec.rb +206 -0
  582. data/spec/mongoid/positional_spec.rb +227 -0
  583. data/spec/mongoid/railties/document_spec.rb +24 -0
  584. data/spec/mongoid/relations/accessors_spec.rb +736 -0
  585. data/spec/mongoid/relations/auto_save_spec.rb +261 -0
  586. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +171 -0
  587. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +54 -0
  588. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +77 -0
  589. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +241 -0
  590. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +153 -0
  591. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +178 -0
  592. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +131 -0
  593. data/spec/mongoid/relations/builders/embedded/in_spec.rb +34 -0
  594. data/spec/mongoid/relations/builders/embedded/many_spec.rb +132 -0
  595. data/spec/mongoid/relations/builders/embedded/one_spec.rb +99 -0
  596. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +234 -0
  597. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +250 -0
  598. data/spec/mongoid/relations/builders/referenced/in_spec.rb +241 -0
  599. data/spec/mongoid/relations/builders/referenced/many_spec.rb +137 -0
  600. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +178 -0
  601. data/spec/mongoid/relations/builders/referenced/one_spec.rb +124 -0
  602. data/spec/mongoid/relations/builders_spec.rb +226 -0
  603. data/spec/mongoid/relations/cascading/delete_spec.rb +101 -0
  604. data/spec/mongoid/relations/cascading/destroy_spec.rb +47 -0
  605. data/spec/mongoid/relations/cascading/nullify_spec.rb +32 -0
  606. data/spec/mongoid/relations/cascading/restrict_spec.rb +68 -0
  607. data/spec/mongoid/relations/cascading_spec.rb +355 -0
  608. data/spec/mongoid/relations/constraint_spec.rb +74 -0
  609. data/spec/mongoid/relations/conversions_spec.rb +126 -0
  610. data/spec/mongoid/relations/counter_cache_spec.rb +205 -0
  611. data/spec/mongoid/relations/cyclic_spec.rb +156 -0
  612. data/spec/mongoid/relations/embedded/dirty_spec.rb +65 -0
  613. data/spec/mongoid/relations/embedded/in_spec.rb +579 -0
  614. data/spec/mongoid/relations/embedded/many_spec.rb +3781 -0
  615. data/spec/mongoid/relations/embedded/one_spec.rb +1014 -0
  616. data/spec/mongoid/relations/macros_spec.rb +613 -0
  617. data/spec/mongoid/relations/metadata_spec.rb +1917 -0
  618. data/spec/mongoid/relations/options_spec.rb +35 -0
  619. data/spec/mongoid/relations/polymorphic_spec.rb +128 -0
  620. data/spec/mongoid/relations/proxy_spec.rb +48 -0
  621. data/spec/mongoid/relations/referenced/in_spec.rb +1435 -0
  622. data/spec/mongoid/relations/referenced/many_spec.rb +3546 -0
  623. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3556 -0
  624. data/spec/mongoid/relations/referenced/one_spec.rb +1289 -0
  625. data/spec/mongoid/relations/reflections_spec.rb +101 -0
  626. data/spec/mongoid/relations/synchronization_spec.rb +449 -0
  627. data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
  628. data/spec/mongoid/relations/touchable_spec.rb +296 -0
  629. data/spec/mongoid/relations_spec.rb +188 -0
  630. data/spec/mongoid/reloadable_spec.rb +305 -0
  631. data/spec/mongoid/scopable_spec.rb +926 -0
  632. data/spec/mongoid/selectable_spec.rb +134 -0
  633. data/spec/mongoid/serializable_spec.rb +862 -0
  634. data/spec/mongoid/sessions/factory_spec.rb +312 -0
  635. data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
  636. data/spec/mongoid/sessions/options_spec.rb +71 -0
  637. data/spec/mongoid/sessions_spec.rb +1078 -0
  638. data/spec/mongoid/shardable_spec.rb +61 -0
  639. data/spec/mongoid/state_spec.rb +102 -0
  640. data/spec/mongoid/threaded_spec.rb +258 -0
  641. data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
  642. data/spec/mongoid/timestamps/created_spec.rb +44 -0
  643. data/spec/mongoid/timestamps/updated/short_spec.rb +90 -0
  644. data/spec/mongoid/timestamps/updated_spec.rb +86 -0
  645. data/spec/mongoid/timestamps_spec.rb +112 -0
  646. data/spec/mongoid/traversable_spec.rb +244 -0
  647. data/spec/mongoid/unit_of_work_spec.rb +196 -0
  648. data/spec/mongoid/validatable/associated_spec.rb +183 -0
  649. data/spec/mongoid/validatable/format_spec.rb +83 -0
  650. data/spec/mongoid/validatable/length_spec.rb +119 -0
  651. data/spec/mongoid/validatable/numericality_spec.rb +30 -0
  652. data/spec/mongoid/validatable/presence_spec.rb +511 -0
  653. data/spec/mongoid/validatable/uniqueness_spec.rb +2305 -0
  654. data/spec/mongoid/validatable_spec.rb +309 -0
  655. data/spec/mongoid_spec.rb +74 -0
  656. data/spec/rack/mongoid/middleware/identity_map_spec.rb +72 -0
  657. data/spec/rails/mongoid_spec.rb +462 -0
  658. data/spec/spec_helper.rb +103 -0
  659. metadata +1159 -0
@@ -0,0 +1,1507 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Changeable 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
+ expect(person.send(:attribute_change, "title")).to eq(
21
+ [ "Grand Poobah", "Captain Obvious" ]
22
+ )
23
+ end
24
+
25
+ it "allows access via (attribute)_change" do
26
+ expect(person.title_change).to 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
+ expect(person.send(:attribute_change, "test")).to eq(
43
+ [ "Aliased 1", "Aliased 2" ]
44
+ )
45
+ end
46
+
47
+ it "allows access via (attribute)_change" do
48
+ expect(person.test_change).to 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
+ expect(person.send(:attribute_change, "title")).to eq(
67
+ [ "Grand Poobah", "Captain Obvious" ]
68
+ )
69
+ end
70
+
71
+ it "allows access via (attribute)_change" do
72
+ expect(person.title_change).to 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
+ expect(person.send(:attribute_change, "pets")).to eq([ nil, true ])
89
+ end
90
+
91
+ it "allows access via (attribute)_change" do
92
+ expect(person.pets_change).to 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
+ expect(person.send(:attribute_change, "pets")).to eq([ nil, true ])
110
+ end
111
+
112
+ it "allows access via (attribute)_change" do
113
+ expect(person.pets_change).to 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
+ expect(person.send(:attribute_change, "a")).to 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
+ expect(person.send(:attribute_change, "title")).to eq(
147
+ [ "Grand Poobah", "Dark Helmet" ]
148
+ )
149
+ end
150
+
151
+ it "allows access via (attribute)_change" do
152
+ expect(person.title_change).to 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
+ expect(person.send(:attribute_change, "aliases")).to eq(
172
+ [[ "Grand Poobah" ], [ "Dark Helmet" ]]
173
+ )
174
+ end
175
+
176
+ it "allows access via (attribute)_change" do
177
+ expect(person.aliases_change).to 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
+ expect(person.send(:attribute_change, "aliases")).to 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
+ expect(person.send(:attribute_change, "map")).to eq(
208
+ [{ location: "Home" }, { location: "Work" }]
209
+ )
210
+ end
211
+
212
+ it "allows access via (attribute)_change" do
213
+ expect(person.map_change).to 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
+ expect(person.send(:attribute_change, "map")).to 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
+ expect(person.send(:attribute_change, "map")).to 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
+ expect(person.send(:attribute_change, "title")).to 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
+ expect(person.send(:attribute_change, "pets")).to 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
+ expect(person.send(:attribute_change, "pets")).to 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
+ expect(person.send(:attribute_change, "title")).to 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
+ expect(person.send(:attribute_change, "title")).to 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
+ expect(person.send(:attribute_changed?, "title")).to be_true
356
+ end
357
+
358
+ it "allows access via (attribute)_changed?" do
359
+ expect(person.title_changed?).to 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
+ expect(person.send(:attribute_changed?, "test")).to be_true
374
+ end
375
+
376
+ it "allows access via (attribute)_changed?" do
377
+ expect(person.test_changed?).to 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
+ expect(person.send(:attribute_changed?, "pets")).to be_true
394
+ end
395
+
396
+ it "allows access via (attribute)_changed?" do
397
+ expect(person.pets_changed?).to 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
+ expect(person.send(:attribute_changed?, "title")).to 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
+ expect(person.send(:attribute_changed?, "pets")).to 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
+ expect(person.send(:attribute_changed?, "pets")).to 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
+ expect(person).to_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
+ expect(person).to_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
+ expect(person).to 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
+ expect(person).to_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
+ expect(person.send(:attribute_was, "title")).to eq("Grand Poobah")
518
+ end
519
+
520
+ it "allows access via (attribute)_was" do
521
+ expect(person.title_was).to 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
+ expect(person.send(:attribute_was, "test")).to eq("Aliased 1")
536
+ end
537
+
538
+ it "allows access via (attribute)_was" do
539
+ expect(person.test_was).to 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
+ expect(person.send(:attribute_was, "pets")).to be_false
556
+ end
557
+
558
+ it "allows access via (attribute)_was" do
559
+ expect(person.pets_was).to 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
+ expect(person.send(:attribute_was, "title")).to 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
+ expect(person.send(:attribute_was, "pets")).to 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
+ expect(changes).to be_empty
612
+ end
613
+
614
+ it "is not flagged as changed" do
615
+ expect(person).to_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
+ expect(changes).to 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
+ expect(changed["aliases"]).to_not equal(aliases)
649
+ end
650
+
651
+ it "puts the old value in the changes" do
652
+ expect(changed["aliases"]).to 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
+ expect(changed["aliases"]).to equal(aliases)
670
+ end
671
+
672
+ it "retains the first value in the changes" do
673
+ expect(changed["aliases"]).to 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
+ expect(person.changed).to 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
+ expect(person.changed).to_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
+ expect(person.name).to 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
+ expect(person).to 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
+ expect(person).to_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
+ expect(person).to 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
+ person.other_name[:full][:first] = 'Name'
787
+ end
788
+
789
+ it "returns true" do
790
+ person.changes.should_not be_empty
791
+ person.should be_changed
792
+ end
793
+ end
794
+ end
795
+
796
+ context "when the document has not changed" do
797
+
798
+ let(:acolyte) do
799
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
800
+ end
801
+
802
+ it "returns false" do
803
+ expect(acolyte).to_not be_changed
804
+ end
805
+ end
806
+
807
+ context "when a child has changed" do
808
+
809
+ let(:person) do
810
+ Person.create
811
+ end
812
+
813
+ let!(:address) do
814
+ person.addresses.create(street: "hobrecht")
815
+ end
816
+
817
+ before do
818
+ address.number = 10
819
+ end
820
+
821
+ it "returns true" do
822
+ expect(person).to be_changed
823
+ end
824
+ end
825
+
826
+ context "when a deeply embedded child has changed" do
827
+
828
+ let(:person) do
829
+ Person.create
830
+ end
831
+
832
+ let(:address) do
833
+ person.addresses.create(street: "hobrecht")
834
+ end
835
+
836
+ let!(:location) do
837
+ address.locations.create(name: "home")
838
+ end
839
+
840
+ before do
841
+ location.name = "work"
842
+ end
843
+
844
+ it "returns true" do
845
+ expect(person).to be_changed
846
+ end
847
+ end
848
+
849
+ context "when a child is new" do
850
+
851
+ let(:person) do
852
+ Person.create
853
+ end
854
+
855
+ let!(:address) do
856
+ person.addresses.build(street: "hobrecht")
857
+ end
858
+
859
+ it "returns true" do
860
+ expect(person).to be_changed
861
+ end
862
+ end
863
+
864
+ context "when a deeply embedded child is new" do
865
+
866
+ let(:person) do
867
+ Person.create
868
+ end
869
+
870
+ let(:address) do
871
+ person.addresses.create(street: "hobrecht")
872
+ end
873
+
874
+ let!(:location) do
875
+ address.locations.build(name: "home")
876
+ end
877
+
878
+ it "returns true" do
879
+ expect(person).to be_changed
880
+ end
881
+ end
882
+ end
883
+
884
+ describe "#changes" do
885
+
886
+ context "when the document has changed" do
887
+
888
+ let(:person) do
889
+ Person.instantiate(title: "Grand Poobah")
890
+ end
891
+
892
+ before do
893
+ person.title = "Captain Obvious"
894
+ end
895
+
896
+ it "returns a hash of changes" do
897
+ expect(person.changes["title"]).to eq(
898
+ [ nil, "Captain Obvious" ]
899
+ )
900
+ end
901
+
902
+ it "returns a hash with indifferent access" do
903
+ expect(person.changes["title"]).to eq(
904
+ [ nil, "Captain Obvious" ]
905
+ )
906
+ end
907
+ end
908
+
909
+ context "when the document has not changed" do
910
+
911
+ let(:acolyte) do
912
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
913
+ end
914
+
915
+ it "returns an empty hash" do
916
+ expect(acolyte.changes).to be_empty
917
+ end
918
+ end
919
+ end
920
+
921
+ describe "#setters" do
922
+
923
+ context "when the document has changed" do
924
+
925
+ let(:person) do
926
+ Person.new(aliases: [ "007" ]).tap do |p|
927
+ p.new_record = false
928
+ p.move_changes
929
+ end
930
+ end
931
+
932
+ context "when an array field has changed" do
933
+
934
+ context "when the array has values removed" do
935
+
936
+ before do
937
+ person.aliases.delete_one("007")
938
+ end
939
+
940
+ let!(:setters) do
941
+ person.setters
942
+ end
943
+
944
+ it "contains array changes in the setters" do
945
+ expect(setters).to eq({ "aliases" => [] })
946
+ end
947
+ end
948
+
949
+ context "when the array has values added" do
950
+
951
+ before do
952
+ person.aliases << "008"
953
+ end
954
+
955
+ let!(:setters) do
956
+ person.setters
957
+ end
958
+
959
+ it "contains array changes in the setters" do
960
+ expect(setters).to eq({ "aliases" => [ "007", "008" ] })
961
+ end
962
+ end
963
+
964
+ context "when the array has changed completely" do
965
+
966
+ before do
967
+ person.aliases << "008"
968
+ person.aliases.delete_one("007")
969
+ end
970
+
971
+ let!(:setters) do
972
+ person.setters
973
+ end
974
+
975
+ it "does not contain array changes in the setters" do
976
+ expect(setters).to eq({ "aliases" => [ "008" ]})
977
+ end
978
+ end
979
+ end
980
+
981
+ context "when the document is a root document" do
982
+
983
+ let(:person) do
984
+ Person.instantiate(title: "Grand Poobah")
985
+ end
986
+
987
+ before do
988
+ person.title = "Captain Obvious"
989
+ end
990
+
991
+ it "returns a hash of field names and new values" do
992
+ expect(person.setters["title"]).to eq("Captain Obvious")
993
+ end
994
+ end
995
+
996
+ context "when the document is embedded" do
997
+
998
+ let(:person) do
999
+ Person.instantiate(title: "Grand Poobah")
1000
+ end
1001
+
1002
+ let(:address) do
1003
+ Address.instantiate(street: "Oxford St")
1004
+ end
1005
+
1006
+ before do
1007
+ person.addresses << address
1008
+ person.instance_variable_set(:@new_record, false)
1009
+ address.instance_variable_set(:@new_record, false)
1010
+ address.street = "Bond St"
1011
+ end
1012
+
1013
+ it "returns a hash of field names and new values" do
1014
+ expect(address.setters).to eq(
1015
+ { "addresses.0.street" => "Bond St" }
1016
+ )
1017
+ end
1018
+
1019
+ context "when the document is embedded multiple levels" do
1020
+
1021
+ let(:location) do
1022
+ Location.new(name: "Home")
1023
+ end
1024
+
1025
+ before do
1026
+ location.instance_variable_set(:@new_record, false)
1027
+ address.locations << location
1028
+ location.name = "Work"
1029
+ end
1030
+
1031
+ it "returns the proper hash with locations" do
1032
+ expect(location.setters).to eq(
1033
+ { "addresses.0.locations.0.name" => "Work" }
1034
+ )
1035
+ end
1036
+ end
1037
+ end
1038
+ end
1039
+
1040
+ context "when the document has not changed" do
1041
+
1042
+ let(:acolyte) do
1043
+ Acolyte.instantiate("_id" => Moped::BSON::ObjectId.new)
1044
+ end
1045
+
1046
+ it "returns an empty hash" do
1047
+ expect(acolyte.setters).to be_empty
1048
+ end
1049
+ end
1050
+ end
1051
+
1052
+ describe "#previous_changes" do
1053
+
1054
+ let(:person) do
1055
+ Person.new(title: "Grand Poobah")
1056
+ end
1057
+
1058
+ before do
1059
+ person.title = "Captain Obvious"
1060
+ end
1061
+
1062
+ context "when the document has been saved" do
1063
+
1064
+ before do
1065
+ person.save!
1066
+ end
1067
+
1068
+ it "returns the changes before the save" do
1069
+ expect(person.previous_changes["title"]).to eq(
1070
+ [ nil, "Captain Obvious" ]
1071
+ )
1072
+ end
1073
+ end
1074
+
1075
+ context "when the document has not been saved" do
1076
+
1077
+ it "returns an empty hash" do
1078
+ expect(person.previous_changes).to be_empty
1079
+ end
1080
+ end
1081
+ end
1082
+
1083
+ describe "#move_changes" do
1084
+
1085
+ let(:person) do
1086
+ Person.new(title: "Sir")
1087
+ end
1088
+
1089
+ before do
1090
+ person.atomic_pulls["addresses"] = Address.new
1091
+ person.atomic_unsets << Address.new
1092
+ person.delayed_atomic_sets["addresses"] = Address.new
1093
+ person.move_changes
1094
+ end
1095
+
1096
+ it "clears the atomic pulls" do
1097
+ expect(person.atomic_pulls).to be_empty
1098
+ end
1099
+
1100
+ it "clears the atomic unsets" do
1101
+ expect(person.atomic_unsets).to be_empty
1102
+ end
1103
+
1104
+ it "clears the delayed atomic sets" do
1105
+ expect(person.delayed_atomic_sets).to be_empty
1106
+ end
1107
+
1108
+ it "clears the changed attributes" do
1109
+ expect(person.changed_attributes).to be_empty
1110
+ end
1111
+ end
1112
+
1113
+ describe "#reset_attribute!" do
1114
+
1115
+ context "when the attribute has changed" do
1116
+
1117
+ let(:person) do
1118
+ Person.instantiate(title: "Grand Poobah")
1119
+ end
1120
+
1121
+ before do
1122
+ person.title = "Captain Obvious"
1123
+ person.send(:reset_attribute!, "title")
1124
+ end
1125
+
1126
+ it "resets the value to the original" do
1127
+ expect(person.title).to be_nil
1128
+ end
1129
+
1130
+ it "allows access via reset_(attribute)!" do
1131
+ expect(person.title).to be_nil
1132
+ end
1133
+
1134
+ it "removes the field from the changes" do
1135
+ expect(person.changed).to_not include("title")
1136
+ end
1137
+
1138
+ context "when the field is aliased" do
1139
+
1140
+ let(:person) do
1141
+ Person.instantiate(test: "Aliased 1")
1142
+ end
1143
+
1144
+ before do
1145
+ person.test = "Aliased 2"
1146
+ person.send(:reset_attribute!, "test")
1147
+ end
1148
+
1149
+ it "resets the value to the original" do
1150
+ expect(person.test).to be_nil
1151
+ end
1152
+
1153
+ it "removes the field from the changes" do
1154
+ expect(person.changed).to_not include("test")
1155
+ end
1156
+ end
1157
+ end
1158
+
1159
+ context "when the attribute has not changed" do
1160
+
1161
+ let(:person) do
1162
+ Person.instantiate(title: "Grand Poobah")
1163
+ end
1164
+
1165
+ before do
1166
+ person.send(:reset_attribute!, "title")
1167
+ end
1168
+
1169
+ it "does nothing" do
1170
+ expect(person.title).to be_nil
1171
+ end
1172
+ end
1173
+ end
1174
+
1175
+ context "when fields have been defined pre-dirty inclusion" do
1176
+
1177
+ let(:document) do
1178
+ Dokument.new
1179
+ end
1180
+
1181
+ it "defines a _change method" do
1182
+ expect(document.updated_at_change).to be_nil
1183
+ end
1184
+
1185
+ it "defines a _changed? method" do
1186
+ expect(document.updated_at_changed?).to be_false
1187
+ end
1188
+
1189
+ it "defines a _changes method" do
1190
+ expect(document.updated_at_was).to be_nil
1191
+ end
1192
+ end
1193
+
1194
+ context "when only embedded documents change" do
1195
+
1196
+ let!(:person) do
1197
+ Person.create
1198
+ end
1199
+
1200
+ context "when the child is an embeds one" do
1201
+
1202
+ context "when the child is new" do
1203
+
1204
+ let!(:name) do
1205
+ person.build_name(first_name: "Gordon", last_name: "Ramsay")
1206
+ end
1207
+
1208
+ it "flags the parent as changed" do
1209
+ expect(person).to be_changed
1210
+ end
1211
+ end
1212
+
1213
+ context "when the child is modified" do
1214
+
1215
+ let!(:name) do
1216
+ person.create_name(first_name: "Gordon", last_name: "Ramsay")
1217
+ end
1218
+
1219
+ before do
1220
+ name.first_name = "G"
1221
+ end
1222
+
1223
+ it "flags the parent as changed" do
1224
+ expect(person).to be_changed
1225
+ end
1226
+ end
1227
+
1228
+ context "when the child is not modified" do
1229
+
1230
+ let!(:name) do
1231
+ person.create_name(first_name: "Gordon", last_name: "Ramsay")
1232
+ end
1233
+
1234
+ it "does not flag the parent as changed" do
1235
+ expect(person).to_not be_changed
1236
+ end
1237
+ end
1238
+ end
1239
+
1240
+ context "when the child is an embeds many" do
1241
+
1242
+ context "when a child is new" do
1243
+
1244
+ let!(:address) do
1245
+ person.addresses.build(street: "jakobstr.")
1246
+ end
1247
+
1248
+ it "flags the parent as changed" do
1249
+ expect(person).to be_changed
1250
+ end
1251
+ end
1252
+
1253
+ context "when a child is modified" do
1254
+
1255
+ let!(:address) do
1256
+ person.addresses.create(street: "jakobstr.")
1257
+ end
1258
+
1259
+ before do
1260
+ address.city = "Berlin"
1261
+ end
1262
+
1263
+ it "flags the parent as changed" do
1264
+ expect(person).to be_changed
1265
+ end
1266
+ end
1267
+
1268
+ context "when no child is modified" do
1269
+
1270
+ let!(:address) do
1271
+ person.addresses.create(street: "skalitzerstr.")
1272
+ end
1273
+
1274
+ it "does not flag the parent as changed" do
1275
+ expect(person).to_not be_changed
1276
+ end
1277
+ end
1278
+ end
1279
+ end
1280
+
1281
+ context "when changing a hash of hashes" do
1282
+
1283
+ let!(:person) do
1284
+ Person.create(map: { "test" => {}})
1285
+ end
1286
+
1287
+ before do
1288
+ person.map["test"]["value"] = 10
1289
+ end
1290
+
1291
+ it "records the changes" do
1292
+ expect(person.changes).to eq(
1293
+ { "map" => [{ "test" => {}}, { "test" => { "value" => 10 }}]}
1294
+ )
1295
+ end
1296
+ end
1297
+
1298
+ context "when modifying a many to many key" do
1299
+
1300
+ let!(:person) do
1301
+ Person.create
1302
+ end
1303
+
1304
+ let!(:preference) do
1305
+ Preference.create(name: "dirty")
1306
+ end
1307
+
1308
+ before do
1309
+ person.update_attributes(preference_ids: [ preference.id ])
1310
+ end
1311
+
1312
+ it "records the foreign key dirty changes" do
1313
+ expect(person.previous_changes["preference_ids"]).to eq(
1314
+ [nil, [ preference.id ]]
1315
+ )
1316
+ end
1317
+ end
1318
+
1319
+ context "when accessing an array field" do
1320
+
1321
+ let!(:person) do
1322
+ Person.create
1323
+ end
1324
+
1325
+ let(:from_db) do
1326
+ Person.find(person.id)
1327
+ end
1328
+
1329
+ context "when the field is not changed" do
1330
+
1331
+ before do
1332
+ from_db.preference_ids
1333
+ end
1334
+
1335
+ it "flags the change" do
1336
+ expect(from_db.changes["preference_ids"]).to eq([ nil, []])
1337
+ end
1338
+
1339
+ it "does not include the changes in the setters" do
1340
+ expect(from_db.setters).to be_empty
1341
+ end
1342
+ end
1343
+ end
1344
+
1345
+ context "when reloading an unchanged document" do
1346
+
1347
+ let!(:person) do
1348
+ Person.create
1349
+ end
1350
+
1351
+ let(:from_db) do
1352
+ Person.find(person.id)
1353
+ end
1354
+
1355
+ before do
1356
+ from_db.reload
1357
+ end
1358
+
1359
+ it "clears the changed attributes" do
1360
+ expect(from_db.changed_attributes).to be_empty
1361
+ end
1362
+ end
1363
+
1364
+ context "when fields are getting changed" do
1365
+
1366
+ let(:person) do
1367
+ Person.create(
1368
+ title: "MC",
1369
+ some_dynamic_field: 'blah'
1370
+ )
1371
+ end
1372
+
1373
+ before do
1374
+ person.title = "DJ"
1375
+ person.write_attribute(:ssn, "222-22-2222")
1376
+ person.some_dynamic_field = 'bloop'
1377
+ end
1378
+
1379
+ it "marks the document as changed" do
1380
+ expect(person).to be_changed
1381
+ end
1382
+
1383
+ it "marks field changes" do
1384
+ expect(person.changes).to eq({
1385
+ "title" => [ "MC", "DJ" ],
1386
+ "ssn" => [ nil, "222-22-2222" ],
1387
+ "some_dynamic_field" => [ "blah", "bloop" ]
1388
+ })
1389
+ end
1390
+
1391
+ it "marks changed fields" do
1392
+ expect(person.changed).to eq([ "title", "ssn", "some_dynamic_field" ])
1393
+ end
1394
+
1395
+ it "marks the field as changed" do
1396
+ expect(person.title_changed?).to be_true
1397
+ end
1398
+
1399
+ it "stores previous field values" do
1400
+ expect(person.title_was).to eq("MC")
1401
+ end
1402
+
1403
+ it "marks field changes" do
1404
+ expect(person.title_change).to eq([ "MC", "DJ" ])
1405
+ end
1406
+
1407
+ it "allows reset of field changes" do
1408
+ person.reset_title!
1409
+ expect(person.title).to eq("MC")
1410
+ expect(person.changed).to eq([ "ssn", "some_dynamic_field" ])
1411
+ end
1412
+
1413
+ context "after a save" do
1414
+
1415
+ before do
1416
+ person.save!
1417
+ end
1418
+
1419
+ it "clears changes" do
1420
+ expect(person).to_not be_changed
1421
+ end
1422
+
1423
+ it "stores previous changes" do
1424
+ expect(person.previous_changes["title"]).to eq([ "MC", "DJ" ])
1425
+ expect(person.previous_changes["ssn"]).to eq([ nil, "222-22-2222" ])
1426
+ end
1427
+ end
1428
+
1429
+ context "when the previous value is nil" do
1430
+
1431
+ before do
1432
+ person.score = 100
1433
+ person.reset_score!
1434
+ end
1435
+
1436
+ it "removes the attribute from the document" do
1437
+ expect(person.score).to be_nil
1438
+ end
1439
+ end
1440
+ end
1441
+
1442
+ context "when accessing dirty attributes in callbacks" do
1443
+
1444
+ context "when the document is persisted" do
1445
+
1446
+ let!(:acolyte) do
1447
+ Acolyte.create(name: "callback-test")
1448
+ end
1449
+
1450
+ before do
1451
+ Acolyte.set_callback(:save, :after, if: :callback_test?) do |doc|
1452
+ doc[:changed_in_callback] = doc.changes.dup
1453
+ end
1454
+ end
1455
+
1456
+ after do
1457
+ Acolyte._save_callbacks.reject! do |callback|
1458
+ callback.kind == :after
1459
+ end
1460
+ end
1461
+
1462
+ it "retains the changes until after all callbacks" do
1463
+ acolyte.update_attribute(:status, "testing")
1464
+ expect(acolyte.changed_in_callback).to eq({ "status" => [ nil, "testing" ] })
1465
+ end
1466
+ end
1467
+
1468
+ context "when the document is new" do
1469
+
1470
+ let!(:acolyte) do
1471
+ Acolyte.new(name: "callback-test")
1472
+ end
1473
+
1474
+ before do
1475
+ Acolyte.set_callback(:save, :after, if: :callback_test?) do |doc|
1476
+ doc[:changed_in_callback] = doc.changes.dup
1477
+ end
1478
+ end
1479
+
1480
+ after do
1481
+ Acolyte._save_callbacks.reject! do |callback|
1482
+ callback.kind == :after
1483
+ end
1484
+ end
1485
+
1486
+ it "retains the changes until after all callbacks" do
1487
+ acolyte.save
1488
+ expect(acolyte.changed_in_callback["name"]).to eq([ nil, "callback-test" ])
1489
+ end
1490
+ end
1491
+ end
1492
+
1493
+ context "when associations are getting changed" do
1494
+
1495
+ let(:person) do
1496
+ Person.create(addresses: [ Address.new ])
1497
+ end
1498
+
1499
+ before do
1500
+ person.addresses = [ Address.new ]
1501
+ end
1502
+
1503
+ it "does not set the association to nil when hitting the database" do
1504
+ expect(person.setters).to_not eq({ "addresses" => nil })
1505
+ end
1506
+ end
1507
+ end