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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/lib/mongoid/contextual.rb +3 -0
- data/lib/mongoid/criteria.rb +10 -2
- data/lib/mongoid/document.rb +1 -1
- data/lib/mongoid/paranoia.rb +4 -0
- data/lib/mongoid/persistence/upsertion.rb +1 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +16 -2
- data/lib/mongoid/relations/macros.rb +1 -1
- data/lib/mongoid/relations/one.rb +12 -0
- data/lib/mongoid/relations/referenced/in.rb +18 -1
- data/lib/mongoid/relations/referenced/many_to_many.rb +2 -2
- data/lib/mongoid/validations.rb +1 -1
- data/lib/mongoid/validations/localizable.rb +1 -1
- data/lib/mongoid/validations/presence.rb +1 -1
- data/lib/mongoid/validations/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/support/ruby_version.rb +1 -1
- data/spec/app/models/account.rb +32 -0
- data/spec/app/models/acolyte.rb +16 -0
- data/spec/app/models/actor.rb +19 -0
- data/spec/app/models/actor_observer.rb +15 -0
- data/spec/app/models/actress.rb +2 -0
- data/spec/app/models/address.rb +72 -0
- data/spec/app/models/address_component.rb +5 -0
- data/spec/app/models/address_number.rb +6 -0
- data/spec/app/models/agency.rb +5 -0
- data/spec/app/models/agent.rb +12 -0
- data/spec/app/models/album.rb +14 -0
- data/spec/app/models/alert.rb +5 -0
- data/spec/app/models/animal.rb +25 -0
- data/spec/app/models/answer.rb +4 -0
- data/spec/app/models/appointment.rb +7 -0
- data/spec/app/models/article.rb +13 -0
- data/spec/app/models/artist.rb +66 -0
- data/spec/app/models/artwork.rb +4 -0
- data/spec/app/models/augmentation.rb +11 -0
- data/spec/app/models/author.rb +6 -0
- data/spec/app/models/band.rb +25 -0
- data/spec/app/models/bar.rb +9 -0
- data/spec/app/models/basic.rb +6 -0
- data/spec/app/models/bed.rb +1 -0
- data/spec/app/models/big_palette.rb +2 -0
- data/spec/app/models/birthday.rb +13 -0
- data/spec/app/models/book.rb +12 -0
- data/spec/app/models/breed.rb +4 -0
- data/spec/app/models/browser.rb +6 -0
- data/spec/app/models/building.rb +7 -0
- data/spec/app/models/building_address.rb +7 -0
- data/spec/app/models/bus.rb +7 -0
- data/spec/app/models/business.rb +5 -0
- data/spec/app/models/callback_recorder.rb +25 -0
- data/spec/app/models/callback_test.rb +9 -0
- data/spec/app/models/canvas.rb +25 -0
- data/spec/app/models/car.rb +1 -0
- data/spec/app/models/cat.rb +8 -0
- data/spec/app/models/category.rb +8 -0
- data/spec/app/models/child.rb +4 -0
- data/spec/app/models/child_doc.rb +22 -0
- data/spec/app/models/church.rb +4 -0
- data/spec/app/models/circle.rb +3 -0
- data/spec/app/models/circuit.rb +4 -0
- data/spec/app/models/circus.rb +7 -0
- data/spec/app/models/code.rb +5 -0
- data/spec/app/models/comment.rb +16 -0
- data/spec/app/models/contractor.rb +7 -0
- data/spec/app/models/cookie.rb +6 -0
- data/spec/app/models/country_code.rb +8 -0
- data/spec/app/models/definition.rb +8 -0
- data/spec/app/models/description.rb +11 -0
- data/spec/app/models/dictionary.rb +10 -0
- data/spec/app/models/division.rb +10 -0
- data/spec/app/models/doctor.rb +12 -0
- data/spec/app/models/dog.rb +7 -0
- data/spec/app/models/dokument.rb +5 -0
- data/spec/app/models/driver.rb +7 -0
- data/spec/app/models/drug.rb +8 -0
- data/spec/app/models/email.rb +6 -0
- data/spec/app/models/employer.rb +5 -0
- data/spec/app/models/entry.rb +6 -0
- data/spec/app/models/eraser.rb +1 -0
- data/spec/app/models/event.rb +22 -0
- data/spec/app/models/exhibition.rb +4 -0
- data/spec/app/models/exhibitor.rb +5 -0
- data/spec/app/models/eye.rb +9 -0
- data/spec/app/models/eye_bowl.rb +9 -0
- data/spec/app/models/face.rb +8 -0
- data/spec/app/models/favorite.rb +6 -0
- data/spec/app/models/filesystem.rb +4 -0
- data/spec/app/models/fire_hydrant.rb +6 -0
- data/spec/app/models/firefox.rb +4 -0
- data/spec/app/models/fish.rb +8 -0
- data/spec/app/models/folder.rb +7 -0
- data/spec/app/models/folder_item.rb +9 -0
- data/spec/app/models/fruits.rb +28 -0
- data/spec/app/models/game.rb +21 -0
- data/spec/app/models/ghost.rb +7 -0
- data/spec/app/models/home.rb +4 -0
- data/spec/app/models/house.rb +8 -0
- data/spec/app/models/html_writer.rb +3 -0
- data/spec/app/models/image.rb +22 -0
- data/spec/app/models/implant.rb +16 -0
- data/spec/app/models/item.rb +12 -0
- data/spec/app/models/jar.rb +7 -0
- data/spec/app/models/label.rb +40 -0
- data/spec/app/models/language.rb +5 -0
- data/spec/app/models/lat_lng.rb +15 -0
- data/spec/app/models/league.rb +11 -0
- data/spec/app/models/learner.rb +2 -0
- data/spec/app/models/line_item.rb +6 -0
- data/spec/app/models/location.rb +8 -0
- data/spec/app/models/login.rb +8 -0
- data/spec/app/models/manufacturer.rb +7 -0
- data/spec/app/models/meat.rb +4 -0
- data/spec/app/models/membership.rb +4 -0
- data/spec/app/models/mixed_drink.rb +4 -0
- data/spec/app/models/movie.rb +12 -0
- data/spec/app/models/my_hash.rb +2 -0
- data/spec/app/models/name.rb +23 -0
- data/spec/app/models/node.rb +5 -0
- data/spec/app/models/note.rb +12 -0
- data/spec/app/models/ordered_post.rb +6 -0
- data/spec/app/models/ordered_preference.rb +6 -0
- data/spec/app/models/oscar.rb +15 -0
- data/spec/app/models/override.rb +16 -0
- data/spec/app/models/ownable.rb +6 -0
- data/spec/app/models/owner.rb +6 -0
- data/spec/app/models/pack.rb +3 -0
- data/spec/app/models/page.rb +5 -0
- data/spec/app/models/page_question.rb +4 -0
- data/spec/app/models/palette.rb +7 -0
- data/spec/app/models/paranoid_phone.rb +25 -0
- data/spec/app/models/paranoid_post.rb +36 -0
- data/spec/app/models/parent.rb +5 -0
- data/spec/app/models/parent_doc.rb +6 -0
- data/spec/app/models/passport.rb +5 -0
- data/spec/app/models/patient.rb +9 -0
- data/spec/app/models/pdf_writer.rb +3 -0
- data/spec/app/models/pencil.rb +1 -0
- data/spec/app/models/person.rb +201 -0
- data/spec/app/models/pet.rb +23 -0
- data/spec/app/models/pet_owner.rb +6 -0
- data/spec/app/models/phone.rb +11 -0
- data/spec/app/models/phone_observer.rb +6 -0
- data/spec/app/models/pizza.rb +7 -0
- data/spec/app/models/player.rb +35 -0
- data/spec/app/models/post.rb +43 -0
- data/spec/app/models/powerup.rb +11 -0
- data/spec/app/models/preference.rb +9 -0
- data/spec/app/models/princess.rb +8 -0
- data/spec/app/models/product.rb +17 -0
- data/spec/app/models/profile.rb +5 -0
- data/spec/app/models/pronunciation.rb +5 -0
- data/spec/app/models/purchase.rb +4 -0
- data/spec/app/models/question.rb +8 -0
- data/spec/app/models/quiz.rb +10 -0
- data/spec/app/models/rating.rb +8 -0
- data/spec/app/models/record.rb +46 -0
- data/spec/app/models/registry.rb +4 -0
- data/spec/app/models/role.rb +7 -0
- data/spec/app/models/root_category.rb +4 -0
- data/spec/app/models/sandwich.rb +4 -0
- data/spec/app/models/scheduler.rb +7 -0
- data/spec/app/models/seo.rb +7 -0
- data/spec/app/models/series.rb +4 -0
- data/spec/app/models/server.rb +13 -0
- data/spec/app/models/service.rb +22 -0
- data/spec/app/models/shape.rb +12 -0
- data/spec/app/models/shelf.rb +5 -0
- data/spec/app/models/shipping_container.rb +5 -0
- data/spec/app/models/shipping_pack.rb +3 -0
- data/spec/app/models/shop.rb +6 -0
- data/spec/app/models/short_agent.rb +4 -0
- data/spec/app/models/short_quiz.rb +5 -0
- data/spec/app/models/slave.rb +6 -0
- data/spec/app/models/song.rb +8 -0
- data/spec/app/models/square.rb +4 -0
- data/spec/app/models/strategy.rb +3 -0
- data/spec/app/models/sub_item.rb +3 -0
- data/spec/app/models/subscription.rb +4 -0
- data/spec/app/models/survey.rb +5 -0
- data/spec/app/models/symptom.rb +6 -0
- data/spec/app/models/tag.rb +8 -0
- data/spec/app/models/target.rb +5 -0
- data/spec/app/models/template.rb +5 -0
- data/spec/app/models/thing.rb +9 -0
- data/spec/app/models/title.rb +4 -0
- data/spec/app/models/tool.rb +8 -0
- data/spec/app/models/topping.rb +5 -0
- data/spec/app/models/track.rb +38 -0
- data/spec/app/models/translation.rb +5 -0
- data/spec/app/models/tree.rb +9 -0
- data/spec/app/models/truck.rb +3 -0
- data/spec/app/models/user.rb +21 -0
- data/spec/app/models/user_account.rb +10 -0
- data/spec/app/models/validation_callback.rb +10 -0
- data/spec/app/models/vehicle.rb +11 -0
- data/spec/app/models/version.rb +5 -0
- data/spec/app/models/vet_visit.rb +5 -0
- data/spec/app/models/video.rb +17 -0
- data/spec/app/models/video_game.rb +1 -0
- data/spec/app/models/weapon.rb +11 -0
- data/spec/app/models/wiki_page.rb +17 -0
- data/spec/app/models/word.rb +12 -0
- data/spec/app/models/word_origin.rb +11 -0
- data/spec/app/models/writer.rb +11 -0
- data/spec/config/mongoid.yml +40 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +159 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +152 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +106 -0
- data/spec/mongoid/atomic/paths_spec.rb +270 -0
- data/spec/mongoid/atomic/positionable_spec.rb +227 -0
- data/spec/mongoid/atomic_spec.rb +365 -0
- data/spec/mongoid/attributes/processing_spec.rb +149 -0
- data/spec/mongoid/attributes/readonly_spec.rb +169 -0
- data/spec/mongoid/attributes_spec.rb +1705 -0
- data/spec/mongoid/callbacks_spec.rb +1564 -0
- data/spec/mongoid/components_spec.rb +24 -0
- data/spec/mongoid/config/environment_spec.rb +83 -0
- data/spec/mongoid/config/options_spec.rb +56 -0
- data/spec/mongoid/config_spec.rb +334 -0
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +293 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +455 -0
- data/spec/mongoid/contextual/atomic_spec.rb +525 -0
- data/spec/mongoid/contextual/find_and_modify_spec.rb +220 -0
- data/spec/mongoid/contextual/geo_near_spec.rb +405 -0
- data/spec/mongoid/contextual/map_reduce_spec.rb +464 -0
- data/spec/mongoid/contextual/memory_spec.rb +1236 -0
- data/spec/mongoid/contextual/mongo_spec.rb +1757 -0
- data/spec/mongoid/copyable_spec.rb +393 -0
- data/spec/mongoid/criteria_spec.rb +5140 -0
- data/spec/mongoid/criterion/destructive_spec.rb +101 -0
- data/spec/mongoid/criterion/inspection_spec.rb +27 -0
- data/spec/mongoid/criterion/marshalable_spec.rb +28 -0
- data/spec/mongoid/criterion/modifiable_spec.rb +409 -0
- data/spec/mongoid/criterion/modification_spec.rb +402 -0
- data/spec/mongoid/criterion/scoping_spec.rb +391 -0
- data/spec/mongoid/dirty_spec.rb +1508 -0
- data/spec/mongoid/document_spec.rb +1146 -0
- data/spec/mongoid/equality_spec.rb +241 -0
- data/spec/mongoid/errors/ambiguous_relationship_spec.rb +29 -0
- data/spec/mongoid/errors/callback_spec.rb +29 -0
- data/spec/mongoid/errors/delete_restriction_spec.rb +29 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +104 -0
- data/spec/mongoid/errors/eager_load_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_collection_spec.rb +36 -0
- data/spec/mongoid/errors/invalid_config_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_spec.rb +37 -0
- data/spec/mongoid/errors/invalid_find_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_includes_spec.rb +40 -0
- data/spec/mongoid/errors/invalid_index_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_path_spec.rb +23 -0
- data/spec/mongoid/errors/invalid_scope_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +17 -0
- data/spec/mongoid/errors/invalid_storage_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_time_spec.rb +29 -0
- data/spec/mongoid/errors/inverse_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_relations_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_session_configuration_spec.rb +29 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +48 -0
- data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/no_environment_spec.rb +29 -0
- data/spec/mongoid/errors/no_map_reduce_output_spec.rb +29 -0
- data/spec/mongoid/errors/no_metadata_spec.rb +23 -0
- data/spec/mongoid/errors/no_parent_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_config_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_database_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_hosts_spec.rb +29 -0
- data/spec/mongoid/errors/no_sessions_config_spec.rb +29 -0
- data/spec/mongoid/errors/readonly_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/scope_overwrite_spec.rb +29 -0
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +29 -0
- data/spec/mongoid/errors/unknown_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/unsaved_document_spec.rb +37 -0
- data/spec/mongoid/errors/unsupported_javascript_spec.rb +29 -0
- data/spec/mongoid/errors/validations_spec.rb +45 -0
- data/spec/mongoid/errors/versioning_not_on_root_spec.rb +29 -0
- data/spec/mongoid/extensions/array_spec.rb +638 -0
- data/spec/mongoid/extensions/big_decimal_spec.rb +104 -0
- data/spec/mongoid/extensions/binary_spec.rb +60 -0
- data/spec/mongoid/extensions/boolean_spec.rb +135 -0
- data/spec/mongoid/extensions/date_spec.rb +235 -0
- data/spec/mongoid/extensions/date_time_spec.rb +155 -0
- data/spec/mongoid/extensions/false_class_spec.rb +42 -0
- data/spec/mongoid/extensions/float_spec.rb +133 -0
- data/spec/mongoid/extensions/hash_spec.rb +333 -0
- data/spec/mongoid/extensions/integer_spec.rb +136 -0
- data/spec/mongoid/extensions/module_spec.rb +42 -0
- data/spec/mongoid/extensions/nil_class_spec.rb +11 -0
- data/spec/mongoid/extensions/object_id_spec.rb +946 -0
- data/spec/mongoid/extensions/object_spec.rb +292 -0
- data/spec/mongoid/extensions/range_spec.rb +105 -0
- data/spec/mongoid/extensions/regexp_spec.rb +47 -0
- data/spec/mongoid/extensions/set_spec.rb +33 -0
- data/spec/mongoid/extensions/string_spec.rb +368 -0
- data/spec/mongoid/extensions/symbol_spec.rb +76 -0
- data/spec/mongoid/extensions/time_spec.rb +467 -0
- data/spec/mongoid/extensions/time_with_zone_spec.rb +405 -0
- data/spec/mongoid/extensions/true_class_spec.rb +42 -0
- data/spec/mongoid/factory_spec.rb +185 -0
- data/spec/mongoid/fields/foreign_key_spec.rb +694 -0
- data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +184 -0
- data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +201 -0
- data/spec/mongoid/fields/localized_spec.rb +386 -0
- data/spec/mongoid/fields/standard_spec.rb +166 -0
- data/spec/mongoid/fields_spec.rb +1253 -0
- data/spec/mongoid/finders_spec.rb +321 -0
- data/spec/mongoid/hierarchy_spec.rb +244 -0
- data/spec/mongoid/identity_map_spec.rb +564 -0
- data/spec/mongoid/indexes_spec.rb +404 -0
- data/spec/mongoid/inspection_spec.rb +57 -0
- data/spec/mongoid/json_spec.rb +33 -0
- data/spec/mongoid/loggable_spec.rb +21 -0
- data/spec/mongoid/matchers/all_spec.rb +31 -0
- data/spec/mongoid/matchers/and_spec.rb +162 -0
- data/spec/mongoid/matchers/default_spec.rb +130 -0
- data/spec/mongoid/matchers/exists_spec.rb +57 -0
- data/spec/mongoid/matchers/gt_spec.rb +74 -0
- data/spec/mongoid/matchers/gte_spec.rb +74 -0
- data/spec/mongoid/matchers/in_spec.rb +25 -0
- data/spec/mongoid/matchers/lt_spec.rb +74 -0
- data/spec/mongoid/matchers/lte_spec.rb +74 -0
- data/spec/mongoid/matchers/ne_spec.rb +25 -0
- data/spec/mongoid/matchers/nin_spec.rb +25 -0
- data/spec/mongoid/matchers/or_spec.rb +106 -0
- data/spec/mongoid/matchers/size_spec.rb +25 -0
- data/spec/mongoid/matchers_spec.rb +532 -0
- data/spec/mongoid/multi_parameter_attributes_spec.rb +128 -0
- data/spec/mongoid/nested_attributes_spec.rb +4945 -0
- data/spec/mongoid/observer_spec.rb +290 -0
- data/spec/mongoid/paranoia_spec.rb +759 -0
- data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +262 -0
- data/spec/mongoid/persistence/atomic/bit_spec.rb +88 -0
- data/spec/mongoid/persistence/atomic/inc_spec.rb +133 -0
- data/spec/mongoid/persistence/atomic/pop_spec.rb +111 -0
- data/spec/mongoid/persistence/atomic/pull_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/pull_spec.rb +80 -0
- data/spec/mongoid/persistence/atomic/push_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/push_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/rename_spec.rb +42 -0
- data/spec/mongoid/persistence/atomic/sets_spec.rb +154 -0
- data/spec/mongoid/persistence/atomic/unset_spec.rb +65 -0
- data/spec/mongoid/persistence/atomic_spec.rb +216 -0
- data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +191 -0
- data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +8 -0
- data/spec/mongoid/persistence/operations/insert_spec.rb +149 -0
- data/spec/mongoid/persistence/operations/remove_spec.rb +113 -0
- data/spec/mongoid/persistence/operations/update_spec.rb +141 -0
- data/spec/mongoid/persistence/operations/upsert_spec.rb +59 -0
- data/spec/mongoid/persistence/operations_spec.rb +313 -0
- data/spec/mongoid/persistence_spec.rb +2279 -0
- data/spec/mongoid/railties/document_spec.rb +24 -0
- data/spec/mongoid/relations/accessors_spec.rb +844 -0
- data/spec/mongoid/relations/auto_save_spec.rb +261 -0
- data/spec/mongoid/relations/bindings/embedded/in_spec.rb +171 -0
- data/spec/mongoid/relations/bindings/embedded/many_spec.rb +54 -0
- data/spec/mongoid/relations/bindings/embedded/one_spec.rb +77 -0
- data/spec/mongoid/relations/bindings/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/bindings/referenced/many_spec.rb +153 -0
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/bindings/referenced/one_spec.rb +131 -0
- data/spec/mongoid/relations/builders/embedded/in_spec.rb +34 -0
- data/spec/mongoid/relations/builders/embedded/many_spec.rb +132 -0
- data/spec/mongoid/relations/builders/embedded/one_spec.rb +99 -0
- data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +234 -0
- data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +250 -0
- data/spec/mongoid/relations/builders/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/builders/referenced/many_spec.rb +137 -0
- data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/builders/referenced/one_spec.rb +124 -0
- data/spec/mongoid/relations/builders_spec.rb +226 -0
- data/spec/mongoid/relations/cascading/delete_spec.rb +101 -0
- data/spec/mongoid/relations/cascading/destroy_spec.rb +47 -0
- data/spec/mongoid/relations/cascading/nullify_spec.rb +32 -0
- data/spec/mongoid/relations/cascading/restrict_spec.rb +68 -0
- data/spec/mongoid/relations/cascading_spec.rb +355 -0
- data/spec/mongoid/relations/constraint_spec.rb +74 -0
- data/spec/mongoid/relations/conversions_spec.rb +126 -0
- data/spec/mongoid/relations/counter_cache_spec.rb +205 -0
- data/spec/mongoid/relations/cyclic_spec.rb +156 -0
- data/spec/mongoid/relations/embedded/dirty_spec.rb +65 -0
- data/spec/mongoid/relations/embedded/in_spec.rb +580 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +3841 -0
- data/spec/mongoid/relations/embedded/one_spec.rb +1055 -0
- data/spec/mongoid/relations/macros_spec.rb +625 -0
- data/spec/mongoid/relations/metadata_spec.rb +2030 -0
- data/spec/mongoid/relations/options_spec.rb +35 -0
- data/spec/mongoid/relations/polymorphic_spec.rb +132 -0
- data/spec/mongoid/relations/proxy_spec.rb +48 -0
- data/spec/mongoid/relations/referenced/in_spec.rb +1501 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +3632 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3561 -0
- data/spec/mongoid/relations/referenced/one_spec.rb +1331 -0
- data/spec/mongoid/relations/reflections_spec.rb +101 -0
- data/spec/mongoid/relations/synchronization_spec.rb +453 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
- data/spec/mongoid/relations_spec.rb +188 -0
- data/spec/mongoid/reloading_spec.rb +305 -0
- data/spec/mongoid/scoping_spec.rb +978 -0
- data/spec/mongoid/serialization_spec.rb +833 -0
- data/spec/mongoid/sessions/factory_spec.rb +312 -0
- data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
- data/spec/mongoid/sessions_spec.rb +1111 -0
- data/spec/mongoid/sharding_spec.rb +61 -0
- data/spec/mongoid/state_spec.rb +102 -0
- data/spec/mongoid/threaded_spec.rb +296 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
- data/spec/mongoid/timestamps/created_spec.rb +44 -0
- data/spec/mongoid/timestamps/timeless_spec.rb +130 -0
- data/spec/mongoid/timestamps/updated/short_spec.rb +90 -0
- data/spec/mongoid/timestamps/updated_spec.rb +86 -0
- data/spec/mongoid/timestamps_spec.rb +112 -0
- data/spec/mongoid/unit_of_work_spec.rb +196 -0
- data/spec/mongoid/validations/associated_spec.rb +183 -0
- data/spec/mongoid/validations/format_spec.rb +83 -0
- data/spec/mongoid/validations/length_spec.rb +223 -0
- data/spec/mongoid/validations/numericality_spec.rb +30 -0
- data/spec/mongoid/validations/presence_spec.rb +592 -0
- data/spec/mongoid/validations/uniqueness_spec.rb +2399 -0
- data/spec/mongoid/validations_spec.rb +309 -0
- data/spec/mongoid/versioning_spec.rb +540 -0
- data/spec/mongoid_spec.rb +74 -0
- data/spec/rack/mongoid/middleware/identity_map_spec.rb +72 -0
- data/spec/rails/mongoid_spec.rb +462 -0
- data/spec/spec_helper.rb +93 -0
- 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
|