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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3213 -0
- data/LICENSE +20 -0
- data/README.md +62 -0
- data/Rakefile +35 -0
- data/lib/config/locales/en.yml +448 -0
- data/lib/mongoid.rb +104 -0
- data/lib/mongoid/atomic.rb +384 -0
- data/lib/mongoid/atomic/modifiers.rb +317 -0
- data/lib/mongoid/atomic/paths.rb +3 -0
- data/lib/mongoid/atomic/paths/embedded.rb +28 -0
- data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
- data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
- data/lib/mongoid/atomic/paths/root.rb +39 -0
- data/lib/mongoid/attributes.rb +284 -0
- data/lib/mongoid/attributes/dynamic.rb +154 -0
- data/lib/mongoid/attributes/nested.rb +82 -0
- data/lib/mongoid/attributes/processing.rb +147 -0
- data/lib/mongoid/attributes/readonly.rb +56 -0
- data/lib/mongoid/changeable.rb +379 -0
- data/lib/mongoid/composable.rb +104 -0
- data/lib/mongoid/config.rb +263 -0
- data/lib/mongoid/config/environment.rb +44 -0
- data/lib/mongoid/config/options.rb +74 -0
- data/lib/mongoid/config/validators.rb +3 -0
- data/lib/mongoid/config/validators/option.rb +25 -0
- data/lib/mongoid/config/validators/session.rb +140 -0
- data/lib/mongoid/contextual.rb +54 -0
- data/lib/mongoid/contextual/aggregable/memory.rb +109 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +147 -0
- data/lib/mongoid/contextual/atomic.rb +180 -0
- data/lib/mongoid/contextual/command.rb +61 -0
- data/lib/mongoid/contextual/eager.rb +158 -0
- data/lib/mongoid/contextual/find_and_modify.rb +69 -0
- data/lib/mongoid/contextual/geo_near.rb +238 -0
- data/lib/mongoid/contextual/map_reduce.rb +324 -0
- data/lib/mongoid/contextual/memory.rb +440 -0
- data/lib/mongoid/contextual/mongo.rb +676 -0
- data/lib/mongoid/contextual/queryable.rb +25 -0
- data/lib/mongoid/contextual/text_search.rb +180 -0
- data/lib/mongoid/copyable.rb +67 -0
- data/lib/mongoid/criteria.rb +562 -0
- data/lib/mongoid/criteria/findable.rb +179 -0
- data/lib/mongoid/criteria/inspectable.rb +25 -0
- data/lib/mongoid/criteria/marshalable.rb +50 -0
- data/lib/mongoid/criteria/modifiable.rb +189 -0
- data/lib/mongoid/criteria/scopable.rb +158 -0
- data/lib/mongoid/document.rb +361 -0
- data/lib/mongoid/equality.rb +66 -0
- data/lib/mongoid/errors.rb +40 -0
- data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
- data/lib/mongoid/errors/callback.rb +25 -0
- data/lib/mongoid/errors/delete_restriction.rb +29 -0
- data/lib/mongoid/errors/document_not_found.rb +111 -0
- data/lib/mongoid/errors/eager_load.rb +22 -0
- data/lib/mongoid/errors/invalid_collection.rb +18 -0
- data/lib/mongoid/errors/invalid_config_option.rb +27 -0
- data/lib/mongoid/errors/invalid_field.rb +64 -0
- data/lib/mongoid/errors/invalid_field_option.rb +35 -0
- data/lib/mongoid/errors/invalid_find.rb +19 -0
- data/lib/mongoid/errors/invalid_includes.rb +32 -0
- data/lib/mongoid/errors/invalid_index.rb +28 -0
- data/lib/mongoid/errors/invalid_options.rb +28 -0
- data/lib/mongoid/errors/invalid_path.rb +21 -0
- data/lib/mongoid/errors/invalid_scope.rb +24 -0
- data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
- data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
- data/lib/mongoid/errors/invalid_time.rb +22 -0
- data/lib/mongoid/errors/inverse_not_found.rb +29 -0
- data/lib/mongoid/errors/mixed_relations.rb +32 -0
- data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
- data/lib/mongoid/errors/mongoid_error.rb +92 -0
- data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
- data/lib/mongoid/errors/no_default_session.rb +23 -0
- data/lib/mongoid/errors/no_environment.rb +19 -0
- data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
- data/lib/mongoid/errors/no_metadata.rb +21 -0
- data/lib/mongoid/errors/no_parent.rb +24 -0
- data/lib/mongoid/errors/no_session_config.rb +22 -0
- data/lib/mongoid/errors/no_session_database.rb +27 -0
- data/lib/mongoid/errors/no_session_hosts.rb +27 -0
- data/lib/mongoid/errors/no_sessions_config.rb +20 -0
- data/lib/mongoid/errors/readonly_attribute.rb +25 -0
- data/lib/mongoid/errors/scope_overwrite.rb +21 -0
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
- data/lib/mongoid/errors/unknown_attribute.rb +25 -0
- data/lib/mongoid/errors/unsaved_document.rb +19 -0
- data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
- data/lib/mongoid/errors/validations.rb +29 -0
- data/lib/mongoid/evolvable.rb +19 -0
- data/lib/mongoid/extensions.rb +35 -0
- data/lib/mongoid/extensions/array.rb +180 -0
- data/lib/mongoid/extensions/big_decimal.rb +69 -0
- data/lib/mongoid/extensions/boolean.rb +21 -0
- data/lib/mongoid/extensions/date.rb +77 -0
- data/lib/mongoid/extensions/date_time.rb +73 -0
- data/lib/mongoid/extensions/false_class.rb +38 -0
- data/lib/mongoid/extensions/float.rb +56 -0
- data/lib/mongoid/extensions/hash.rb +209 -0
- data/lib/mongoid/extensions/integer.rb +67 -0
- data/lib/mongoid/extensions/module.rb +28 -0
- data/lib/mongoid/extensions/nil_class.rb +33 -0
- data/lib/mongoid/extensions/object.rb +274 -0
- data/lib/mongoid/extensions/object_id.rb +54 -0
- data/lib/mongoid/extensions/range.rb +79 -0
- data/lib/mongoid/extensions/regexp.rb +27 -0
- data/lib/mongoid/extensions/set.rb +55 -0
- data/lib/mongoid/extensions/string.rb +199 -0
- data/lib/mongoid/extensions/symbol.rb +54 -0
- data/lib/mongoid/extensions/time.rb +88 -0
- data/lib/mongoid/extensions/time_with_zone.rb +56 -0
- data/lib/mongoid/extensions/true_class.rb +38 -0
- data/lib/mongoid/factory.rb +46 -0
- data/lib/mongoid/fields.rb +542 -0
- data/lib/mongoid/fields/foreign_key.rb +174 -0
- data/lib/mongoid/fields/localized.rb +73 -0
- data/lib/mongoid/fields/standard.rb +273 -0
- data/lib/mongoid/fields/validators.rb +2 -0
- data/lib/mongoid/fields/validators/macro.rb +92 -0
- data/lib/mongoid/findable.rb +133 -0
- data/lib/mongoid/identity_map.rb +163 -0
- data/lib/mongoid/indexable.rb +147 -0
- data/lib/mongoid/indexable/specification.rb +115 -0
- data/lib/mongoid/indexable/validators/options.rb +103 -0
- data/lib/mongoid/inspectable.rb +59 -0
- data/lib/mongoid/interceptable.rb +265 -0
- data/lib/mongoid/loggable.rb +69 -0
- data/lib/mongoid/matchable.rb +152 -0
- data/lib/mongoid/matchable/all.rb +27 -0
- data/lib/mongoid/matchable/and.rb +30 -0
- data/lib/mongoid/matchable/default.rb +72 -0
- data/lib/mongoid/matchable/exists.rb +23 -0
- data/lib/mongoid/matchable/gt.rb +21 -0
- data/lib/mongoid/matchable/gte.rb +21 -0
- data/lib/mongoid/matchable/in.rb +24 -0
- data/lib/mongoid/matchable/lt.rb +21 -0
- data/lib/mongoid/matchable/lte.rb +21 -0
- data/lib/mongoid/matchable/ne.rb +21 -0
- data/lib/mongoid/matchable/nin.rb +21 -0
- data/lib/mongoid/matchable/or.rb +33 -0
- data/lib/mongoid/matchable/size.rb +21 -0
- data/lib/mongoid/persistable.rb +207 -0
- data/lib/mongoid/persistable/creatable.rb +189 -0
- data/lib/mongoid/persistable/deletable.rb +149 -0
- data/lib/mongoid/persistable/destroyable.rb +55 -0
- data/lib/mongoid/persistable/incrementable.rb +36 -0
- data/lib/mongoid/persistable/logical.rb +38 -0
- data/lib/mongoid/persistable/poppable.rb +39 -0
- data/lib/mongoid/persistable/pullable.rb +55 -0
- data/lib/mongoid/persistable/pushable.rb +62 -0
- data/lib/mongoid/persistable/renamable.rb +35 -0
- data/lib/mongoid/persistable/savable.rb +52 -0
- data/lib/mongoid/persistable/settable.rb +33 -0
- data/lib/mongoid/persistable/unsettable.rb +36 -0
- data/lib/mongoid/persistable/updatable.rb +151 -0
- data/lib/mongoid/persistable/upsertable.rb +55 -0
- data/lib/mongoid/positional.rb +71 -0
- data/lib/mongoid/railtie.rb +156 -0
- data/lib/mongoid/railties/database.rake +97 -0
- data/lib/mongoid/railties/document.rb +12 -0
- data/lib/mongoid/relations.rb +162 -0
- data/lib/mongoid/relations/accessors.rb +299 -0
- data/lib/mongoid/relations/auto_save.rb +106 -0
- data/lib/mongoid/relations/binding.rb +218 -0
- data/lib/mongoid/relations/bindings.rb +9 -0
- data/lib/mongoid/relations/bindings/embedded/in.rb +63 -0
- data/lib/mongoid/relations/bindings/embedded/many.rb +50 -0
- data/lib/mongoid/relations/bindings/embedded/one.rb +55 -0
- data/lib/mongoid/relations/bindings/referenced/in.rb +65 -0
- data/lib/mongoid/relations/bindings/referenced/many.rb +42 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +67 -0
- data/lib/mongoid/relations/bindings/referenced/one.rb +44 -0
- data/lib/mongoid/relations/builder.rb +57 -0
- data/lib/mongoid/relations/builders.rb +104 -0
- data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
- data/lib/mongoid/relations/builders/embedded/many.rb +36 -0
- data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +174 -0
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +126 -0
- data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
- data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +40 -0
- data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
- data/lib/mongoid/relations/cascading.rb +56 -0
- data/lib/mongoid/relations/cascading/delete.rb +44 -0
- data/lib/mongoid/relations/cascading/destroy.rb +43 -0
- data/lib/mongoid/relations/cascading/nullify.rb +35 -0
- data/lib/mongoid/relations/cascading/restrict.rb +39 -0
- data/lib/mongoid/relations/constraint.rb +49 -0
- data/lib/mongoid/relations/conversions.rb +34 -0
- data/lib/mongoid/relations/counter_cache.rb +105 -0
- data/lib/mongoid/relations/cyclic.rb +107 -0
- data/lib/mongoid/relations/embedded/batchable.rb +355 -0
- data/lib/mongoid/relations/embedded/in.rb +231 -0
- data/lib/mongoid/relations/embedded/many.rb +639 -0
- data/lib/mongoid/relations/embedded/one.rb +223 -0
- data/lib/mongoid/relations/macros.rb +356 -0
- data/lib/mongoid/relations/many.rb +208 -0
- data/lib/mongoid/relations/marshalable.rb +32 -0
- data/lib/mongoid/relations/metadata.rb +1174 -0
- data/lib/mongoid/relations/nested_builder.rb +74 -0
- data/lib/mongoid/relations/one.rb +48 -0
- data/lib/mongoid/relations/options.rb +48 -0
- data/lib/mongoid/relations/polymorphic.rb +39 -0
- data/lib/mongoid/relations/proxy.rb +270 -0
- data/lib/mongoid/relations/referenced/in.rb +297 -0
- data/lib/mongoid/relations/referenced/many.rb +787 -0
- data/lib/mongoid/relations/referenced/many_to_many.rb +486 -0
- data/lib/mongoid/relations/referenced/one.rb +290 -0
- data/lib/mongoid/relations/reflections.rb +62 -0
- data/lib/mongoid/relations/synchronization.rb +169 -0
- data/lib/mongoid/relations/targets.rb +2 -0
- data/lib/mongoid/relations/targets/enumerable.rb +473 -0
- data/lib/mongoid/relations/touchable.rb +94 -0
- data/lib/mongoid/reloadable.rb +95 -0
- data/lib/mongoid/scopable.rb +379 -0
- data/lib/mongoid/selectable.rb +59 -0
- data/lib/mongoid/serializable.rb +170 -0
- data/lib/mongoid/sessions.rb +330 -0
- data/lib/mongoid/sessions/factory.rb +129 -0
- data/lib/mongoid/sessions/mongo_uri.rb +93 -0
- data/lib/mongoid/sessions/options.rb +141 -0
- data/lib/mongoid/sessions/validators.rb +2 -0
- data/lib/mongoid/sessions/validators/storage.rb +49 -0
- data/lib/mongoid/shardable.rb +65 -0
- data/lib/mongoid/state.rb +97 -0
- data/lib/mongoid/threaded.rb +383 -0
- data/lib/mongoid/threaded/lifecycle.rb +164 -0
- data/lib/mongoid/timestamps.rb +15 -0
- data/lib/mongoid/timestamps/created.rb +30 -0
- data/lib/mongoid/timestamps/created/short.rb +19 -0
- data/lib/mongoid/timestamps/short.rb +10 -0
- data/lib/mongoid/timestamps/updated.rb +39 -0
- data/lib/mongoid/timestamps/updated/short.rb +19 -0
- data/lib/mongoid/traversable.rb +192 -0
- data/lib/mongoid/unit_of_work.rb +61 -0
- data/lib/mongoid/validatable.rb +180 -0
- data/lib/mongoid/validatable/associated.rb +48 -0
- data/lib/mongoid/validatable/format.rb +20 -0
- data/lib/mongoid/validatable/length.rb +20 -0
- data/lib/mongoid/validatable/localizable.rb +30 -0
- data/lib/mongoid/validatable/macros.rb +94 -0
- data/lib/mongoid/validatable/presence.rb +86 -0
- data/lib/mongoid/validatable/queryable.rb +30 -0
- data/lib/mongoid/validatable/uniqueness.rb +330 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/rack/mongoid.rb +2 -0
- data/lib/rack/mongoid/middleware/identity_map.rb +39 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +76 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +25 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
- data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
- data/lib/rails/generators/mongoid_generator.rb +65 -0
- data/lib/rails/mongoid.rb +180 -0
- data/lib/support/ruby_version.rb +26 -0
- data/spec/app/models/account.rb +28 -0
- data/spec/app/models/acolyte.rb +17 -0
- data/spec/app/models/actor.rb +18 -0
- data/spec/app/models/actress.rb +2 -0
- data/spec/app/models/address.rb +77 -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 +10 -0
- data/spec/app/models/artist.rb +66 -0
- data/spec/app/models/artwork.rb +4 -0
- data/spec/app/models/audio.rb +5 -0
- data/spec/app/models/augmentation.rb +11 -0
- data/spec/app/models/author.rb +4 -0
- data/spec/app/models/band.rb +26 -0
- data/spec/app/models/bar.rb +10 -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 +13 -0
- data/spec/app/models/breed.rb +4 -0
- data/spec/app/models/browser.rb +6 -0
- data/spec/app/models/building.rb +5 -0
- data/spec/app/models/building_address.rb +5 -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 +5 -0
- data/spec/app/models/cookie.rb +6 -0
- data/spec/app/models/country_code.rb +8 -0
- data/spec/app/models/definition.rb +7 -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/dragon.rb +4 -0
- data/spec/app/models/driver.rb +7 -0
- data/spec/app/models/drug.rb +6 -0
- data/spec/app/models/dungeon.rb +4 -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 +5 -0
- data/spec/app/models/fire_hydrant.rb +6 -0
- data/spec/app/models/firefox.rb +4 -0
- data/spec/app/models/fish.rb +7 -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 +19 -0
- data/spec/app/models/ghost.rb +7 -0
- data/spec/app/models/home.rb +4 -0
- data/spec/app/models/house.rb +6 -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 +8 -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 +13 -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/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 +205 -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/pizza.rb +7 -0
- data/spec/app/models/player.rb +35 -0
- data/spec/app/models/post.rb +44 -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 +15 -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 +7 -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/sound.rb +5 -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 +3 -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 +13 -0
- data/spec/app/models/weapon.rb +11 -0
- data/spec/app/models/wiki_page.rb +14 -0
- data/spec/app/models/word.rb +15 -0
- data/spec/app/models/word_origin.rb +11 -0
- data/spec/app/models/writer.rb +11 -0
- data/spec/config/mongoid.yml +38 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +118 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +110 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +48 -0
- data/spec/mongoid/atomic/paths_spec.rb +270 -0
- data/spec/mongoid/atomic_spec.rb +365 -0
- data/spec/mongoid/attributes/nested_spec.rb +4832 -0
- data/spec/mongoid/attributes/readonly_spec.rb +169 -0
- data/spec/mongoid/attributes_spec.rb +1412 -0
- data/spec/mongoid/changeable_spec.rb +1507 -0
- data/spec/mongoid/composable_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 +318 -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 +529 -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 +1843 -0
- data/spec/mongoid/contextual/text_search_spec.rb +207 -0
- data/spec/mongoid/copyable_spec.rb +393 -0
- data/spec/mongoid/criteria/findable_spec.rb +1189 -0
- data/spec/mongoid/criteria/inspectable_spec.rb +27 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +28 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +1063 -0
- data/spec/mongoid/criteria/scopable_spec.rb +391 -0
- data/spec/mongoid/criteria_spec.rb +3821 -0
- data/spec/mongoid/document_spec.rb +1205 -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/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 +357 -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/extensions_spec.rb +15 -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 +1229 -0
- data/spec/mongoid/findable_spec.rb +342 -0
- data/spec/mongoid/identity_map_spec.rb +564 -0
- data/spec/mongoid/indexable/specification_spec.rb +87 -0
- data/spec/mongoid/indexable_spec.rb +504 -0
- data/spec/mongoid/inspectable_spec.rb +49 -0
- data/spec/mongoid/interceptable_spec.rb +1564 -0
- data/spec/mongoid/loggable_spec.rb +21 -0
- data/spec/mongoid/matchable/all_spec.rb +31 -0
- data/spec/mongoid/matchable/and_spec.rb +162 -0
- data/spec/mongoid/matchable/default_spec.rb +130 -0
- data/spec/mongoid/matchable/exists_spec.rb +57 -0
- data/spec/mongoid/matchable/gt_spec.rb +75 -0
- data/spec/mongoid/matchable/gte_spec.rb +74 -0
- data/spec/mongoid/matchable/in_spec.rb +25 -0
- data/spec/mongoid/matchable/lt_spec.rb +74 -0
- data/spec/mongoid/matchable/lte_spec.rb +74 -0
- data/spec/mongoid/matchable/ne_spec.rb +25 -0
- data/spec/mongoid/matchable/nin_spec.rb +25 -0
- data/spec/mongoid/matchable/or_spec.rb +106 -0
- data/spec/mongoid/matchable/size_spec.rb +25 -0
- data/spec/mongoid/matchable_spec.rb +532 -0
- data/spec/mongoid/persistable/creatable_spec.rb +512 -0
- data/spec/mongoid/persistable/deletable_spec.rb +205 -0
- data/spec/mongoid/persistable/destroyable_spec.rb +148 -0
- data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
- data/spec/mongoid/persistable/logical_spec.rb +143 -0
- data/spec/mongoid/persistable/poppable_spec.rb +115 -0
- data/spec/mongoid/persistable/pullable_spec.rb +228 -0
- data/spec/mongoid/persistable/pushable_spec.rb +258 -0
- data/spec/mongoid/persistable/renamable_spec.rb +135 -0
- data/spec/mongoid/persistable/savable_spec.rb +432 -0
- data/spec/mongoid/persistable/settable_spec.rb +139 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
- data/spec/mongoid/persistable/updatable_spec.rb +522 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
- data/spec/mongoid/persistable_spec.rb +206 -0
- data/spec/mongoid/positional_spec.rb +227 -0
- data/spec/mongoid/railties/document_spec.rb +24 -0
- data/spec/mongoid/relations/accessors_spec.rb +736 -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 +579 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +3781 -0
- data/spec/mongoid/relations/embedded/one_spec.rb +1014 -0
- data/spec/mongoid/relations/macros_spec.rb +613 -0
- data/spec/mongoid/relations/metadata_spec.rb +1917 -0
- data/spec/mongoid/relations/options_spec.rb +35 -0
- data/spec/mongoid/relations/polymorphic_spec.rb +128 -0
- data/spec/mongoid/relations/proxy_spec.rb +48 -0
- data/spec/mongoid/relations/referenced/in_spec.rb +1435 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +3546 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3556 -0
- data/spec/mongoid/relations/referenced/one_spec.rb +1289 -0
- data/spec/mongoid/relations/reflections_spec.rb +101 -0
- data/spec/mongoid/relations/synchronization_spec.rb +449 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
- data/spec/mongoid/relations/touchable_spec.rb +296 -0
- data/spec/mongoid/relations_spec.rb +188 -0
- data/spec/mongoid/reloadable_spec.rb +305 -0
- data/spec/mongoid/scopable_spec.rb +926 -0
- data/spec/mongoid/selectable_spec.rb +134 -0
- data/spec/mongoid/serializable_spec.rb +862 -0
- data/spec/mongoid/sessions/factory_spec.rb +312 -0
- data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
- data/spec/mongoid/sessions/options_spec.rb +71 -0
- data/spec/mongoid/sessions_spec.rb +1078 -0
- data/spec/mongoid/shardable_spec.rb +61 -0
- data/spec/mongoid/state_spec.rb +102 -0
- data/spec/mongoid/threaded_spec.rb +258 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
- data/spec/mongoid/timestamps/created_spec.rb +44 -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/traversable_spec.rb +244 -0
- data/spec/mongoid/unit_of_work_spec.rb +196 -0
- data/spec/mongoid/validatable/associated_spec.rb +183 -0
- data/spec/mongoid/validatable/format_spec.rb +83 -0
- data/spec/mongoid/validatable/length_spec.rb +119 -0
- data/spec/mongoid/validatable/numericality_spec.rb +30 -0
- data/spec/mongoid/validatable/presence_spec.rb +511 -0
- data/spec/mongoid/validatable/uniqueness_spec.rb +2305 -0
- data/spec/mongoid/validatable_spec.rb +309 -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 +103 -0
- 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
|