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