mongoid 3.1.4 → 3.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/lib/mongoid/contextual.rb +3 -0
- data/lib/mongoid/criteria.rb +10 -2
- data/lib/mongoid/document.rb +1 -1
- data/lib/mongoid/paranoia.rb +4 -0
- data/lib/mongoid/persistence/upsertion.rb +1 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +16 -2
- data/lib/mongoid/relations/macros.rb +1 -1
- data/lib/mongoid/relations/one.rb +12 -0
- data/lib/mongoid/relations/referenced/in.rb +18 -1
- data/lib/mongoid/relations/referenced/many_to_many.rb +2 -2
- data/lib/mongoid/validations.rb +1 -1
- data/lib/mongoid/validations/localizable.rb +1 -1
- data/lib/mongoid/validations/presence.rb +1 -1
- data/lib/mongoid/validations/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/support/ruby_version.rb +1 -1
- data/spec/app/models/account.rb +32 -0
- data/spec/app/models/acolyte.rb +16 -0
- data/spec/app/models/actor.rb +19 -0
- data/spec/app/models/actor_observer.rb +15 -0
- data/spec/app/models/actress.rb +2 -0
- data/spec/app/models/address.rb +72 -0
- data/spec/app/models/address_component.rb +5 -0
- data/spec/app/models/address_number.rb +6 -0
- data/spec/app/models/agency.rb +5 -0
- data/spec/app/models/agent.rb +12 -0
- data/spec/app/models/album.rb +14 -0
- data/spec/app/models/alert.rb +5 -0
- data/spec/app/models/animal.rb +25 -0
- data/spec/app/models/answer.rb +4 -0
- data/spec/app/models/appointment.rb +7 -0
- data/spec/app/models/article.rb +13 -0
- data/spec/app/models/artist.rb +66 -0
- data/spec/app/models/artwork.rb +4 -0
- data/spec/app/models/augmentation.rb +11 -0
- data/spec/app/models/author.rb +6 -0
- data/spec/app/models/band.rb +25 -0
- data/spec/app/models/bar.rb +9 -0
- data/spec/app/models/basic.rb +6 -0
- data/spec/app/models/bed.rb +1 -0
- data/spec/app/models/big_palette.rb +2 -0
- data/spec/app/models/birthday.rb +13 -0
- data/spec/app/models/book.rb +12 -0
- data/spec/app/models/breed.rb +4 -0
- data/spec/app/models/browser.rb +6 -0
- data/spec/app/models/building.rb +7 -0
- data/spec/app/models/building_address.rb +7 -0
- data/spec/app/models/bus.rb +7 -0
- data/spec/app/models/business.rb +5 -0
- data/spec/app/models/callback_recorder.rb +25 -0
- data/spec/app/models/callback_test.rb +9 -0
- data/spec/app/models/canvas.rb +25 -0
- data/spec/app/models/car.rb +1 -0
- data/spec/app/models/cat.rb +8 -0
- data/spec/app/models/category.rb +8 -0
- data/spec/app/models/child.rb +4 -0
- data/spec/app/models/child_doc.rb +22 -0
- data/spec/app/models/church.rb +4 -0
- data/spec/app/models/circle.rb +3 -0
- data/spec/app/models/circuit.rb +4 -0
- data/spec/app/models/circus.rb +7 -0
- data/spec/app/models/code.rb +5 -0
- data/spec/app/models/comment.rb +16 -0
- data/spec/app/models/contractor.rb +7 -0
- data/spec/app/models/cookie.rb +6 -0
- data/spec/app/models/country_code.rb +8 -0
- data/spec/app/models/definition.rb +8 -0
- data/spec/app/models/description.rb +11 -0
- data/spec/app/models/dictionary.rb +10 -0
- data/spec/app/models/division.rb +10 -0
- data/spec/app/models/doctor.rb +12 -0
- data/spec/app/models/dog.rb +7 -0
- data/spec/app/models/dokument.rb +5 -0
- data/spec/app/models/driver.rb +7 -0
- data/spec/app/models/drug.rb +8 -0
- data/spec/app/models/email.rb +6 -0
- data/spec/app/models/employer.rb +5 -0
- data/spec/app/models/entry.rb +6 -0
- data/spec/app/models/eraser.rb +1 -0
- data/spec/app/models/event.rb +22 -0
- data/spec/app/models/exhibition.rb +4 -0
- data/spec/app/models/exhibitor.rb +5 -0
- data/spec/app/models/eye.rb +9 -0
- data/spec/app/models/eye_bowl.rb +9 -0
- data/spec/app/models/face.rb +8 -0
- data/spec/app/models/favorite.rb +6 -0
- data/spec/app/models/filesystem.rb +4 -0
- data/spec/app/models/fire_hydrant.rb +6 -0
- data/spec/app/models/firefox.rb +4 -0
- data/spec/app/models/fish.rb +8 -0
- data/spec/app/models/folder.rb +7 -0
- data/spec/app/models/folder_item.rb +9 -0
- data/spec/app/models/fruits.rb +28 -0
- data/spec/app/models/game.rb +21 -0
- data/spec/app/models/ghost.rb +7 -0
- data/spec/app/models/home.rb +4 -0
- data/spec/app/models/house.rb +8 -0
- data/spec/app/models/html_writer.rb +3 -0
- data/spec/app/models/image.rb +22 -0
- data/spec/app/models/implant.rb +16 -0
- data/spec/app/models/item.rb +12 -0
- data/spec/app/models/jar.rb +7 -0
- data/spec/app/models/label.rb +40 -0
- data/spec/app/models/language.rb +5 -0
- data/spec/app/models/lat_lng.rb +15 -0
- data/spec/app/models/league.rb +11 -0
- data/spec/app/models/learner.rb +2 -0
- data/spec/app/models/line_item.rb +6 -0
- data/spec/app/models/location.rb +8 -0
- data/spec/app/models/login.rb +8 -0
- data/spec/app/models/manufacturer.rb +7 -0
- data/spec/app/models/meat.rb +4 -0
- data/spec/app/models/membership.rb +4 -0
- data/spec/app/models/mixed_drink.rb +4 -0
- data/spec/app/models/movie.rb +12 -0
- data/spec/app/models/my_hash.rb +2 -0
- data/spec/app/models/name.rb +23 -0
- data/spec/app/models/node.rb +5 -0
- data/spec/app/models/note.rb +12 -0
- data/spec/app/models/ordered_post.rb +6 -0
- data/spec/app/models/ordered_preference.rb +6 -0
- data/spec/app/models/oscar.rb +15 -0
- data/spec/app/models/override.rb +16 -0
- data/spec/app/models/ownable.rb +6 -0
- data/spec/app/models/owner.rb +6 -0
- data/spec/app/models/pack.rb +3 -0
- data/spec/app/models/page.rb +5 -0
- data/spec/app/models/page_question.rb +4 -0
- data/spec/app/models/palette.rb +7 -0
- data/spec/app/models/paranoid_phone.rb +25 -0
- data/spec/app/models/paranoid_post.rb +36 -0
- data/spec/app/models/parent.rb +5 -0
- data/spec/app/models/parent_doc.rb +6 -0
- data/spec/app/models/passport.rb +5 -0
- data/spec/app/models/patient.rb +9 -0
- data/spec/app/models/pdf_writer.rb +3 -0
- data/spec/app/models/pencil.rb +1 -0
- data/spec/app/models/person.rb +201 -0
- data/spec/app/models/pet.rb +23 -0
- data/spec/app/models/pet_owner.rb +6 -0
- data/spec/app/models/phone.rb +11 -0
- data/spec/app/models/phone_observer.rb +6 -0
- data/spec/app/models/pizza.rb +7 -0
- data/spec/app/models/player.rb +35 -0
- data/spec/app/models/post.rb +43 -0
- data/spec/app/models/powerup.rb +11 -0
- data/spec/app/models/preference.rb +9 -0
- data/spec/app/models/princess.rb +8 -0
- data/spec/app/models/product.rb +17 -0
- data/spec/app/models/profile.rb +5 -0
- data/spec/app/models/pronunciation.rb +5 -0
- data/spec/app/models/purchase.rb +4 -0
- data/spec/app/models/question.rb +8 -0
- data/spec/app/models/quiz.rb +10 -0
- data/spec/app/models/rating.rb +8 -0
- data/spec/app/models/record.rb +46 -0
- data/spec/app/models/registry.rb +4 -0
- data/spec/app/models/role.rb +7 -0
- data/spec/app/models/root_category.rb +4 -0
- data/spec/app/models/sandwich.rb +4 -0
- data/spec/app/models/scheduler.rb +7 -0
- data/spec/app/models/seo.rb +7 -0
- data/spec/app/models/series.rb +4 -0
- data/spec/app/models/server.rb +13 -0
- data/spec/app/models/service.rb +22 -0
- data/spec/app/models/shape.rb +12 -0
- data/spec/app/models/shelf.rb +5 -0
- data/spec/app/models/shipping_container.rb +5 -0
- data/spec/app/models/shipping_pack.rb +3 -0
- data/spec/app/models/shop.rb +6 -0
- data/spec/app/models/short_agent.rb +4 -0
- data/spec/app/models/short_quiz.rb +5 -0
- data/spec/app/models/slave.rb +6 -0
- data/spec/app/models/song.rb +8 -0
- data/spec/app/models/square.rb +4 -0
- data/spec/app/models/strategy.rb +3 -0
- data/spec/app/models/sub_item.rb +3 -0
- data/spec/app/models/subscription.rb +4 -0
- data/spec/app/models/survey.rb +5 -0
- data/spec/app/models/symptom.rb +6 -0
- data/spec/app/models/tag.rb +8 -0
- data/spec/app/models/target.rb +5 -0
- data/spec/app/models/template.rb +5 -0
- data/spec/app/models/thing.rb +9 -0
- data/spec/app/models/title.rb +4 -0
- data/spec/app/models/tool.rb +8 -0
- data/spec/app/models/topping.rb +5 -0
- data/spec/app/models/track.rb +38 -0
- data/spec/app/models/translation.rb +5 -0
- data/spec/app/models/tree.rb +9 -0
- data/spec/app/models/truck.rb +3 -0
- data/spec/app/models/user.rb +21 -0
- data/spec/app/models/user_account.rb +10 -0
- data/spec/app/models/validation_callback.rb +10 -0
- data/spec/app/models/vehicle.rb +11 -0
- data/spec/app/models/version.rb +5 -0
- data/spec/app/models/vet_visit.rb +5 -0
- data/spec/app/models/video.rb +17 -0
- data/spec/app/models/video_game.rb +1 -0
- data/spec/app/models/weapon.rb +11 -0
- data/spec/app/models/wiki_page.rb +17 -0
- data/spec/app/models/word.rb +12 -0
- data/spec/app/models/word_origin.rb +11 -0
- data/spec/app/models/writer.rb +11 -0
- data/spec/config/mongoid.yml +40 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +159 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +152 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +106 -0
- data/spec/mongoid/atomic/paths_spec.rb +270 -0
- data/spec/mongoid/atomic/positionable_spec.rb +227 -0
- data/spec/mongoid/atomic_spec.rb +365 -0
- data/spec/mongoid/attributes/processing_spec.rb +149 -0
- data/spec/mongoid/attributes/readonly_spec.rb +169 -0
- data/spec/mongoid/attributes_spec.rb +1705 -0
- data/spec/mongoid/callbacks_spec.rb +1564 -0
- data/spec/mongoid/components_spec.rb +24 -0
- data/spec/mongoid/config/environment_spec.rb +83 -0
- data/spec/mongoid/config/options_spec.rb +56 -0
- data/spec/mongoid/config_spec.rb +334 -0
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +293 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +455 -0
- data/spec/mongoid/contextual/atomic_spec.rb +525 -0
- data/spec/mongoid/contextual/find_and_modify_spec.rb +220 -0
- data/spec/mongoid/contextual/geo_near_spec.rb +405 -0
- data/spec/mongoid/contextual/map_reduce_spec.rb +464 -0
- data/spec/mongoid/contextual/memory_spec.rb +1236 -0
- data/spec/mongoid/contextual/mongo_spec.rb +1757 -0
- data/spec/mongoid/copyable_spec.rb +393 -0
- data/spec/mongoid/criteria_spec.rb +5140 -0
- data/spec/mongoid/criterion/destructive_spec.rb +101 -0
- data/spec/mongoid/criterion/inspection_spec.rb +27 -0
- data/spec/mongoid/criterion/marshalable_spec.rb +28 -0
- data/spec/mongoid/criterion/modifiable_spec.rb +409 -0
- data/spec/mongoid/criterion/modification_spec.rb +402 -0
- data/spec/mongoid/criterion/scoping_spec.rb +391 -0
- data/spec/mongoid/dirty_spec.rb +1508 -0
- data/spec/mongoid/document_spec.rb +1146 -0
- data/spec/mongoid/equality_spec.rb +241 -0
- data/spec/mongoid/errors/ambiguous_relationship_spec.rb +29 -0
- data/spec/mongoid/errors/callback_spec.rb +29 -0
- data/spec/mongoid/errors/delete_restriction_spec.rb +29 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +104 -0
- data/spec/mongoid/errors/eager_load_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_collection_spec.rb +36 -0
- data/spec/mongoid/errors/invalid_config_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_spec.rb +37 -0
- data/spec/mongoid/errors/invalid_find_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_includes_spec.rb +40 -0
- data/spec/mongoid/errors/invalid_index_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_path_spec.rb +23 -0
- data/spec/mongoid/errors/invalid_scope_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +17 -0
- data/spec/mongoid/errors/invalid_storage_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_time_spec.rb +29 -0
- data/spec/mongoid/errors/inverse_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_relations_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_session_configuration_spec.rb +29 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +48 -0
- data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/no_environment_spec.rb +29 -0
- data/spec/mongoid/errors/no_map_reduce_output_spec.rb +29 -0
- data/spec/mongoid/errors/no_metadata_spec.rb +23 -0
- data/spec/mongoid/errors/no_parent_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_config_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_database_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_hosts_spec.rb +29 -0
- data/spec/mongoid/errors/no_sessions_config_spec.rb +29 -0
- data/spec/mongoid/errors/readonly_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/scope_overwrite_spec.rb +29 -0
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +29 -0
- data/spec/mongoid/errors/unknown_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/unsaved_document_spec.rb +37 -0
- data/spec/mongoid/errors/unsupported_javascript_spec.rb +29 -0
- data/spec/mongoid/errors/validations_spec.rb +45 -0
- data/spec/mongoid/errors/versioning_not_on_root_spec.rb +29 -0
- data/spec/mongoid/extensions/array_spec.rb +638 -0
- data/spec/mongoid/extensions/big_decimal_spec.rb +104 -0
- data/spec/mongoid/extensions/binary_spec.rb +60 -0
- data/spec/mongoid/extensions/boolean_spec.rb +135 -0
- data/spec/mongoid/extensions/date_spec.rb +235 -0
- data/spec/mongoid/extensions/date_time_spec.rb +155 -0
- data/spec/mongoid/extensions/false_class_spec.rb +42 -0
- data/spec/mongoid/extensions/float_spec.rb +133 -0
- data/spec/mongoid/extensions/hash_spec.rb +333 -0
- data/spec/mongoid/extensions/integer_spec.rb +136 -0
- data/spec/mongoid/extensions/module_spec.rb +42 -0
- data/spec/mongoid/extensions/nil_class_spec.rb +11 -0
- data/spec/mongoid/extensions/object_id_spec.rb +946 -0
- data/spec/mongoid/extensions/object_spec.rb +292 -0
- data/spec/mongoid/extensions/range_spec.rb +105 -0
- data/spec/mongoid/extensions/regexp_spec.rb +47 -0
- data/spec/mongoid/extensions/set_spec.rb +33 -0
- data/spec/mongoid/extensions/string_spec.rb +368 -0
- data/spec/mongoid/extensions/symbol_spec.rb +76 -0
- data/spec/mongoid/extensions/time_spec.rb +467 -0
- data/spec/mongoid/extensions/time_with_zone_spec.rb +405 -0
- data/spec/mongoid/extensions/true_class_spec.rb +42 -0
- data/spec/mongoid/factory_spec.rb +185 -0
- data/spec/mongoid/fields/foreign_key_spec.rb +694 -0
- data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +184 -0
- data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +201 -0
- data/spec/mongoid/fields/localized_spec.rb +386 -0
- data/spec/mongoid/fields/standard_spec.rb +166 -0
- data/spec/mongoid/fields_spec.rb +1253 -0
- data/spec/mongoid/finders_spec.rb +321 -0
- data/spec/mongoid/hierarchy_spec.rb +244 -0
- data/spec/mongoid/identity_map_spec.rb +564 -0
- data/spec/mongoid/indexes_spec.rb +404 -0
- data/spec/mongoid/inspection_spec.rb +57 -0
- data/spec/mongoid/json_spec.rb +33 -0
- data/spec/mongoid/loggable_spec.rb +21 -0
- data/spec/mongoid/matchers/all_spec.rb +31 -0
- data/spec/mongoid/matchers/and_spec.rb +162 -0
- data/spec/mongoid/matchers/default_spec.rb +130 -0
- data/spec/mongoid/matchers/exists_spec.rb +57 -0
- data/spec/mongoid/matchers/gt_spec.rb +74 -0
- data/spec/mongoid/matchers/gte_spec.rb +74 -0
- data/spec/mongoid/matchers/in_spec.rb +25 -0
- data/spec/mongoid/matchers/lt_spec.rb +74 -0
- data/spec/mongoid/matchers/lte_spec.rb +74 -0
- data/spec/mongoid/matchers/ne_spec.rb +25 -0
- data/spec/mongoid/matchers/nin_spec.rb +25 -0
- data/spec/mongoid/matchers/or_spec.rb +106 -0
- data/spec/mongoid/matchers/size_spec.rb +25 -0
- data/spec/mongoid/matchers_spec.rb +532 -0
- data/spec/mongoid/multi_parameter_attributes_spec.rb +128 -0
- data/spec/mongoid/nested_attributes_spec.rb +4945 -0
- data/spec/mongoid/observer_spec.rb +290 -0
- data/spec/mongoid/paranoia_spec.rb +759 -0
- data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +262 -0
- data/spec/mongoid/persistence/atomic/bit_spec.rb +88 -0
- data/spec/mongoid/persistence/atomic/inc_spec.rb +133 -0
- data/spec/mongoid/persistence/atomic/pop_spec.rb +111 -0
- data/spec/mongoid/persistence/atomic/pull_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/pull_spec.rb +80 -0
- data/spec/mongoid/persistence/atomic/push_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/push_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/rename_spec.rb +42 -0
- data/spec/mongoid/persistence/atomic/sets_spec.rb +154 -0
- data/spec/mongoid/persistence/atomic/unset_spec.rb +65 -0
- data/spec/mongoid/persistence/atomic_spec.rb +216 -0
- data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +191 -0
- data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +8 -0
- data/spec/mongoid/persistence/operations/insert_spec.rb +149 -0
- data/spec/mongoid/persistence/operations/remove_spec.rb +113 -0
- data/spec/mongoid/persistence/operations/update_spec.rb +141 -0
- data/spec/mongoid/persistence/operations/upsert_spec.rb +59 -0
- data/spec/mongoid/persistence/operations_spec.rb +313 -0
- data/spec/mongoid/persistence_spec.rb +2279 -0
- data/spec/mongoid/railties/document_spec.rb +24 -0
- data/spec/mongoid/relations/accessors_spec.rb +844 -0
- data/spec/mongoid/relations/auto_save_spec.rb +261 -0
- data/spec/mongoid/relations/bindings/embedded/in_spec.rb +171 -0
- data/spec/mongoid/relations/bindings/embedded/many_spec.rb +54 -0
- data/spec/mongoid/relations/bindings/embedded/one_spec.rb +77 -0
- data/spec/mongoid/relations/bindings/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/bindings/referenced/many_spec.rb +153 -0
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/bindings/referenced/one_spec.rb +131 -0
- data/spec/mongoid/relations/builders/embedded/in_spec.rb +34 -0
- data/spec/mongoid/relations/builders/embedded/many_spec.rb +132 -0
- data/spec/mongoid/relations/builders/embedded/one_spec.rb +99 -0
- data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +234 -0
- data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +250 -0
- data/spec/mongoid/relations/builders/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/builders/referenced/many_spec.rb +137 -0
- data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/builders/referenced/one_spec.rb +124 -0
- data/spec/mongoid/relations/builders_spec.rb +226 -0
- data/spec/mongoid/relations/cascading/delete_spec.rb +101 -0
- data/spec/mongoid/relations/cascading/destroy_spec.rb +47 -0
- data/spec/mongoid/relations/cascading/nullify_spec.rb +32 -0
- data/spec/mongoid/relations/cascading/restrict_spec.rb +68 -0
- data/spec/mongoid/relations/cascading_spec.rb +355 -0
- data/spec/mongoid/relations/constraint_spec.rb +74 -0
- data/spec/mongoid/relations/conversions_spec.rb +126 -0
- data/spec/mongoid/relations/counter_cache_spec.rb +205 -0
- data/spec/mongoid/relations/cyclic_spec.rb +156 -0
- data/spec/mongoid/relations/embedded/dirty_spec.rb +65 -0
- data/spec/mongoid/relations/embedded/in_spec.rb +580 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +3841 -0
- data/spec/mongoid/relations/embedded/one_spec.rb +1055 -0
- data/spec/mongoid/relations/macros_spec.rb +625 -0
- data/spec/mongoid/relations/metadata_spec.rb +2030 -0
- data/spec/mongoid/relations/options_spec.rb +35 -0
- data/spec/mongoid/relations/polymorphic_spec.rb +132 -0
- data/spec/mongoid/relations/proxy_spec.rb +48 -0
- data/spec/mongoid/relations/referenced/in_spec.rb +1501 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +3632 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3561 -0
- data/spec/mongoid/relations/referenced/one_spec.rb +1331 -0
- data/spec/mongoid/relations/reflections_spec.rb +101 -0
- data/spec/mongoid/relations/synchronization_spec.rb +453 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
- data/spec/mongoid/relations_spec.rb +188 -0
- data/spec/mongoid/reloading_spec.rb +305 -0
- data/spec/mongoid/scoping_spec.rb +978 -0
- data/spec/mongoid/serialization_spec.rb +833 -0
- data/spec/mongoid/sessions/factory_spec.rb +312 -0
- data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
- data/spec/mongoid/sessions_spec.rb +1111 -0
- data/spec/mongoid/sharding_spec.rb +61 -0
- data/spec/mongoid/state_spec.rb +102 -0
- data/spec/mongoid/threaded_spec.rb +296 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
- data/spec/mongoid/timestamps/created_spec.rb +44 -0
- data/spec/mongoid/timestamps/timeless_spec.rb +130 -0
- data/spec/mongoid/timestamps/updated/short_spec.rb +90 -0
- data/spec/mongoid/timestamps/updated_spec.rb +86 -0
- data/spec/mongoid/timestamps_spec.rb +112 -0
- data/spec/mongoid/unit_of_work_spec.rb +196 -0
- data/spec/mongoid/validations/associated_spec.rb +183 -0
- data/spec/mongoid/validations/format_spec.rb +83 -0
- data/spec/mongoid/validations/length_spec.rb +223 -0
- data/spec/mongoid/validations/numericality_spec.rb +30 -0
- data/spec/mongoid/validations/presence_spec.rb +592 -0
- data/spec/mongoid/validations/uniqueness_spec.rb +2399 -0
- data/spec/mongoid/validations_spec.rb +309 -0
- data/spec/mongoid/versioning_spec.rb +540 -0
- data/spec/mongoid_spec.rb +74 -0
- data/spec/rack/mongoid/middleware/identity_map_spec.rb +72 -0
- data/spec/rails/mongoid_spec.rb +462 -0
- data/spec/spec_helper.rb +93 -0
- metadata +826 -6
|
@@ -0,0 +1,1757 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Contextual::Mongo do
|
|
4
|
+
|
|
5
|
+
[ :blank?, :empty? ].each do |method|
|
|
6
|
+
|
|
7
|
+
describe "##{method}" do
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
Band.create(name: "Depeche Mode")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "when the count is zero" do
|
|
14
|
+
|
|
15
|
+
let(:criteria) do
|
|
16
|
+
Band.where(name: "New Order")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:context) do
|
|
20
|
+
described_class.new(criteria)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns true" do
|
|
24
|
+
context.send(method).should be_true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "when the count is greater than zero" do
|
|
29
|
+
|
|
30
|
+
let(:criteria) do
|
|
31
|
+
Band.where(name: "Depeche Mode")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
let(:context) do
|
|
35
|
+
described_class.new(criteria)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "returns false" do
|
|
39
|
+
context.send(method).should be_false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "#cached?" do
|
|
46
|
+
|
|
47
|
+
context "when the criteria is cached" do
|
|
48
|
+
|
|
49
|
+
let(:criteria) do
|
|
50
|
+
Band.all.cache
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
let(:context) do
|
|
54
|
+
described_class.new(criteria)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "returns true" do
|
|
58
|
+
context.should be_cached
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "when the criteria is not cached" do
|
|
63
|
+
|
|
64
|
+
let(:criteria) do
|
|
65
|
+
Band.all
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
let(:context) do
|
|
69
|
+
described_class.new(criteria)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "returns false" do
|
|
73
|
+
context.should_not be_cached
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#count" do
|
|
79
|
+
|
|
80
|
+
let!(:depeche) do
|
|
81
|
+
Band.create(name: "Depeche Mode")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
let!(:new_order) do
|
|
85
|
+
Band.create(name: "New Order")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
let(:criteria) do
|
|
89
|
+
Band.where(name: "Depeche Mode")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when no arguments are provided" do
|
|
93
|
+
|
|
94
|
+
let(:context) do
|
|
95
|
+
described_class.new(criteria)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "returns the number of documents that match" do
|
|
99
|
+
context.count.should eq(1)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "when context is cached" do
|
|
104
|
+
|
|
105
|
+
let(:context) do
|
|
106
|
+
described_class.new(criteria.cache)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
before do
|
|
110
|
+
context.query.should_receive(:count).once.and_return(1)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "returns the count cached value after first call" do
|
|
114
|
+
2.times { context.count.should eq(1) }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "when provided a document" do
|
|
119
|
+
|
|
120
|
+
let(:context) do
|
|
121
|
+
described_class.new(criteria)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
let(:count) do
|
|
125
|
+
context.count(depeche)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "returns the number of documents that match" do
|
|
129
|
+
count.should eq(1)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "when provided a block" do
|
|
134
|
+
|
|
135
|
+
let(:context) do
|
|
136
|
+
described_class.new(criteria)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
let(:count) do
|
|
140
|
+
context.count do |doc|
|
|
141
|
+
doc.likes.nil?
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "returns the number of documents that match" do
|
|
146
|
+
count.should eq(1)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
context "and a limit true" do
|
|
150
|
+
|
|
151
|
+
before do
|
|
152
|
+
2.times { Band.create(name: "Depeche Mode", likes: 1) }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
let(:count) do
|
|
156
|
+
context.count(true) do |doc|
|
|
157
|
+
doc.likes.nil?
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "returns the number of documents that match" do
|
|
162
|
+
count.should eq(1)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
context "when provided limit true" do
|
|
168
|
+
|
|
169
|
+
before do
|
|
170
|
+
2.times { Band.create(name: "Depeche Mode") }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
let(:context) do
|
|
174
|
+
described_class.new(criteria.limit(2))
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
let(:count) do
|
|
178
|
+
context.count(true)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "returns the number of documents that match" do
|
|
182
|
+
count.should eq(2)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
[ :delete, :delete_all ].each do |method|
|
|
188
|
+
|
|
189
|
+
describe "##{method}" do
|
|
190
|
+
|
|
191
|
+
let!(:depeche_mode) do
|
|
192
|
+
Band.create(name: "Depeche Mode")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
let!(:new_order) do
|
|
196
|
+
Band.create(name: "New Order")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context "when the selector is contraining" do
|
|
200
|
+
|
|
201
|
+
let(:criteria) do
|
|
202
|
+
Band.where(name: "Depeche Mode")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
let(:context) do
|
|
206
|
+
described_class.new(criteria)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
let!(:deleted) do
|
|
210
|
+
context.send(method)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "deletes the matching documents" do
|
|
214
|
+
Band.find(new_order.id).should eq(new_order)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "deletes the correct number of documents" do
|
|
218
|
+
Band.count.should eq(1)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "returns the number of documents deleted" do
|
|
222
|
+
deleted.should eq(1)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
context "when the selector is not contraining" do
|
|
227
|
+
|
|
228
|
+
let(:criteria) do
|
|
229
|
+
Band.all
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
let(:context) do
|
|
233
|
+
described_class.new(criteria)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
before do
|
|
237
|
+
context.send(method)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "deletes all the documents" do
|
|
241
|
+
Band.count.should eq(0)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
[ :destroy, :destroy_all ].each do |method|
|
|
248
|
+
|
|
249
|
+
describe "##{method}" do
|
|
250
|
+
|
|
251
|
+
let!(:depeche_mode) do
|
|
252
|
+
Band.create(name: "Depeche Mode")
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
let!(:new_order) do
|
|
256
|
+
Band.create(name: "New Order")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
context "when the selector is contraining" do
|
|
260
|
+
|
|
261
|
+
let(:criteria) do
|
|
262
|
+
Band.where(name: "Depeche Mode")
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
let(:context) do
|
|
266
|
+
described_class.new(criteria)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
let!(:destroyed) do
|
|
270
|
+
context.send(method)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "destroys the matching documents" do
|
|
274
|
+
Band.find(new_order.id).should eq(new_order)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "destroys the correct number of documents" do
|
|
278
|
+
Band.count.should eq(1)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "returns the number of documents destroyed" do
|
|
282
|
+
destroyed.should eq(1)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context "when the selector is not contraining" do
|
|
287
|
+
|
|
288
|
+
let(:criteria) do
|
|
289
|
+
Band.all
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
let(:context) do
|
|
293
|
+
described_class.new(criteria)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
before do
|
|
297
|
+
context.send(method)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it "destroys all the documents" do
|
|
301
|
+
Band.count.should eq(0)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
describe "#distinct" do
|
|
308
|
+
|
|
309
|
+
before do
|
|
310
|
+
Band.create(name: "Depeche Mode", years: 30)
|
|
311
|
+
Band.create(name: "New Order", years: 25)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context "when limiting the result set" do
|
|
315
|
+
|
|
316
|
+
let(:criteria) do
|
|
317
|
+
Band.where(name: "Depeche Mode")
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
let(:context) do
|
|
321
|
+
described_class.new(criteria)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it "returns the distinct matching fields" do
|
|
325
|
+
context.distinct(:name).should eq([ "Depeche Mode" ])
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
context "when not limiting the result set" do
|
|
330
|
+
|
|
331
|
+
let(:criteria) do
|
|
332
|
+
Band.criteria
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
let(:context) do
|
|
336
|
+
described_class.new(criteria)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "returns the distinct field values" do
|
|
340
|
+
context.distinct(:name).should eq([ "Depeche Mode", "New Order" ])
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
context "when providing an aliased field" do
|
|
345
|
+
|
|
346
|
+
let(:criteria) do
|
|
347
|
+
Band.criteria
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
let(:context) do
|
|
351
|
+
described_class.new(criteria)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it "returns the distinct field values" do
|
|
355
|
+
context.distinct(:years).should eq([ 30, 25 ])
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe "#each" do
|
|
361
|
+
|
|
362
|
+
before do
|
|
363
|
+
Band.create(name: "Depeche Mode")
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
let(:criteria) do
|
|
367
|
+
Band.where(name: "Depeche Mode")
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
let(:context) do
|
|
371
|
+
described_class.new(criteria)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
context "when providing a block" do
|
|
375
|
+
|
|
376
|
+
it "yields mongoid documents to the block" do
|
|
377
|
+
context.each do |doc|
|
|
378
|
+
doc.should be_a(Mongoid::Document)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
it "iterates over the matching documents" do
|
|
383
|
+
context.each do |doc|
|
|
384
|
+
doc.name.should eq("Depeche Mode")
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
it "returns self" do
|
|
389
|
+
context.each{}.should be(context)
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
context "when no block is provided" do
|
|
394
|
+
|
|
395
|
+
let(:enum) do
|
|
396
|
+
context.each
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "returns an enumerator" do
|
|
400
|
+
enum.should be_a(Enumerator)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
context "when iterating over the enumerator" do
|
|
404
|
+
|
|
405
|
+
context "when iterating with each" do
|
|
406
|
+
|
|
407
|
+
it "yields mongoid documents to the block" do
|
|
408
|
+
enum.each do |doc|
|
|
409
|
+
doc.should be_a(Mongoid::Document)
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
context "when iterating with next" do
|
|
415
|
+
|
|
416
|
+
it "yields mongoid documents" do
|
|
417
|
+
enum.next.should be_a(Mongoid::Document)
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
describe "#eager_load" do
|
|
425
|
+
|
|
426
|
+
let(:criteria) do
|
|
427
|
+
Person.includes(:game)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
let(:context) do
|
|
431
|
+
described_class.new(criteria)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
context "when no documents are returned" do
|
|
435
|
+
|
|
436
|
+
let(:game_metadata) do
|
|
437
|
+
Person.reflect_on_association(:game)
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it "does not make any additional database queries" do
|
|
441
|
+
game_metadata.should_receive(:eager_load).never
|
|
442
|
+
context.send(:eager_load, [])
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
describe "#exists?" do
|
|
448
|
+
|
|
449
|
+
before do
|
|
450
|
+
Band.create(name: "Depeche Mode")
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
context "when the count is zero" do
|
|
454
|
+
|
|
455
|
+
let(:criteria) do
|
|
456
|
+
Band.where(name: "New Order")
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
let(:context) do
|
|
460
|
+
described_class.new(criteria)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "returns false" do
|
|
464
|
+
context.should_not be_exists
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
context "when the count is greater than zero" do
|
|
469
|
+
|
|
470
|
+
let(:criteria) do
|
|
471
|
+
Band.where(name: "Depeche Mode")
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
let(:context) do
|
|
475
|
+
described_class.new(criteria)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it "returns true" do
|
|
479
|
+
context.should be_exists
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
context "when caching is enabled" do
|
|
484
|
+
|
|
485
|
+
let(:criteria) do
|
|
486
|
+
Band.where(name: "Depeche Mode").cache
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
let(:context) do
|
|
490
|
+
described_class.new(criteria)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
context "when the cache is loaded" do
|
|
494
|
+
|
|
495
|
+
before do
|
|
496
|
+
context.to_a
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
it "does not hit the database" do
|
|
500
|
+
context.should_receive(:query).never
|
|
501
|
+
context.should be_exists
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
context "when the cache is not loaded" do
|
|
506
|
+
|
|
507
|
+
context "when a count has been executed" do
|
|
508
|
+
|
|
509
|
+
before do
|
|
510
|
+
context.count
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
it "does not hit the database" do
|
|
514
|
+
context.should_receive(:query).never
|
|
515
|
+
context.should be_exists
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
describe "#explain" do
|
|
523
|
+
|
|
524
|
+
let(:criteria) do
|
|
525
|
+
Band.where(name: "Depeche Mode")
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
let(:context) do
|
|
529
|
+
described_class.new(criteria)
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it "returns the criteria explain path" do
|
|
533
|
+
context.explain["cursor"].should eq("BasicCursor")
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
describe "#find_and_modify" do
|
|
538
|
+
|
|
539
|
+
let!(:depeche) do
|
|
540
|
+
Band.create(name: "Depeche Mode")
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
let!(:tool) do
|
|
544
|
+
Band.create(name: "Tool")
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
context "when the selector matches" do
|
|
548
|
+
|
|
549
|
+
context "when not providing options" do
|
|
550
|
+
|
|
551
|
+
let(:criteria) do
|
|
552
|
+
Band.where(name: "Depeche Mode")
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
let(:context) do
|
|
556
|
+
described_class.new(criteria)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
let!(:result) do
|
|
560
|
+
context.find_and_modify("$inc" => { likes: 1 })
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it "returns the first matching document" do
|
|
564
|
+
result.should eq(depeche)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it "updates the document in the database" do
|
|
568
|
+
depeche.reload.likes.should eq(1)
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
context "when sorting" do
|
|
573
|
+
|
|
574
|
+
let(:criteria) do
|
|
575
|
+
Band.desc(:name)
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
let(:context) do
|
|
579
|
+
described_class.new(criteria)
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
let!(:result) do
|
|
583
|
+
context.find_and_modify("$inc" => { likes: 1 })
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
it "returns the first matching document" do
|
|
587
|
+
result.should eq(tool)
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
it "updates the document in the database" do
|
|
591
|
+
tool.reload.likes.should eq(1)
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
context "when limiting fields" do
|
|
596
|
+
|
|
597
|
+
let(:criteria) do
|
|
598
|
+
Band.only(:_id)
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
let(:context) do
|
|
602
|
+
described_class.new(criteria)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
let!(:result) do
|
|
606
|
+
context.find_and_modify("$inc" => { likes: 1 })
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
it "returns the first matching document" do
|
|
610
|
+
result.should eq(depeche)
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
it "limits the returned fields" do
|
|
614
|
+
result.name.should be_nil
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
it "updates the document in the database" do
|
|
618
|
+
depeche.reload.likes.should eq(1)
|
|
619
|
+
end
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
context "when returning new" do
|
|
623
|
+
|
|
624
|
+
let(:criteria) do
|
|
625
|
+
Band.where(name: "Depeche Mode")
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
let(:context) do
|
|
629
|
+
described_class.new(criteria)
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
let!(:result) do
|
|
633
|
+
context.find_and_modify({ "$inc" => { likes: 1 }}, new: true)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
it "returns the first matching document" do
|
|
637
|
+
result.should eq(depeche)
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
it "returns the updated document" do
|
|
641
|
+
result.likes.should eq(1)
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
context "when removing" do
|
|
646
|
+
|
|
647
|
+
let(:criteria) do
|
|
648
|
+
Band.where(name: "Depeche Mode")
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
let(:context) do
|
|
652
|
+
described_class.new(criteria)
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
let!(:result) do
|
|
656
|
+
context.find_and_modify({}, remove: true)
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
it "returns the first matching document" do
|
|
660
|
+
result.should eq(depeche)
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
it "deletes the document from the database" do
|
|
664
|
+
expect {
|
|
665
|
+
depeche.reload
|
|
666
|
+
}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
context "when the selector does not match" do
|
|
672
|
+
|
|
673
|
+
let(:criteria) do
|
|
674
|
+
Band.where(name: "Placebo")
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
let(:context) do
|
|
678
|
+
described_class.new(criteria)
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
let(:result) do
|
|
682
|
+
context.find_and_modify("$inc" => { likes: 1 })
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
it "returns nil" do
|
|
686
|
+
result.should be_nil
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
[ :first, :one ].each do |method|
|
|
692
|
+
|
|
693
|
+
describe "##{method}" do
|
|
694
|
+
|
|
695
|
+
let!(:depeche_mode) do
|
|
696
|
+
Band.create(name: "Depeche Mode")
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
let!(:new_order) do
|
|
700
|
+
Band.create(name: "New Order")
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
context "when the context is not cached" do
|
|
704
|
+
|
|
705
|
+
let(:criteria) do
|
|
706
|
+
Band.where(name: "Depeche Mode")
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
let(:context) do
|
|
710
|
+
described_class.new(criteria)
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
it "returns the first matching document" do
|
|
714
|
+
context.send(method).should eq(depeche_mode)
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
context "when using .desc" do
|
|
719
|
+
|
|
720
|
+
let(:criteria) do
|
|
721
|
+
Band.desc(:name)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
let(:context) do
|
|
725
|
+
described_class.new(criteria)
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
context "when there is sort on the context" do
|
|
729
|
+
|
|
730
|
+
it "follows the main sort" do
|
|
731
|
+
context.send(method).should eq(new_order)
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
context "when subsequently calling #last" do
|
|
736
|
+
|
|
737
|
+
it "returns the correnct document" do
|
|
738
|
+
context.send(method).should eq(new_order)
|
|
739
|
+
context.last.should eq(depeche_mode)
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
context "when using .sort" do
|
|
745
|
+
|
|
746
|
+
let(:criteria) do
|
|
747
|
+
Band.all.sort(:name => -1).criteria
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
let(:context) do
|
|
751
|
+
described_class.new(criteria)
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
context "when there is sort on the context" do
|
|
755
|
+
|
|
756
|
+
it "follows the main sort" do
|
|
757
|
+
context.send(method).should eq(new_order)
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
context "when subsequently calling #last" do
|
|
762
|
+
|
|
763
|
+
it "returns the correnct document" do
|
|
764
|
+
context.send(method).should eq(new_order)
|
|
765
|
+
context.last.should eq(depeche_mode)
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
context "when the context is cached" do
|
|
771
|
+
|
|
772
|
+
let(:criteria) do
|
|
773
|
+
Band.where(name: "Depeche Mode").cache
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
let(:context) do
|
|
777
|
+
described_class.new(criteria)
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
context "when the cache is loaded" do
|
|
781
|
+
|
|
782
|
+
before do
|
|
783
|
+
context.to_a
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
it "returns the first document without touching the database" do
|
|
787
|
+
context.should_receive(:query).never
|
|
788
|
+
context.send(method).should eq(depeche_mode)
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
end
|
|
792
|
+
end
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
describe "#initialize" do
|
|
796
|
+
|
|
797
|
+
let(:criteria) do
|
|
798
|
+
Band.where(name: "Depeche Mode").no_timeout
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
let(:context) do
|
|
802
|
+
described_class.new(criteria)
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
it "sets the criteria" do
|
|
806
|
+
context.criteria.should eq(criteria)
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
it "sets the klass" do
|
|
810
|
+
context.klass.should eq(Band)
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
it "sets the query" do
|
|
814
|
+
context.query.should be_a(Moped::Query)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
it "sets the query selector" do
|
|
818
|
+
context.query.selector.should eq({ "name" => "Depeche Mode" })
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
it "sets timeout options" do
|
|
822
|
+
context.query.operation.flags.should eq([ :no_cursor_timeout ])
|
|
823
|
+
end
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
describe "#last" do
|
|
827
|
+
|
|
828
|
+
context "when no default scope" do
|
|
829
|
+
|
|
830
|
+
let!(:depeche_mode) do
|
|
831
|
+
Band.create(name: "Depeche Mode")
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
let!(:new_order) do
|
|
835
|
+
Band.create(name: "New Order")
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
let(:criteria) do
|
|
839
|
+
Band.all
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
let(:context) do
|
|
843
|
+
described_class.new(criteria)
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
it "returns the last matching document" do
|
|
847
|
+
context.last.should eq(new_order)
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
context "when default scope" do
|
|
852
|
+
|
|
853
|
+
let!(:palm) do
|
|
854
|
+
Tree.create(name: "Palm")
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
let!(:maple) do
|
|
858
|
+
Tree.create(name: "Maple")
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
let(:criteria) do
|
|
862
|
+
Tree.all
|
|
863
|
+
end
|
|
864
|
+
|
|
865
|
+
let(:context) do
|
|
866
|
+
described_class.new(criteria)
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
it "respects default scope" do
|
|
870
|
+
context.last.should eq(palm)
|
|
871
|
+
end
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
context "when subsequently calling #first" do
|
|
875
|
+
|
|
876
|
+
let!(:depeche_mode) do
|
|
877
|
+
Band.create(name: "Depeche Mode")
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
let!(:new_order) do
|
|
881
|
+
Band.create(name: "New Order")
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
let(:criteria) do
|
|
885
|
+
Band.asc(:name)
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
let(:context) do
|
|
889
|
+
described_class.new(criteria)
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
it "returns the correnct document" do
|
|
893
|
+
context.last.should eq(new_order)
|
|
894
|
+
context.first.should eq(depeche_mode)
|
|
895
|
+
end
|
|
896
|
+
end
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
[ :length, :size ].each do |method|
|
|
900
|
+
|
|
901
|
+
describe "##{method}" do
|
|
902
|
+
|
|
903
|
+
before do
|
|
904
|
+
Band.create(name: "Depeche Mode")
|
|
905
|
+
Band.create(name: "New Order")
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
context "when the criteria has a limit" do
|
|
909
|
+
|
|
910
|
+
let(:criteria) do
|
|
911
|
+
Band.limit(1)
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
let(:context) do
|
|
915
|
+
described_class.new(criteria)
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
it "returns the number of documents that match" do
|
|
919
|
+
context.send(method).should eq(2)
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
context "when calling more than once" do
|
|
923
|
+
|
|
924
|
+
before do
|
|
925
|
+
context.query.should_receive(:count).once.and_return(2)
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
it "returns the cached value for subsequent calls" do
|
|
929
|
+
2.times { context.send(method).should eq(2) }
|
|
930
|
+
end
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
context "when the results have been iterated over" do
|
|
934
|
+
|
|
935
|
+
before do
|
|
936
|
+
context.entries
|
|
937
|
+
context.query.should_receive(:count).once.and_return(2)
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
it "returns the cached value for all calls" do
|
|
941
|
+
context.send(method).should eq(2)
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
context "when the results have been iterated over multiple times" do
|
|
945
|
+
|
|
946
|
+
before do
|
|
947
|
+
context.entries
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
it "resets the length on each full iteration" do
|
|
951
|
+
context.should have(2).items
|
|
952
|
+
end
|
|
953
|
+
end
|
|
954
|
+
end
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
context "when the criteria has no limit" do
|
|
958
|
+
|
|
959
|
+
let(:criteria) do
|
|
960
|
+
Band.where(name: "Depeche Mode")
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
let(:context) do
|
|
964
|
+
described_class.new(criteria)
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
it "returns the number of documents that match" do
|
|
968
|
+
context.send(method).should eq(1)
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
context "when calling more than once" do
|
|
972
|
+
|
|
973
|
+
before do
|
|
974
|
+
context.query.should_receive(:count).once.and_return(1)
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
it "returns the cached value for subsequent calls" do
|
|
978
|
+
2.times { context.send(method).should eq(1) }
|
|
979
|
+
end
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
context "when the results have been iterated over" do
|
|
983
|
+
|
|
984
|
+
before do
|
|
985
|
+
context.entries
|
|
986
|
+
context.query.should_receive(:count).once.and_return(1)
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
it "returns the cached value for all calls" do
|
|
990
|
+
context.send(method).should eq(1)
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
context "when the results have been iterated over multiple times" do
|
|
994
|
+
|
|
995
|
+
before do
|
|
996
|
+
context.entries
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
it "resets the length on each full iteration" do
|
|
1000
|
+
context.should have(1).item
|
|
1001
|
+
end
|
|
1002
|
+
end
|
|
1003
|
+
end
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
1007
|
+
|
|
1008
|
+
describe "#limit" do
|
|
1009
|
+
|
|
1010
|
+
let!(:depeche_mode) do
|
|
1011
|
+
Band.create(name: "Depeche Mode")
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
let!(:new_order) do
|
|
1015
|
+
Band.create(name: "New Order")
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
let(:criteria) do
|
|
1019
|
+
Band.all
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
let(:context) do
|
|
1023
|
+
described_class.new(criteria)
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
it "limits the results" do
|
|
1027
|
+
context.limit(1).entries.should eq([ depeche_mode ])
|
|
1028
|
+
end
|
|
1029
|
+
end
|
|
1030
|
+
|
|
1031
|
+
describe "#map" do
|
|
1032
|
+
|
|
1033
|
+
before do
|
|
1034
|
+
Band.create(name: "Depeche Mode")
|
|
1035
|
+
Band.create(name: "New Order")
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
let(:criteria) do
|
|
1039
|
+
Band.all
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
let(:context) do
|
|
1043
|
+
described_class.new(criteria)
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
context "when passed the symbol field name" do
|
|
1047
|
+
|
|
1048
|
+
it "limits query to that field" do
|
|
1049
|
+
criteria.should_receive(:only).with(:name).and_call_original
|
|
1050
|
+
context.map(:name)
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
it "performs mapping" do
|
|
1054
|
+
context.map(:name).should eq ["Depeche Mode", "New Order"]
|
|
1055
|
+
end
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
context "when passed a block" do
|
|
1059
|
+
|
|
1060
|
+
it "performs mapping" do
|
|
1061
|
+
context.map(&:name).should eq ["Depeche Mode", "New Order"]
|
|
1062
|
+
end
|
|
1063
|
+
end
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
describe "#map_reduce" do
|
|
1067
|
+
|
|
1068
|
+
let!(:depeche_mode) do
|
|
1069
|
+
Band.create(name: "Depeche Mode", likes: 200)
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1072
|
+
let!(:tool) do
|
|
1073
|
+
Band.create(name: "Tool", likes: 100)
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
let(:map) do
|
|
1077
|
+
%Q{
|
|
1078
|
+
function() {
|
|
1079
|
+
emit(this.name, { likes: this.likes });
|
|
1080
|
+
}}
|
|
1081
|
+
end
|
|
1082
|
+
|
|
1083
|
+
let(:reduce) do
|
|
1084
|
+
%Q{
|
|
1085
|
+
function(key, values) {
|
|
1086
|
+
var result = { likes: 0 };
|
|
1087
|
+
values.forEach(function(value) {
|
|
1088
|
+
result.likes += value.likes;
|
|
1089
|
+
});
|
|
1090
|
+
return result;
|
|
1091
|
+
}}
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
context "when no selection is provided" do
|
|
1095
|
+
|
|
1096
|
+
let(:criteria) do
|
|
1097
|
+
Band.all
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
let(:context) do
|
|
1101
|
+
described_class.new(criteria)
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
let(:results) do
|
|
1105
|
+
context.map_reduce(map, reduce).out(inline: 1)
|
|
1106
|
+
end
|
|
1107
|
+
|
|
1108
|
+
it "returns the first aggregate result" do
|
|
1109
|
+
results.should include(
|
|
1110
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1111
|
+
)
|
|
1112
|
+
end
|
|
1113
|
+
|
|
1114
|
+
it "returns the second aggregate result" do
|
|
1115
|
+
results.should include(
|
|
1116
|
+
{ "_id" => "Tool", "value" => { "likes" => 100 }}
|
|
1117
|
+
)
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
it "returns the correct number of documents" do
|
|
1121
|
+
results.count.should eq(2)
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1124
|
+
it "contains the entire raw results" do
|
|
1125
|
+
results["results"].should eq([
|
|
1126
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
|
|
1127
|
+
{ "_id" => "Tool", "value" => { "likes" => 100 }}
|
|
1128
|
+
])
|
|
1129
|
+
end
|
|
1130
|
+
|
|
1131
|
+
it "contains the execution time" do
|
|
1132
|
+
results.time.should_not be_nil
|
|
1133
|
+
end
|
|
1134
|
+
|
|
1135
|
+
it "contains the count statistics" do
|
|
1136
|
+
results["counts"].should eq({
|
|
1137
|
+
"input" => 2, "emit" => 2, "reduce" => 0, "output" => 2
|
|
1138
|
+
})
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
it "contains the input count" do
|
|
1142
|
+
results.input.should eq(2)
|
|
1143
|
+
end
|
|
1144
|
+
|
|
1145
|
+
it "contains the emitted count" do
|
|
1146
|
+
results.emitted.should eq(2)
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
it "contains the reduced count" do
|
|
1150
|
+
results.reduced.should eq(0)
|
|
1151
|
+
end
|
|
1152
|
+
|
|
1153
|
+
it "contains the output count" do
|
|
1154
|
+
results.output.should eq(2)
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
|
|
1158
|
+
context "when selection is provided" do
|
|
1159
|
+
|
|
1160
|
+
let(:criteria) do
|
|
1161
|
+
Band.where(name: "Depeche Mode")
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
let(:context) do
|
|
1165
|
+
described_class.new(criteria)
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
let(:results) do
|
|
1169
|
+
context.map_reduce(map, reduce).out(inline: 1)
|
|
1170
|
+
end
|
|
1171
|
+
|
|
1172
|
+
it "includes the aggregate result" do
|
|
1173
|
+
results.should include(
|
|
1174
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1175
|
+
)
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
it "returns the correct number of documents" do
|
|
1179
|
+
results.count.should eq(1)
|
|
1180
|
+
end
|
|
1181
|
+
|
|
1182
|
+
it "contains the entire raw results" do
|
|
1183
|
+
results["results"].should eq([
|
|
1184
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1185
|
+
])
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
it "contains the execution time" do
|
|
1189
|
+
results.time.should_not be_nil
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1192
|
+
it "contains the count statistics" do
|
|
1193
|
+
results["counts"].should eq({
|
|
1194
|
+
"input" => 1, "emit" => 1, "reduce" => 0, "output" => 1
|
|
1195
|
+
})
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
it "contains the input count" do
|
|
1199
|
+
results.input.should eq(1)
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
it "contains the emitted count" do
|
|
1203
|
+
results.emitted.should eq(1)
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
it "contains the reduced count" do
|
|
1207
|
+
results.reduced.should eq(0)
|
|
1208
|
+
end
|
|
1209
|
+
|
|
1210
|
+
it "contains the output count" do
|
|
1211
|
+
results.output.should eq(1)
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
context "when sorting is provided" do
|
|
1216
|
+
|
|
1217
|
+
before do
|
|
1218
|
+
Band.index(name: -1)
|
|
1219
|
+
Band.create_indexes
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
let(:criteria) do
|
|
1223
|
+
Band.desc(:name)
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
let(:context) do
|
|
1227
|
+
described_class.new(criteria)
|
|
1228
|
+
end
|
|
1229
|
+
|
|
1230
|
+
let(:results) do
|
|
1231
|
+
context.map_reduce(map, reduce).out(inline: 1)
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
it "returns the first aggregate result" do
|
|
1235
|
+
results.should include(
|
|
1236
|
+
{ "_id" => "Tool", "value" => { "likes" => 100 }}
|
|
1237
|
+
)
|
|
1238
|
+
end
|
|
1239
|
+
|
|
1240
|
+
it "returns the second aggregate result" do
|
|
1241
|
+
results.should include(
|
|
1242
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1243
|
+
)
|
|
1244
|
+
end
|
|
1245
|
+
|
|
1246
|
+
it "returns the correct number of documents" do
|
|
1247
|
+
results.count.should eq(2)
|
|
1248
|
+
end
|
|
1249
|
+
|
|
1250
|
+
it "contains the entire raw results" do
|
|
1251
|
+
results["results"].should eq([
|
|
1252
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
|
|
1253
|
+
{ "_id" => "Tool", "value" => { "likes" => 100 }}
|
|
1254
|
+
])
|
|
1255
|
+
end
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
context "when limiting is provided" do
|
|
1259
|
+
|
|
1260
|
+
let(:criteria) do
|
|
1261
|
+
Band.limit(1)
|
|
1262
|
+
end
|
|
1263
|
+
|
|
1264
|
+
let(:context) do
|
|
1265
|
+
described_class.new(criteria)
|
|
1266
|
+
end
|
|
1267
|
+
|
|
1268
|
+
let(:results) do
|
|
1269
|
+
context.map_reduce(map, reduce).out(inline: 1)
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
it "returns the first aggregate result" do
|
|
1273
|
+
results.should include(
|
|
1274
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1275
|
+
)
|
|
1276
|
+
end
|
|
1277
|
+
|
|
1278
|
+
it "returns the correct number of documents" do
|
|
1279
|
+
results.count.should eq(1)
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
it "contains the entire raw results" do
|
|
1283
|
+
results["results"].should eq([
|
|
1284
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1285
|
+
])
|
|
1286
|
+
end
|
|
1287
|
+
end
|
|
1288
|
+
|
|
1289
|
+
context "when the output is replace" do
|
|
1290
|
+
|
|
1291
|
+
let(:criteria) do
|
|
1292
|
+
Band.limit(1)
|
|
1293
|
+
end
|
|
1294
|
+
|
|
1295
|
+
let(:context) do
|
|
1296
|
+
described_class.new(criteria)
|
|
1297
|
+
end
|
|
1298
|
+
|
|
1299
|
+
let(:results) do
|
|
1300
|
+
context.map_reduce(map, reduce).out(replace: "mr-output")
|
|
1301
|
+
end
|
|
1302
|
+
|
|
1303
|
+
it "returns the correct number of documents" do
|
|
1304
|
+
results.count.should eq(1)
|
|
1305
|
+
end
|
|
1306
|
+
|
|
1307
|
+
it "contains the entire results" do
|
|
1308
|
+
results.should eq([
|
|
1309
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1310
|
+
])
|
|
1311
|
+
end
|
|
1312
|
+
end
|
|
1313
|
+
|
|
1314
|
+
context "when the output is reduce" do
|
|
1315
|
+
|
|
1316
|
+
let(:criteria) do
|
|
1317
|
+
Band.limit(1)
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
let(:context) do
|
|
1321
|
+
described_class.new(criteria)
|
|
1322
|
+
end
|
|
1323
|
+
|
|
1324
|
+
let(:results) do
|
|
1325
|
+
context.map_reduce(map, reduce).out(reduce: :mr_output)
|
|
1326
|
+
end
|
|
1327
|
+
|
|
1328
|
+
it "returns the correct number of documents" do
|
|
1329
|
+
results.count.should eq(1)
|
|
1330
|
+
end
|
|
1331
|
+
|
|
1332
|
+
it "contains the entire results" do
|
|
1333
|
+
results.should eq([
|
|
1334
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1335
|
+
])
|
|
1336
|
+
end
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
context "when the output is merge" do
|
|
1340
|
+
|
|
1341
|
+
let(:criteria) do
|
|
1342
|
+
Band.limit(1)
|
|
1343
|
+
end
|
|
1344
|
+
|
|
1345
|
+
let(:context) do
|
|
1346
|
+
described_class.new(criteria)
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1349
|
+
let(:results) do
|
|
1350
|
+
context.map_reduce(map, reduce).out(merge: :mr_output)
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
it "returns the correct number of documents" do
|
|
1354
|
+
results.count.should eq(1)
|
|
1355
|
+
end
|
|
1356
|
+
|
|
1357
|
+
it "contains the entire results" do
|
|
1358
|
+
results.should eq([
|
|
1359
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
1360
|
+
])
|
|
1361
|
+
end
|
|
1362
|
+
end
|
|
1363
|
+
|
|
1364
|
+
context "when providing no output" do
|
|
1365
|
+
|
|
1366
|
+
let(:criteria) do
|
|
1367
|
+
Band.limit(1)
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1370
|
+
let(:context) do
|
|
1371
|
+
described_class.new(criteria)
|
|
1372
|
+
end
|
|
1373
|
+
|
|
1374
|
+
let(:results) do
|
|
1375
|
+
context.map_reduce(map, reduce)
|
|
1376
|
+
end
|
|
1377
|
+
|
|
1378
|
+
it "raises an error" do
|
|
1379
|
+
expect {
|
|
1380
|
+
results.entries
|
|
1381
|
+
}.to raise_error(Mongoid::Errors::NoMapReduceOutput)
|
|
1382
|
+
end
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
context "when providing a finalize" do
|
|
1386
|
+
|
|
1387
|
+
let(:criteria) do
|
|
1388
|
+
Band.limit(1)
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
let(:context) do
|
|
1392
|
+
described_class.new(criteria)
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
let(:finalize) do
|
|
1396
|
+
%Q{
|
|
1397
|
+
function(key, value) {
|
|
1398
|
+
value.extra = true;
|
|
1399
|
+
return value;
|
|
1400
|
+
}}
|
|
1401
|
+
end
|
|
1402
|
+
|
|
1403
|
+
let(:results) do
|
|
1404
|
+
context.map_reduce(map, reduce).out(inline: 1).finalize(finalize)
|
|
1405
|
+
end
|
|
1406
|
+
|
|
1407
|
+
it "returns the correct number of documents" do
|
|
1408
|
+
results.count.should eq(1)
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
it "contains the entire results" do
|
|
1412
|
+
results.should eq([
|
|
1413
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200, "extra" => true }}
|
|
1414
|
+
])
|
|
1415
|
+
end
|
|
1416
|
+
end
|
|
1417
|
+
end
|
|
1418
|
+
|
|
1419
|
+
describe "#skip" do
|
|
1420
|
+
|
|
1421
|
+
let!(:depeche_mode) do
|
|
1422
|
+
Band.create(name: "Depeche Mode")
|
|
1423
|
+
end
|
|
1424
|
+
|
|
1425
|
+
let!(:new_order) do
|
|
1426
|
+
Band.create(name: "New Order")
|
|
1427
|
+
end
|
|
1428
|
+
|
|
1429
|
+
let(:criteria) do
|
|
1430
|
+
Band.all
|
|
1431
|
+
end
|
|
1432
|
+
|
|
1433
|
+
let(:context) do
|
|
1434
|
+
described_class.new(criteria)
|
|
1435
|
+
end
|
|
1436
|
+
|
|
1437
|
+
it "limits the results" do
|
|
1438
|
+
context.skip(1).entries.should eq([ new_order ])
|
|
1439
|
+
end
|
|
1440
|
+
end
|
|
1441
|
+
|
|
1442
|
+
describe "#sort" do
|
|
1443
|
+
|
|
1444
|
+
let!(:depeche_mode) do
|
|
1445
|
+
Band.create(name: "Depeche Mode")
|
|
1446
|
+
end
|
|
1447
|
+
|
|
1448
|
+
let!(:new_order) do
|
|
1449
|
+
Band.create(name: "New Order")
|
|
1450
|
+
end
|
|
1451
|
+
|
|
1452
|
+
let(:criteria) do
|
|
1453
|
+
Band.all
|
|
1454
|
+
end
|
|
1455
|
+
|
|
1456
|
+
let(:context) do
|
|
1457
|
+
described_class.new(criteria)
|
|
1458
|
+
end
|
|
1459
|
+
|
|
1460
|
+
context "when providing a spec" do
|
|
1461
|
+
|
|
1462
|
+
it "sorts the results" do
|
|
1463
|
+
context.sort(name: -1).entries.should eq([ new_order, depeche_mode ])
|
|
1464
|
+
end
|
|
1465
|
+
|
|
1466
|
+
it "returns the context" do
|
|
1467
|
+
context.sort(name: 1).should eq(context)
|
|
1468
|
+
end
|
|
1469
|
+
end
|
|
1470
|
+
|
|
1471
|
+
context "when providing a block" do
|
|
1472
|
+
|
|
1473
|
+
let(:sorted) do
|
|
1474
|
+
context.sort do |a, b|
|
|
1475
|
+
b.name <=> a.name
|
|
1476
|
+
end
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
it "sorts the results in memory" do
|
|
1480
|
+
sorted.should eq([ new_order, depeche_mode ])
|
|
1481
|
+
end
|
|
1482
|
+
end
|
|
1483
|
+
end
|
|
1484
|
+
|
|
1485
|
+
describe "#update" do
|
|
1486
|
+
|
|
1487
|
+
let!(:depeche_mode) do
|
|
1488
|
+
Band.create(name: "Depeche Mode")
|
|
1489
|
+
end
|
|
1490
|
+
|
|
1491
|
+
let!(:new_order) do
|
|
1492
|
+
Band.create(name: "New Order")
|
|
1493
|
+
end
|
|
1494
|
+
|
|
1495
|
+
let(:criteria) do
|
|
1496
|
+
Band.all
|
|
1497
|
+
end
|
|
1498
|
+
|
|
1499
|
+
let(:context) do
|
|
1500
|
+
described_class.new(criteria)
|
|
1501
|
+
end
|
|
1502
|
+
|
|
1503
|
+
context "when providing attributes" do
|
|
1504
|
+
|
|
1505
|
+
context "when the attributes are of the correct type" do
|
|
1506
|
+
|
|
1507
|
+
before do
|
|
1508
|
+
context.update(name: "Smiths")
|
|
1509
|
+
end
|
|
1510
|
+
|
|
1511
|
+
it "updates only the first matching document" do
|
|
1512
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1513
|
+
end
|
|
1514
|
+
|
|
1515
|
+
it "does not update the last matching document" do
|
|
1516
|
+
new_order.reload.name.should eq("New Order")
|
|
1517
|
+
end
|
|
1518
|
+
end
|
|
1519
|
+
|
|
1520
|
+
context "when the attributes must be mongoized" do
|
|
1521
|
+
|
|
1522
|
+
context "when coercing a string to integer" do
|
|
1523
|
+
|
|
1524
|
+
before do
|
|
1525
|
+
context.update(member_count: "1")
|
|
1526
|
+
end
|
|
1527
|
+
|
|
1528
|
+
it "updates the first matching document" do
|
|
1529
|
+
depeche_mode.reload.member_count.should eq(1)
|
|
1530
|
+
end
|
|
1531
|
+
|
|
1532
|
+
it "does not update the last matching document" do
|
|
1533
|
+
new_order.reload.member_count.should be_nil
|
|
1534
|
+
end
|
|
1535
|
+
end
|
|
1536
|
+
|
|
1537
|
+
context "when coercing a string to date" do
|
|
1538
|
+
|
|
1539
|
+
before do
|
|
1540
|
+
context.update(founded: "1979/1/1")
|
|
1541
|
+
end
|
|
1542
|
+
|
|
1543
|
+
it "updates the first matching document" do
|
|
1544
|
+
depeche_mode.reload.founded.should eq(Date.new(1979, 1, 1))
|
|
1545
|
+
end
|
|
1546
|
+
|
|
1547
|
+
it "does not update the last matching document" do
|
|
1548
|
+
new_order.reload.founded.should be_nil
|
|
1549
|
+
end
|
|
1550
|
+
end
|
|
1551
|
+
end
|
|
1552
|
+
end
|
|
1553
|
+
|
|
1554
|
+
context "when providing atomic operations" do
|
|
1555
|
+
|
|
1556
|
+
context "when only atomic operations are provided" do
|
|
1557
|
+
|
|
1558
|
+
context "when the attributes are in the correct type" do
|
|
1559
|
+
|
|
1560
|
+
before do
|
|
1561
|
+
context.update("$set" => { name: "Smiths" })
|
|
1562
|
+
end
|
|
1563
|
+
|
|
1564
|
+
it "updates the first matching document" do
|
|
1565
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1566
|
+
end
|
|
1567
|
+
|
|
1568
|
+
it "does not update the last matching document" do
|
|
1569
|
+
new_order.reload.name.should eq("New Order")
|
|
1570
|
+
end
|
|
1571
|
+
end
|
|
1572
|
+
|
|
1573
|
+
context "when the attributes must be mongoized" do
|
|
1574
|
+
|
|
1575
|
+
before do
|
|
1576
|
+
context.update("$set" => { member_count: "1" })
|
|
1577
|
+
end
|
|
1578
|
+
|
|
1579
|
+
it "updates the first matching document" do
|
|
1580
|
+
depeche_mode.reload.member_count.should eq(1)
|
|
1581
|
+
end
|
|
1582
|
+
|
|
1583
|
+
it "does not update the last matching document" do
|
|
1584
|
+
new_order.reload.member_count.should be_nil
|
|
1585
|
+
end
|
|
1586
|
+
end
|
|
1587
|
+
end
|
|
1588
|
+
|
|
1589
|
+
context "when a mix are provided" do
|
|
1590
|
+
|
|
1591
|
+
before do
|
|
1592
|
+
context.update("$set" => { name: "Smiths" }, likes: 100)
|
|
1593
|
+
end
|
|
1594
|
+
|
|
1595
|
+
it "updates the first matching document's set" do
|
|
1596
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1597
|
+
end
|
|
1598
|
+
|
|
1599
|
+
it "updates the first matching document's updates" do
|
|
1600
|
+
depeche_mode.reload.likes.should eq(100)
|
|
1601
|
+
end
|
|
1602
|
+
|
|
1603
|
+
it "does not update the last matching document's set" do
|
|
1604
|
+
new_order.reload.name.should eq("New Order")
|
|
1605
|
+
end
|
|
1606
|
+
|
|
1607
|
+
it "does not update the last matching document's updates" do
|
|
1608
|
+
new_order.reload.likes.should be_nil
|
|
1609
|
+
end
|
|
1610
|
+
end
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
context "when providing no attributes" do
|
|
1614
|
+
|
|
1615
|
+
it "returns false" do
|
|
1616
|
+
context.update.should be_false
|
|
1617
|
+
end
|
|
1618
|
+
end
|
|
1619
|
+
end
|
|
1620
|
+
|
|
1621
|
+
describe "#update_all" do
|
|
1622
|
+
|
|
1623
|
+
let!(:depeche_mode) do
|
|
1624
|
+
Band.create(name: "Depeche Mode", origin: "Essex")
|
|
1625
|
+
end
|
|
1626
|
+
|
|
1627
|
+
let!(:new_order) do
|
|
1628
|
+
Band.create(name: "New Order")
|
|
1629
|
+
end
|
|
1630
|
+
|
|
1631
|
+
let(:criteria) do
|
|
1632
|
+
Band.all
|
|
1633
|
+
end
|
|
1634
|
+
|
|
1635
|
+
let(:context) do
|
|
1636
|
+
described_class.new(criteria)
|
|
1637
|
+
end
|
|
1638
|
+
|
|
1639
|
+
context "when providing attributes" do
|
|
1640
|
+
|
|
1641
|
+
context "when the attributes are of the correct type" do
|
|
1642
|
+
|
|
1643
|
+
before do
|
|
1644
|
+
context.update_all(name: "Smiths")
|
|
1645
|
+
end
|
|
1646
|
+
|
|
1647
|
+
it "updates the first matching document" do
|
|
1648
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1649
|
+
end
|
|
1650
|
+
|
|
1651
|
+
it "does not clear out other attributes" do
|
|
1652
|
+
depeche_mode.reload.origin.should eq("Essex")
|
|
1653
|
+
end
|
|
1654
|
+
|
|
1655
|
+
it "updates the last matching document" do
|
|
1656
|
+
new_order.reload.name.should eq("Smiths")
|
|
1657
|
+
end
|
|
1658
|
+
end
|
|
1659
|
+
|
|
1660
|
+
context "when the attributes must be mongoized" do
|
|
1661
|
+
|
|
1662
|
+
before do
|
|
1663
|
+
context.update_all(member_count: "1")
|
|
1664
|
+
end
|
|
1665
|
+
|
|
1666
|
+
it "updates the first matching document" do
|
|
1667
|
+
depeche_mode.reload.member_count.should eq(1)
|
|
1668
|
+
end
|
|
1669
|
+
|
|
1670
|
+
it "updates the last matching document" do
|
|
1671
|
+
new_order.reload.member_count.should eq(1)
|
|
1672
|
+
end
|
|
1673
|
+
end
|
|
1674
|
+
|
|
1675
|
+
context "when using aliased field names" do
|
|
1676
|
+
|
|
1677
|
+
before do
|
|
1678
|
+
context.update_all(years: 100)
|
|
1679
|
+
end
|
|
1680
|
+
|
|
1681
|
+
it "updates the first matching document" do
|
|
1682
|
+
depeche_mode.reload.years.should eq(100)
|
|
1683
|
+
end
|
|
1684
|
+
|
|
1685
|
+
it "updates the last matching document" do
|
|
1686
|
+
new_order.reload.years.should eq(100)
|
|
1687
|
+
end
|
|
1688
|
+
end
|
|
1689
|
+
end
|
|
1690
|
+
|
|
1691
|
+
context "when providing atomic operations" do
|
|
1692
|
+
|
|
1693
|
+
context "when only atomic operations are provided" do
|
|
1694
|
+
|
|
1695
|
+
context "when the attributes are in the correct type" do
|
|
1696
|
+
|
|
1697
|
+
before do
|
|
1698
|
+
context.update_all("$set" => { name: "Smiths" })
|
|
1699
|
+
end
|
|
1700
|
+
|
|
1701
|
+
it "updates the first matching document" do
|
|
1702
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1703
|
+
end
|
|
1704
|
+
|
|
1705
|
+
it "updates the last matching document" do
|
|
1706
|
+
new_order.reload.name.should eq("Smiths")
|
|
1707
|
+
end
|
|
1708
|
+
end
|
|
1709
|
+
|
|
1710
|
+
context "when the attributes must be mongoized" do
|
|
1711
|
+
|
|
1712
|
+
before do
|
|
1713
|
+
context.update_all("$set" => { member_count: "1" })
|
|
1714
|
+
end
|
|
1715
|
+
|
|
1716
|
+
it "updates the first matching document" do
|
|
1717
|
+
depeche_mode.reload.member_count.should eq(1)
|
|
1718
|
+
end
|
|
1719
|
+
|
|
1720
|
+
it "updates the last matching document" do
|
|
1721
|
+
new_order.reload.member_count.should eq(1)
|
|
1722
|
+
end
|
|
1723
|
+
end
|
|
1724
|
+
end
|
|
1725
|
+
|
|
1726
|
+
context "when a mix are provided" do
|
|
1727
|
+
|
|
1728
|
+
before do
|
|
1729
|
+
context.update_all("$set" => { name: "Smiths" }, likes: 100)
|
|
1730
|
+
end
|
|
1731
|
+
|
|
1732
|
+
it "updates the first matching document's set" do
|
|
1733
|
+
depeche_mode.reload.name.should eq("Smiths")
|
|
1734
|
+
end
|
|
1735
|
+
|
|
1736
|
+
it "updates the first matching document's updates" do
|
|
1737
|
+
depeche_mode.reload.likes.should eq(100)
|
|
1738
|
+
end
|
|
1739
|
+
|
|
1740
|
+
it "updates the last matching document's set" do
|
|
1741
|
+
new_order.reload.name.should eq("Smiths")
|
|
1742
|
+
end
|
|
1743
|
+
|
|
1744
|
+
it "updates the last matching document's updates" do
|
|
1745
|
+
new_order.reload.likes.should eq(100)
|
|
1746
|
+
end
|
|
1747
|
+
end
|
|
1748
|
+
end
|
|
1749
|
+
|
|
1750
|
+
context "when providing no attributes" do
|
|
1751
|
+
|
|
1752
|
+
it "returns false" do
|
|
1753
|
+
context.update_all.should be_false
|
|
1754
|
+
end
|
|
1755
|
+
end
|
|
1756
|
+
end
|
|
1757
|
+
end
|