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