mongoid 7.5.4 → 8.1.9
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 +3 -3
- data/README.md +6 -6
- data/Rakefile +44 -46
- data/lib/config/locales/en.yml +92 -43
- data/lib/mongoid/association/accessors.rb +44 -11
- data/lib/mongoid/association/bindable.rb +50 -2
- data/lib/mongoid/association/builders.rb +5 -3
- data/lib/mongoid/association/constrainable.rb +0 -1
- data/lib/mongoid/association/eager_loadable.rb +32 -7
- data/lib/mongoid/association/embedded/batchable.rb +34 -11
- data/lib/mongoid/association/embedded/cyclic.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
- data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +4 -3
- data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
- data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +4 -3
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +85 -46
- data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +19 -5
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +24 -5
- data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
- data/lib/mongoid/association/macros.rb +8 -1
- data/lib/mongoid/association/many.rb +11 -7
- data/lib/mongoid/association/nested/many.rb +5 -4
- data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
- data/lib/mongoid/association/nested/one.rb +45 -7
- data/lib/mongoid/association/one.rb +2 -2
- data/lib/mongoid/association/options.rb +9 -9
- data/lib/mongoid/association/proxy.rb +15 -4
- data/lib/mongoid/association/referenced/auto_save.rb +4 -3
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
- data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
- data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
- data/lib/mongoid/association/referenced/eager.rb +2 -2
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
- data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +22 -30
- data/lib/mongoid/association/referenced/has_many/proxy.rb +40 -21
- data/lib/mongoid/association/referenced/has_many.rb +3 -3
- data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
- data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
- data/lib/mongoid/association/referenced/has_one.rb +3 -3
- data/lib/mongoid/association/referenced/syncable.rb +4 -4
- data/lib/mongoid/association/reflections.rb +4 -4
- data/lib/mongoid/association/relatable.rb +44 -10
- data/lib/mongoid/association.rb +5 -5
- data/lib/mongoid/atomic/modifiers.rb +2 -2
- data/lib/mongoid/atomic.rb +16 -7
- data/lib/mongoid/attributes/dynamic.rb +4 -4
- data/lib/mongoid/attributes/nested.rb +6 -6
- data/lib/mongoid/attributes/processing.rb +37 -6
- data/lib/mongoid/attributes/projector.rb +2 -2
- data/lib/mongoid/attributes/readonly.rb +11 -6
- data/lib/mongoid/attributes.rb +51 -42
- data/lib/mongoid/changeable.rb +147 -14
- data/lib/mongoid/clients/options.rb +5 -1
- data/lib/mongoid/clients/sessions.rb +2 -14
- data/lib/mongoid/clients/storage_options.rb +2 -5
- data/lib/mongoid/clients/validators/storage.rb +3 -15
- data/lib/mongoid/collection_configurable.rb +58 -0
- data/lib/mongoid/composable.rb +2 -0
- data/lib/mongoid/config/defaults.rb +60 -0
- data/lib/mongoid/config/options.rb +3 -0
- data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
- data/lib/mongoid/config/validators/client.rb +6 -6
- data/lib/mongoid/config/validators.rb +1 -0
- data/lib/mongoid/config.rb +153 -18
- data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
- data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
- data/lib/mongoid/contextual/aggregable/none.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +1 -1
- data/lib/mongoid/contextual/geo_near.rb +7 -7
- data/lib/mongoid/contextual/map_reduce.rb +2 -2
- data/lib/mongoid/contextual/memory.rb +285 -58
- data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
- data/lib/mongoid/contextual/mongo.rb +540 -346
- data/lib/mongoid/contextual/none.rb +193 -20
- data/lib/mongoid/contextual/queryable.rb +1 -1
- data/lib/mongoid/contextual.rb +14 -2
- data/lib/mongoid/copyable.rb +32 -8
- data/lib/mongoid/criteria/findable.rb +8 -5
- data/lib/mongoid/criteria/includable.rb +27 -22
- data/lib/mongoid/criteria/marshalable.rb +10 -2
- data/lib/mongoid/criteria/permission.rb +1 -1
- data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -16
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -17
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -9
- data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
- data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
- data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
- data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
- data/lib/mongoid/criteria/queryable/key.rb +4 -4
- data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
- data/lib/mongoid/criteria/queryable/optional.rb +11 -17
- data/lib/mongoid/criteria/queryable/options.rb +2 -2
- data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
- data/lib/mongoid/criteria/queryable/selectable.rb +48 -39
- data/lib/mongoid/criteria/queryable/selector.rb +92 -7
- data/lib/mongoid/criteria/queryable/smash.rb +40 -7
- data/lib/mongoid/criteria/queryable.rb +12 -7
- data/lib/mongoid/criteria/scopable.rb +2 -2
- data/lib/mongoid/criteria/translator.rb +45 -0
- data/lib/mongoid/criteria.rb +20 -40
- data/lib/mongoid/deprecable.rb +37 -0
- data/lib/mongoid/deprecation.rb +25 -0
- data/lib/mongoid/document.rb +135 -36
- data/lib/mongoid/equality.rb +9 -8
- data/lib/mongoid/errors/create_collection_failure.rb +33 -0
- data/lib/mongoid/errors/document_not_found.rb +10 -6
- data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
- data/lib/mongoid/errors/immutable_attribute.rb +26 -0
- data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
- data/lib/mongoid/errors/invalid_config_option.rb +1 -1
- data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
- data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
- data/lib/mongoid/errors/invalid_field.rb +6 -2
- data/lib/mongoid/errors/invalid_field_type.rb +26 -0
- data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
- data/lib/mongoid/errors/invalid_relation.rb +1 -1
- data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
- data/lib/mongoid/errors/invalid_session_use.rb +1 -1
- data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
- data/lib/mongoid/errors/mongoid_error.rb +3 -3
- data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
- data/lib/mongoid/errors/no_client_database.rb +1 -1
- data/lib/mongoid/errors/no_client_hosts.rb +1 -1
- data/lib/mongoid/errors/readonly_attribute.rb +1 -1
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
- data/lib/mongoid/errors/unknown_attribute.rb +1 -1
- data/lib/mongoid/errors.rb +6 -3
- data/lib/mongoid/extensions/array.rb +9 -7
- data/lib/mongoid/extensions/big_decimal.rb +33 -10
- data/lib/mongoid/extensions/binary.rb +42 -0
- data/lib/mongoid/extensions/boolean.rb +8 -2
- data/lib/mongoid/extensions/date.rb +26 -20
- data/lib/mongoid/extensions/date_time.rb +1 -1
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/float.rb +7 -4
- data/lib/mongoid/extensions/hash.rb +38 -9
- data/lib/mongoid/extensions/integer.rb +7 -4
- data/lib/mongoid/extensions/module.rb +1 -1
- data/lib/mongoid/extensions/object.rb +10 -8
- data/lib/mongoid/extensions/range.rb +41 -10
- data/lib/mongoid/extensions/regexp.rb +11 -4
- data/lib/mongoid/extensions/set.rb +11 -4
- data/lib/mongoid/extensions/string.rb +11 -22
- data/lib/mongoid/extensions/symbol.rb +4 -15
- data/lib/mongoid/extensions/time.rb +29 -16
- data/lib/mongoid/extensions/time_with_zone.rb +1 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/factory.rb +55 -7
- data/lib/mongoid/fields/foreign_key.rb +11 -4
- data/lib/mongoid/fields/localized.rb +19 -4
- data/lib/mongoid/fields/standard.rb +17 -7
- data/lib/mongoid/fields/validators/macro.rb +3 -9
- data/lib/mongoid/fields.rb +142 -28
- data/lib/mongoid/findable.rb +54 -24
- data/lib/mongoid/indexable/specification.rb +2 -2
- data/lib/mongoid/indexable/validators/options.rb +6 -2
- data/lib/mongoid/interceptable.rb +187 -16
- data/lib/mongoid/matchable.rb +1 -1
- data/lib/mongoid/matcher/eq_impl.rb +1 -1
- data/lib/mongoid/matcher/type.rb +1 -1
- data/lib/mongoid/matcher.rb +48 -14
- data/lib/mongoid/persistable/creatable.rb +19 -9
- data/lib/mongoid/persistable/deletable.rb +2 -2
- data/lib/mongoid/persistable/destroyable.rb +1 -1
- data/lib/mongoid/persistable/savable.rb +14 -2
- data/lib/mongoid/persistable/unsettable.rb +2 -2
- data/lib/mongoid/persistable/updatable.rb +69 -12
- data/lib/mongoid/persistable/upsertable.rb +21 -2
- data/lib/mongoid/persistable.rb +6 -3
- data/lib/mongoid/persistence_context.rb +6 -4
- data/lib/mongoid/query_cache.rb +13 -261
- data/lib/mongoid/railties/controller_runtime.rb +1 -1
- data/lib/mongoid/railties/database.rake +7 -2
- data/lib/mongoid/reloadable.rb +10 -8
- data/lib/mongoid/scopable.rb +15 -13
- data/lib/mongoid/selectable.rb +1 -2
- data/lib/mongoid/serializable.rb +17 -13
- data/lib/mongoid/stateful.rb +57 -10
- data/lib/mongoid/tasks/database.rake +12 -0
- data/lib/mongoid/tasks/database.rb +20 -2
- data/lib/mongoid/threaded/lifecycle.rb +5 -5
- data/lib/mongoid/threaded.rb +42 -12
- data/lib/mongoid/timestamps/created.rb +9 -2
- data/lib/mongoid/timestamps/updated.rb +2 -2
- data/lib/mongoid/touchable.rb +3 -4
- data/lib/mongoid/traversable.rb +41 -5
- data/lib/mongoid/utils.rb +22 -0
- data/lib/mongoid/validatable/associated.rb +98 -17
- data/lib/mongoid/validatable/localizable.rb +1 -1
- data/lib/mongoid/validatable/macros.rb +5 -7
- data/lib/mongoid/validatable/presence.rb +2 -2
- data/lib/mongoid/validatable/uniqueness.rb +9 -8
- data/lib/mongoid/validatable.rb +17 -6
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/warnings.rb +19 -4
- data/lib/mongoid.rb +17 -3
- data/spec/config/mongoid.yml +16 -0
- data/spec/integration/app_spec.rb +24 -19
- data/spec/integration/associations/belongs_to_spec.rb +18 -0
- data/spec/integration/associations/embedded_spec.rb +15 -0
- data/spec/integration/associations/embeds_many_spec.rb +15 -2
- data/spec/integration/associations/embeds_one_spec.rb +18 -0
- data/spec/integration/associations/foreign_key_spec.rb +9 -0
- data/spec/integration/associations/has_and_belongs_to_many_spec.rb +61 -0
- data/spec/integration/associations/has_one_spec.rb +97 -1
- data/spec/integration/associations/scope_option_spec.rb +1 -1
- data/spec/integration/callbacks_models.rb +132 -1
- data/spec/integration/callbacks_spec.rb +381 -4
- data/spec/integration/criteria/range_spec.rb +95 -1
- data/spec/integration/discriminator_key_spec.rb +118 -80
- data/spec/integration/dots_and_dollars_spec.rb +277 -0
- data/spec/integration/i18n_fallbacks_spec.rb +3 -32
- data/spec/integration/matcher_examples_spec.rb +20 -13
- data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
- data/spec/integration/matcher_operator_spec.rb +3 -5
- data/spec/integration/persistence/range_field_spec.rb +350 -0
- data/spec/mongoid/association/counter_cache_spec.rb +1 -1
- data/spec/mongoid/association/depending_spec.rb +9 -9
- data/spec/mongoid/association/eager_spec.rb +26 -3
- data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
- data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +96 -9
- data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +290 -65
- data/spec/mongoid/association/embedded/embeds_many_models.rb +37 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +16 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
- data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
- data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
- data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
- data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
- data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +19 -0
- data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +4 -20
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +186 -229
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +215 -177
- data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
- data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
- data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
- data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
- data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
- data/spec/mongoid/association/syncable_spec.rb +15 -1
- data/spec/mongoid/association_spec.rb +60 -0
- data/spec/mongoid/atomic/paths_spec.rb +0 -14
- data/spec/mongoid/attributes/nested_spec.rb +80 -11
- data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
- data/spec/mongoid/attributes/projector_spec.rb +1 -5
- data/spec/mongoid/attributes/readonly_spec.rb +19 -0
- data/spec/mongoid/attributes_spec.rb +526 -33
- data/spec/mongoid/changeable_spec.rb +429 -37
- data/spec/mongoid/clients/factory_spec.rb +23 -30
- data/spec/mongoid/clients/sessions_spec.rb +0 -38
- data/spec/mongoid/clients_spec.rb +149 -15
- data/spec/mongoid/collection_configurable_spec.rb +158 -0
- data/spec/mongoid/config/defaults_spec.rb +160 -0
- data/spec/mongoid/config_spec.rb +214 -31
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
- data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
- data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
- data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
- data/spec/mongoid/contextual/memory_spec.rb +850 -88
- data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
- data/spec/mongoid/contextual/mongo_spec.rb +2256 -1005
- data/spec/mongoid/contextual/none_spec.rb +60 -21
- data/spec/mongoid/copyable_spec.rb +453 -11
- data/spec/mongoid/criteria/findable_spec.rb +86 -210
- data/spec/mongoid/criteria/includable_spec.rb +1492 -0
- data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
- data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
- data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +469 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +107 -86
- data/spec/mongoid/criteria/queryable/selector_spec.rb +15 -3
- data/spec/mongoid/criteria/translator_spec.rb +132 -0
- data/spec/mongoid/criteria_projection_spec.rb +1 -5
- data/spec/mongoid/criteria_spec.rb +469 -1205
- data/spec/mongoid/document_fields_spec.rb +173 -24
- data/spec/mongoid/document_spec.rb +59 -41
- data/spec/mongoid/equality_spec.rb +6 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
- data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
- data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
- data/spec/mongoid/errors/no_environment_spec.rb +3 -3
- data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
- data/spec/mongoid/extensions/array_spec.rb +16 -2
- data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
- data/spec/mongoid/extensions/binary_spec.rb +44 -9
- data/spec/mongoid/extensions/boolean_spec.rb +68 -82
- data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
- data/spec/mongoid/extensions/date_spec.rb +71 -1
- data/spec/mongoid/extensions/date_time_spec.rb +15 -9
- data/spec/mongoid/extensions/float_spec.rb +53 -74
- data/spec/mongoid/extensions/hash_spec.rb +33 -3
- data/spec/mongoid/extensions/integer_spec.rb +50 -64
- data/spec/mongoid/extensions/range_spec.rb +255 -54
- data/spec/mongoid/extensions/regexp_spec.rb +58 -33
- data/spec/mongoid/extensions/set_spec.rb +106 -0
- data/spec/mongoid/extensions/string_spec.rb +53 -25
- data/spec/mongoid/extensions/symbol_spec.rb +18 -25
- data/spec/mongoid/extensions/time_spec.rb +639 -106
- data/spec/mongoid/extensions/time_with_zone_spec.rb +24 -83
- data/spec/mongoid/factory_spec.rb +61 -1
- data/spec/mongoid/fields/localized_spec.rb +80 -37
- data/spec/mongoid/fields_spec.rb +503 -87
- data/spec/mongoid/findable_spec.rb +450 -58
- data/spec/mongoid/indexable/specification_spec.rb +2 -2
- data/spec/mongoid/indexable_spec.rb +55 -30
- data/spec/mongoid/interceptable_spec.rb +904 -22
- data/spec/mongoid/interceptable_spec_models.rb +189 -22
- data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
- data/spec/mongoid/mongoizable_spec.rb +285 -0
- data/spec/mongoid/persistable/creatable_spec.rb +2 -2
- data/spec/mongoid/persistable/deletable_spec.rb +28 -8
- data/spec/mongoid/persistable/destroyable_spec.rb +28 -8
- data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
- data/spec/mongoid/persistable/logical_spec.rb +37 -0
- data/spec/mongoid/persistable/poppable_spec.rb +36 -0
- data/spec/mongoid/persistable/pullable_spec.rb +72 -0
- data/spec/mongoid/persistable/pushable_spec.rb +72 -0
- data/spec/mongoid/persistable/renamable_spec.rb +36 -0
- data/spec/mongoid/persistable/savable_spec.rb +96 -0
- data/spec/mongoid/persistable/settable_spec.rb +37 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
- data/spec/mongoid/persistable/updatable_spec.rb +20 -28
- data/spec/mongoid/persistable/upsertable_spec.rb +89 -1
- data/spec/mongoid/persistence_context_spec.rb +31 -57
- data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
- data/spec/mongoid/query_cache_spec.rb +56 -215
- data/spec/mongoid/reloadable_spec.rb +83 -6
- data/spec/mongoid/scopable_spec.rb +91 -1
- data/spec/mongoid/serializable_spec.rb +25 -39
- data/spec/mongoid/shardable_spec.rb +4 -4
- data/spec/mongoid/stateful_spec.rb +150 -8
- data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
- data/spec/mongoid/tasks/database_spec.rb +127 -0
- data/spec/mongoid/timestamps/created_spec.rb +23 -0
- data/spec/mongoid/timestamps_spec.rb +392 -4
- data/spec/mongoid/timestamps_spec_models.rb +67 -0
- data/spec/mongoid/touchable_spec.rb +390 -2
- data/spec/mongoid/touchable_spec_models.rb +14 -8
- data/spec/mongoid/traversable_spec.rb +13 -35
- data/spec/mongoid/validatable/associated_spec.rb +27 -34
- data/spec/mongoid/validatable/presence_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +58 -31
- data/spec/mongoid/warnings_spec.rb +35 -0
- data/spec/mongoid_spec.rb +34 -16
- data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
- data/spec/rails/mongoid_spec.rb +4 -16
- data/spec/spec_helper.rb +5 -0
- data/spec/support/constraints.rb +24 -0
- data/spec/support/immutable_ids.rb +118 -0
- data/spec/support/macros.rb +78 -0
- data/spec/support/models/artist.rb +0 -1
- data/spec/support/models/augmentation.rb +12 -0
- data/spec/support/models/band.rb +5 -0
- data/spec/support/models/book.rb +1 -0
- data/spec/support/models/building.rb +2 -0
- data/spec/support/models/catalog.rb +24 -0
- data/spec/support/models/circus.rb +3 -0
- data/spec/support/models/cover.rb +10 -0
- data/spec/support/models/fanatic.rb +8 -0
- data/spec/support/models/implant.rb +9 -0
- data/spec/support/models/label.rb +2 -0
- data/spec/support/models/lat_lng.rb +6 -0
- data/spec/support/models/name.rb +10 -0
- data/spec/support/models/passport.rb +9 -0
- data/spec/support/models/person.rb +2 -0
- data/spec/support/models/player.rb +2 -0
- data/spec/support/models/powerup.rb +12 -0
- data/spec/support/models/product.rb +1 -0
- data/spec/support/models/purse.rb +9 -0
- data/spec/support/models/registry.rb +1 -0
- data/spec/support/models/school.rb +14 -0
- data/spec/support/models/shield.rb +18 -0
- data/spec/support/models/student.rb +14 -0
- data/spec/support/models/weapon.rb +12 -0
- metadata +98 -96
- checksums.yaml.gz.sig +0 -0
- data/lib/mongoid/errors/eager_load.rb +0 -23
- data/lib/mongoid/errors/invalid_value.rb +0 -17
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
- data/spec/mongoid/errors/eager_load_spec.rb +0 -31
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/bin/s3-copy +0 -45
- data/spec/shared/bin/s3-upload +0 -69
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -231
- data/spec/shared/lib/mrss/constraints.rb +0 -378
- data/spec/shared/lib/mrss/docker_runner.rb +0 -291
- data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
- data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -120
- data/spec/shared/lib/mrss/session_registry.rb +0 -69
- data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
- data/spec/shared/lib/mrss/utils.rb +0 -15
- data/spec/shared/share/Dockerfile.erb +0 -325
- data/spec/shared/share/haproxy-1.conf +0 -16
- data/spec/shared/share/haproxy-2.conf +0 -17
- data/spec/shared/shlib/config.sh +0 -27
- data/spec/shared/shlib/distro.sh +0 -74
- data/spec/shared/shlib/server.sh +0 -392
- data/spec/shared/shlib/set_env.sh +0 -169
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -3
@@ -44,39 +44,6 @@ describe Mongoid::Contextual::Mongo do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
describe "#cached?" do
|
48
|
-
|
49
|
-
context "when the criteria is cached" do
|
50
|
-
|
51
|
-
let(:criteria) do
|
52
|
-
Band.all.cache
|
53
|
-
end
|
54
|
-
|
55
|
-
let(:context) do
|
56
|
-
described_class.new(criteria)
|
57
|
-
end
|
58
|
-
|
59
|
-
it "returns true" do
|
60
|
-
expect(context).to be_cached
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context "when the criteria is not cached" do
|
65
|
-
|
66
|
-
let(:criteria) do
|
67
|
-
Band.all
|
68
|
-
end
|
69
|
-
|
70
|
-
let(:context) do
|
71
|
-
described_class.new(criteria)
|
72
|
-
end
|
73
|
-
|
74
|
-
it "returns false" do
|
75
|
-
expect(context).to_not be_cached
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
47
|
describe "#count" do
|
81
48
|
|
82
49
|
let!(:depeche) do
|
@@ -102,15 +69,17 @@ describe Mongoid::Contextual::Mongo do
|
|
102
69
|
end
|
103
70
|
end
|
104
71
|
|
105
|
-
context "when
|
72
|
+
context "when the query cache is enabled" do
|
73
|
+
query_cache_enabled
|
106
74
|
|
107
75
|
let(:context) do
|
108
|
-
described_class.new(criteria
|
76
|
+
described_class.new(criteria)
|
109
77
|
end
|
110
78
|
|
111
|
-
it "
|
112
|
-
|
113
|
-
|
79
|
+
it "only executes the count query once" do
|
80
|
+
expect_query(1) do
|
81
|
+
2.times { expect(context.count).to eq(1) }
|
82
|
+
end
|
114
83
|
end
|
115
84
|
end
|
116
85
|
|
@@ -189,6 +158,16 @@ describe Mongoid::Contextual::Mongo do
|
|
189
158
|
end
|
190
159
|
end
|
191
160
|
end
|
161
|
+
|
162
|
+
context 'when for_js is present' do
|
163
|
+
let(:context) do
|
164
|
+
Band.for_js('this.name == "Depeche Mode"')
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'counts the expected records' do
|
168
|
+
expect(context.count).to eq(1)
|
169
|
+
end
|
170
|
+
end
|
192
171
|
end
|
193
172
|
|
194
173
|
describe "#estimated_count" do
|
@@ -217,16 +196,18 @@ describe Mongoid::Contextual::Mongo do
|
|
217
196
|
end
|
218
197
|
end
|
219
198
|
|
220
|
-
context "when
|
199
|
+
context "when the query cache is enabled" do
|
200
|
+
query_cache_enabled
|
221
201
|
|
222
202
|
let(:context) do
|
223
|
-
described_class.new(criteria
|
203
|
+
described_class.new(criteria)
|
224
204
|
end
|
225
205
|
|
226
|
-
it "
|
227
|
-
|
228
|
-
|
229
|
-
|
206
|
+
it "the results are not cached" do
|
207
|
+
expect_query(2) do
|
208
|
+
2.times do
|
209
|
+
context.estimated_count
|
210
|
+
end
|
230
211
|
end
|
231
212
|
end
|
232
213
|
end
|
@@ -561,8 +542,22 @@ describe Mongoid::Contextual::Mongo do
|
|
561
542
|
context "when legacy_pluck_distinct is set" do
|
562
543
|
config_override :legacy_pluck_distinct, true
|
563
544
|
|
564
|
-
|
565
|
-
|
545
|
+
context 'when storing BigDecimal as string' do
|
546
|
+
config_override :map_big_decimal_to_decimal128, false
|
547
|
+
|
548
|
+
it "returns the non-demongoized distinct field values" do
|
549
|
+
expect(context.distinct(:sales).sort).to eq([ "1E2", "2E3" ])
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
context 'when storing BigDecimal as decimal128' do
|
554
|
+
config_override :map_big_decimal_to_decimal128, true
|
555
|
+
min_bson_version '4.15.0'
|
556
|
+
max_bson_version '4.99.99'
|
557
|
+
|
558
|
+
it "returns the non-demongoized distinct field values" do
|
559
|
+
expect(context.distinct(:sales).sort).to eq([ BSON::Decimal128.new("1E2"), BSON::Decimal128.new("2E3") ])
|
560
|
+
end
|
566
561
|
end
|
567
562
|
end
|
568
563
|
|
@@ -576,6 +571,8 @@ describe Mongoid::Contextual::Mongo do
|
|
576
571
|
end
|
577
572
|
|
578
573
|
context "when getting a localized field" do
|
574
|
+
with_default_i18n_configs
|
575
|
+
|
579
576
|
before do
|
580
577
|
I18n.locale = :en
|
581
578
|
d = Dictionary.create!(description: 'english-text')
|
@@ -584,10 +581,6 @@ describe Mongoid::Contextual::Mongo do
|
|
584
581
|
d.save!
|
585
582
|
end
|
586
583
|
|
587
|
-
after do
|
588
|
-
I18n.locale = :en
|
589
|
-
end
|
590
|
-
|
591
584
|
let(:criteria) do
|
592
585
|
Dictionary.criteria
|
593
586
|
end
|
@@ -680,16 +673,10 @@ describe Mongoid::Contextual::Mongo do
|
|
680
673
|
|
681
674
|
context 'when fallbacks are enabled with a locale list' do
|
682
675
|
require_fallbacks
|
676
|
+
with_default_i18n_configs
|
683
677
|
|
684
|
-
|
685
|
-
prev_fallbacks = I18n.fallbacks.dup
|
678
|
+
before do
|
686
679
|
I18n.fallbacks[:he] = [ :en ]
|
687
|
-
example.run
|
688
|
-
I18n.fallbacks = prev_fallbacks
|
689
|
-
end
|
690
|
-
|
691
|
-
after do
|
692
|
-
I18n.locale = :en
|
693
680
|
end
|
694
681
|
|
695
682
|
let(:distinct) do
|
@@ -709,7 +696,7 @@ describe Mongoid::Contextual::Mongo do
|
|
709
696
|
|
710
697
|
it "correctly uses the fallback" do
|
711
698
|
I18n.locale = :en
|
712
|
-
|
699
|
+
Dictionary.create!(description: 'english-text')
|
713
700
|
I18n.locale = :he
|
714
701
|
distinct.should == "english-text"
|
715
702
|
end
|
@@ -717,6 +704,8 @@ describe Mongoid::Contextual::Mongo do
|
|
717
704
|
end
|
718
705
|
|
719
706
|
context "when the localized field is embedded" do
|
707
|
+
with_default_i18n_configs
|
708
|
+
|
720
709
|
before do
|
721
710
|
p = Passport.new
|
722
711
|
I18n.locale = :en
|
@@ -727,10 +716,6 @@ describe Mongoid::Contextual::Mongo do
|
|
727
716
|
Person.create!(passport: p, employer_id: 12345)
|
728
717
|
end
|
729
718
|
|
730
|
-
after do
|
731
|
-
I18n.locale = :en
|
732
|
-
end
|
733
|
-
|
734
719
|
let(:criteria) do
|
735
720
|
Person.where(employer_id: 12345)
|
736
721
|
end
|
@@ -794,9 +779,11 @@ describe Mongoid::Contextual::Mongo do
|
|
794
779
|
|
795
780
|
context "when legacy_pluck_distinct is set" do
|
796
781
|
config_override :legacy_pluck_distinct, true
|
782
|
+
config_override :map_big_decimal_to_decimal128, true
|
783
|
+
max_bson_version '4.99.99'
|
797
784
|
|
798
785
|
it "returns the distinct matching fields" do
|
799
|
-
expect(context.distinct("label.sales")).to eq([
|
786
|
+
expect(context.distinct("label.sales")).to eq([ BSON::Decimal128.new('1E+2') ])
|
800
787
|
end
|
801
788
|
end
|
802
789
|
|
@@ -809,484 +796,860 @@ describe Mongoid::Contextual::Mongo do
|
|
809
796
|
end
|
810
797
|
end
|
811
798
|
|
812
|
-
describe "#
|
799
|
+
describe "#tally" do
|
800
|
+
let(:fans1) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
|
801
|
+
let(:fans2) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
|
802
|
+
let(:fans3) { [ Fanatic.new(age:1), Fanatic.new(age:3) ] }
|
813
803
|
|
814
|
-
|
815
|
-
|
816
|
-
|
804
|
+
let(:genres1) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 3 } ]}
|
805
|
+
let(:genres2) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 4 } ]}
|
806
|
+
let(:genres3) { [ { x: 1, y: { z: 1 } }, { x: 3, y: { z: 3 } }, { y: 5 } ]}
|
817
807
|
|
818
|
-
let(:
|
819
|
-
|
820
|
-
|
808
|
+
let(:label1) { Label.new(name: "Atlantic") }
|
809
|
+
let(:label2) { Label.new(name: "Atlantic") }
|
810
|
+
let(:label3) { Label.new(name: "Columbia") }
|
821
811
|
|
822
|
-
|
823
|
-
|
812
|
+
before do
|
813
|
+
Band.create!(origin: "tally", name: "Depeche Mode", years: 30, sales: "1E2", label: label1, genres: genres1)
|
814
|
+
Band.create!(origin: "tally", name: "New Order", years: 30, sales: "2E3", label: label2, genres: genres2)
|
815
|
+
Band.create!(origin: "tally", name: "10,000 Maniacs", years: 30, sales: "1E2", label: label3, genres: genres3)
|
816
|
+
Band.create!(origin: "tally2", fanatics: fans1, genres: [1, 2])
|
817
|
+
Band.create!(origin: "tally2", fanatics: fans2, genres: [1, 2])
|
818
|
+
Band.create!(origin: "tally2", fanatics: fans3, genres: [1, 3])
|
824
819
|
end
|
825
820
|
|
826
|
-
|
827
|
-
min_server_version '3.4'
|
821
|
+
let(:criteria) { Band.where(origin: "tally") }
|
828
822
|
|
829
|
-
|
830
|
-
|
823
|
+
context "when tallying a string" do
|
824
|
+
let(:tally) do
|
825
|
+
criteria.tally(:name)
|
831
826
|
end
|
832
827
|
|
833
|
-
it "
|
834
|
-
|
835
|
-
expect(doc).to be_a(Mongoid::Document)
|
836
|
-
end
|
828
|
+
it "returns the correct hash" do
|
829
|
+
expect(tally).to eq("Depeche Mode" => 1, "New Order" => 1, "10,000 Maniacs" => 1)
|
837
830
|
end
|
831
|
+
end
|
838
832
|
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
end
|
833
|
+
context "using an aliased field" do
|
834
|
+
let(:tally) do
|
835
|
+
criteria.tally(:years)
|
843
836
|
end
|
844
837
|
|
845
|
-
it "returns
|
846
|
-
expect(
|
838
|
+
it "returns the correct hash" do
|
839
|
+
expect(tally).to eq(30 => 3)
|
847
840
|
end
|
848
841
|
end
|
849
842
|
|
850
|
-
context "when
|
851
|
-
|
852
|
-
|
853
|
-
context.each do |doc|
|
854
|
-
expect(doc).to be_a(Mongoid::Document)
|
855
|
-
end
|
856
|
-
end
|
857
|
-
|
858
|
-
it "iterates over the matching documents" do
|
859
|
-
context.each do |doc|
|
860
|
-
expect(doc.name).to eq("Depeche Mode")
|
861
|
-
end
|
843
|
+
context "when tallying a demongoizable field" do
|
844
|
+
let(:tally) do
|
845
|
+
criteria.tally(:sales)
|
862
846
|
end
|
863
847
|
|
864
|
-
it "returns
|
865
|
-
expect(
|
848
|
+
it "returns the correct hash" do
|
849
|
+
expect(tally).to eq(BigDecimal("1E2") => 2, BigDecimal("2E3") => 1)
|
866
850
|
end
|
867
851
|
end
|
868
852
|
|
869
|
-
context "when
|
853
|
+
context "when tallying a localized field" do
|
854
|
+
with_default_i18n_configs
|
870
855
|
|
871
|
-
|
872
|
-
|
856
|
+
before do
|
857
|
+
I18n.locale = :en
|
858
|
+
d1 = Dictionary.create!(description: 'en1')
|
859
|
+
d2 = Dictionary.create!(description: 'en1')
|
860
|
+
d3 = Dictionary.create!(description: 'en1')
|
861
|
+
d4 = Dictionary.create!(description: 'en2')
|
862
|
+
I18n.locale = :de
|
863
|
+
d1.description = 'de1'
|
864
|
+
d2.description = 'de1'
|
865
|
+
d3.description = 'de2'
|
866
|
+
d4.description = 'de3'
|
867
|
+
d1.save!
|
868
|
+
d2.save!
|
869
|
+
d3.save!
|
870
|
+
d4.save!
|
871
|
+
I18n.locale = :en
|
873
872
|
end
|
874
873
|
|
875
|
-
|
876
|
-
|
874
|
+
context "when getting the demongoized field" do
|
875
|
+
let(:tallied) do
|
876
|
+
Dictionary.tally(:description)
|
877
|
+
end
|
878
|
+
|
879
|
+
it "returns the translation for the current locale" do
|
880
|
+
expect(tallied).to eq("en1" => 3, "en2" => 1)
|
881
|
+
end
|
877
882
|
end
|
878
883
|
|
879
|
-
context "when
|
884
|
+
context "when getting a specific locale" do
|
885
|
+
let(:tallied) do
|
886
|
+
Dictionary.tally("description.de")
|
887
|
+
end
|
880
888
|
|
881
|
-
|
889
|
+
it "returns the translation for the the specific locale" do
|
890
|
+
expect(tallied).to eq("de1" => 2, "de2" => 1, "de3" => 1)
|
891
|
+
end
|
892
|
+
end
|
882
893
|
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
end
|
887
|
-
end
|
894
|
+
context "when getting the full hash" do
|
895
|
+
let(:tallied) do
|
896
|
+
Dictionary.tally("description_translations")
|
888
897
|
end
|
889
898
|
|
890
|
-
|
899
|
+
it "returns the correct hash" do
|
900
|
+
expect(tallied).to eq(
|
901
|
+
{"de" => "de1", "en" => "en1" } => 2,
|
902
|
+
{"de" => "de2", "en" => "en1" } => 1,
|
903
|
+
{"de" => "de3", "en" => "en2" } => 1
|
904
|
+
)
|
905
|
+
end
|
906
|
+
end
|
907
|
+
end
|
891
908
|
|
892
|
-
|
893
|
-
|
894
|
-
end
|
909
|
+
context "when tallying an embedded localized field" do
|
910
|
+
with_default_i18n_configs
|
895
911
|
|
896
|
-
|
897
|
-
|
898
|
-
|
912
|
+
before do
|
913
|
+
I18n.locale = :en
|
914
|
+
address1a = Address.new(name: "en1")
|
915
|
+
address1b = Address.new(name: "en2")
|
916
|
+
address2a = Address.new(name: "en1")
|
917
|
+
address2b = Address.new(name: "en3")
|
918
|
+
I18n.locale = :de
|
919
|
+
address1a.name = "de1"
|
920
|
+
address1b.name = "de2"
|
921
|
+
address2a.name = "de1"
|
922
|
+
address2b.name = "de3"
|
923
|
+
Person.create!(addresses: [ address1a, address1b ])
|
924
|
+
Person.create!(addresses: [ address2a, address2b ])
|
925
|
+
I18n.locale = :en
|
926
|
+
end
|
899
927
|
|
900
|
-
|
901
|
-
|
902
|
-
|
928
|
+
context "when getting the demongoized field" do
|
929
|
+
let(:tallied) do
|
930
|
+
Person.tally("addresses.name")
|
931
|
+
end
|
903
932
|
|
904
|
-
|
905
|
-
|
906
|
-
|
933
|
+
it "returns the translation for the current locale" do
|
934
|
+
expect(tallied).to eq(
|
935
|
+
[ "en1", "en2" ] => 1,
|
936
|
+
[ "en1", "en3" ] => 1,
|
937
|
+
)
|
938
|
+
end
|
939
|
+
end
|
907
940
|
|
908
|
-
|
941
|
+
context "when getting a specific locale" do
|
942
|
+
let(:tallied) do
|
943
|
+
Person.tally("addresses.name.de")
|
944
|
+
end
|
909
945
|
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
evt.command_name == 'getMore'
|
916
|
-
end
|
917
|
-
expect(get_more_events.length).to be(0)
|
918
|
-
ensure
|
919
|
-
context.view.client.unsubscribe(Mongo::Monitoring::COMMAND, subscriber)
|
920
|
-
end
|
946
|
+
it "returns the translation for the the specific locale" do
|
947
|
+
expect(tallied).to eq(
|
948
|
+
[ "de1", "de2" ] => 1,
|
949
|
+
[ "de1", "de3" ] => 1,
|
950
|
+
)
|
921
951
|
end
|
922
952
|
end
|
923
|
-
end
|
924
953
|
|
925
|
-
|
954
|
+
context "when getting the full hash" do
|
955
|
+
let(:tallied) do
|
956
|
+
Person.tally("addresses.name_translations")
|
957
|
+
end
|
926
958
|
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
959
|
+
it "returns the correct hash" do
|
960
|
+
expect(tallied).to eq(
|
961
|
+
[{ "de" => "de1", "en" => "en1" }, { "de" => "de2", "en" => "en2" }] => 1,
|
962
|
+
[{ "de" => "de1", "en" => "en1" }, { "de" => "de3", "en" => "en3" }] => 1,
|
963
|
+
)
|
964
|
+
end
|
931
965
|
end
|
932
966
|
|
933
|
-
|
934
|
-
|
967
|
+
end
|
968
|
+
|
969
|
+
context "when tallying an embedded field" do
|
970
|
+
let(:tally) do
|
971
|
+
criteria.tally("label.name")
|
935
972
|
end
|
936
973
|
|
937
|
-
|
938
|
-
|
974
|
+
it "returns the correct hash" do
|
975
|
+
expect(tally).to eq("Atlantic" => 2, "Columbia" => 1)
|
939
976
|
end
|
977
|
+
end
|
940
978
|
|
941
|
-
|
942
|
-
|
979
|
+
context "when tallying an element in an embeds_many field" do
|
980
|
+
let(:criteria) { Band.where(origin: "tally2") }
|
981
|
+
|
982
|
+
let(:tally) do
|
983
|
+
criteria.tally("fanatics.age")
|
943
984
|
end
|
944
985
|
|
945
|
-
it
|
946
|
-
expect(
|
986
|
+
it "returns the correct hash" do
|
987
|
+
expect(tally).to eq(
|
988
|
+
[1, 2] => 2,
|
989
|
+
[1, 3] => 1
|
990
|
+
)
|
947
991
|
end
|
948
992
|
end
|
949
|
-
end
|
950
993
|
|
951
|
-
|
994
|
+
context "when tallying an embeds_many field" do
|
995
|
+
let(:criteria) { Band.where(origin: "tally2") }
|
952
996
|
|
953
|
-
|
954
|
-
|
955
|
-
|
997
|
+
let(:tally) do
|
998
|
+
criteria.tally("fanatics")
|
999
|
+
end
|
956
1000
|
|
957
|
-
|
958
|
-
|
1001
|
+
it "returns the correct hash" do
|
1002
|
+
expect(tally).to eq(
|
1003
|
+
fans1.map(&:attributes) => 1,
|
1004
|
+
fans2.map(&:attributes) => 1,
|
1005
|
+
fans3.map(&:attributes) => 1,
|
1006
|
+
)
|
1007
|
+
end
|
959
1008
|
end
|
960
1009
|
|
961
|
-
context "when
|
1010
|
+
context "when tallying a field of type array" do
|
1011
|
+
let(:criteria) { Band.where(origin: "tally2") }
|
962
1012
|
|
963
|
-
let(:
|
964
|
-
|
1013
|
+
let(:tally) do
|
1014
|
+
criteria.tally("genres")
|
965
1015
|
end
|
966
1016
|
|
967
|
-
it "
|
968
|
-
expect(
|
969
|
-
|
1017
|
+
it "returns the correct hash" do
|
1018
|
+
expect(tally).to eq(
|
1019
|
+
[1, 2] => 2,
|
1020
|
+
[1, 3] => 1
|
1021
|
+
)
|
970
1022
|
end
|
971
1023
|
end
|
972
|
-
end
|
973
1024
|
|
974
|
-
|
1025
|
+
context "when tallying an element from an array of hashes" do
|
1026
|
+
let(:criteria) { Band.where(origin: "tally") }
|
975
1027
|
|
976
|
-
|
977
|
-
|
1028
|
+
let(:tally) do
|
1029
|
+
criteria.tally("genres.x")
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
it "returns the correct hash without the nil keys" do
|
1033
|
+
expect(tally).to eq(
|
1034
|
+
[1, 2] => 2,
|
1035
|
+
[1, 3] => 1
|
1036
|
+
)
|
1037
|
+
end
|
978
1038
|
end
|
979
1039
|
|
980
|
-
context "when
|
1040
|
+
context "when tallying an element from an array of hashes; with duplicate" do
|
981
1041
|
|
982
|
-
|
983
|
-
Band.
|
1042
|
+
before do
|
1043
|
+
Band.create!(origin: "tally", genres: [ { x: 1 }, {x: 1} ] )
|
984
1044
|
end
|
985
1045
|
|
986
|
-
let(:
|
987
|
-
|
1046
|
+
let(:criteria) { Band.where(origin: "tally") }
|
1047
|
+
|
1048
|
+
let(:tally) do
|
1049
|
+
criteria.tally("genres.x")
|
988
1050
|
end
|
989
1051
|
|
990
|
-
it "returns
|
991
|
-
expect(
|
1052
|
+
it "returns the correct hash without the nil keys" do
|
1053
|
+
expect(tally).to eq(
|
1054
|
+
[1, 2] => 2,
|
1055
|
+
[1, 3] => 1,
|
1056
|
+
[1, 1] => 1,
|
1057
|
+
)
|
992
1058
|
end
|
993
1059
|
end
|
994
1060
|
|
995
|
-
context "when
|
1061
|
+
context "when tallying an aliased field of type array" do
|
996
1062
|
|
997
|
-
|
998
|
-
|
1063
|
+
before do
|
1064
|
+
Person.create!(array: [ 1, 2 ])
|
1065
|
+
Person.create!(array: [ 1, 3 ])
|
999
1066
|
end
|
1000
1067
|
|
1001
|
-
let(:
|
1002
|
-
|
1068
|
+
let(:tally) do
|
1069
|
+
Person.tally("array")
|
1003
1070
|
end
|
1004
1071
|
|
1005
|
-
it "returns
|
1006
|
-
expect(
|
1072
|
+
it "returns the correct hash" do
|
1073
|
+
expect(tally).to eq(
|
1074
|
+
[1, 2] => 1,
|
1075
|
+
[1, 3] => 1
|
1076
|
+
)
|
1007
1077
|
end
|
1008
1078
|
end
|
1009
1079
|
|
1010
|
-
context "when
|
1080
|
+
context "when going multiple levels deep in arrays" do
|
1081
|
+
let(:criteria) { Band.where(origin: "tally") }
|
1011
1082
|
|
1012
|
-
let(:
|
1013
|
-
|
1083
|
+
let(:tally) do
|
1084
|
+
criteria.tally("genres.y.z")
|
1014
1085
|
end
|
1015
1086
|
|
1016
|
-
|
1017
|
-
|
1087
|
+
it "returns the correct hash" do
|
1088
|
+
expect(tally).to eq(
|
1089
|
+
[1, 2] => 2,
|
1090
|
+
[1, 3] => 1
|
1091
|
+
)
|
1018
1092
|
end
|
1093
|
+
end
|
1019
1094
|
|
1020
|
-
|
1095
|
+
context "when going multiple levels deep in an array" do
|
1096
|
+
let(:criteria) { Band.where(origin: "tally") }
|
1021
1097
|
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1098
|
+
let(:tally) do
|
1099
|
+
criteria.tally("genres.y.z")
|
1100
|
+
end
|
1025
1101
|
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1102
|
+
it "returns the correct hash" do
|
1103
|
+
expect(tally).to eq(
|
1104
|
+
[1, 2] => 2,
|
1105
|
+
[1, 3] => 1
|
1106
|
+
)
|
1030
1107
|
end
|
1031
1108
|
end
|
1032
1109
|
|
1033
|
-
context "when
|
1110
|
+
context "when tallying deeply nested arrays/embedded associations" do
|
1034
1111
|
|
1035
|
-
|
1036
|
-
|
1112
|
+
before do
|
1113
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
|
1114
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
|
1115
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
|
1037
1116
|
end
|
1038
1117
|
|
1039
|
-
let(:
|
1040
|
-
|
1118
|
+
let(:tally) do
|
1119
|
+
Person.tally("addresses.code.deepest.array.y.z")
|
1041
1120
|
end
|
1042
1121
|
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
it "does not hit the database" do
|
1050
|
-
expect(context).to receive(:view).never
|
1051
|
-
expect(context).to be_exists
|
1052
|
-
end
|
1122
|
+
it "returns the correct hash" do
|
1123
|
+
expect(tally).to eq(
|
1124
|
+
[ [ 1, 2 ] ] => 2,
|
1125
|
+
[ [ 1, 3 ] ] => 1
|
1126
|
+
)
|
1053
1127
|
end
|
1128
|
+
end
|
1054
1129
|
|
1055
|
-
|
1130
|
+
context "when tallying deeply nested arrays/embedded associations" do
|
1056
1131
|
|
1057
|
-
|
1132
|
+
before do
|
1133
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
|
1134
|
+
Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
|
1135
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
|
1136
|
+
Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
|
1137
|
+
Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))),
|
1138
|
+
Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
|
1139
|
+
end
|
1058
1140
|
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1141
|
+
let(:tally) do
|
1142
|
+
Person.tally("addresses.code.deepest.array.y.z")
|
1143
|
+
end
|
1062
1144
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1145
|
+
it "returns the correct hash" do
|
1146
|
+
expect(tally).to eq(
|
1147
|
+
[ [ 1, 2 ], [ 1, 2 ] ] => 2,
|
1148
|
+
[ [ 1, 3 ], [ 1, 3 ] ] => 1
|
1149
|
+
)
|
1068
1150
|
end
|
1069
1151
|
end
|
1070
|
-
end
|
1071
1152
|
|
1072
|
-
|
1153
|
+
context "when some keys are missing" do
|
1154
|
+
before do
|
1155
|
+
3.times { Band.create!(origin: "tally") }
|
1156
|
+
end
|
1073
1157
|
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1158
|
+
let(:tally) do
|
1159
|
+
criteria.tally(:name)
|
1160
|
+
end
|
1077
1161
|
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1162
|
+
it "returns the correct hash" do
|
1163
|
+
expect(tally).to eq(
|
1164
|
+
"Depeche Mode" => 1,
|
1165
|
+
"New Order" => 1,
|
1166
|
+
"10,000 Maniacs" => 1,
|
1167
|
+
nil => 3
|
1168
|
+
)
|
1169
|
+
end
|
1084
1170
|
end
|
1085
|
-
end
|
1086
1171
|
|
1087
|
-
|
1172
|
+
context "when the first element is an embeds_one" do
|
1173
|
+
before do
|
1174
|
+
Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ]))
|
1175
|
+
Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ]))
|
1176
|
+
Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 3) ]))
|
1177
|
+
end
|
1088
1178
|
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1179
|
+
let(:tally) do
|
1180
|
+
Person.tally("name.translations.language")
|
1181
|
+
end
|
1092
1182
|
|
1093
|
-
|
1094
|
-
|
1183
|
+
it "returns the correct hash" do
|
1184
|
+
expect(tally).to eq(
|
1185
|
+
[1, 2] => 2,
|
1186
|
+
[1, 3] => 1
|
1187
|
+
)
|
1188
|
+
end
|
1095
1189
|
end
|
1096
1190
|
|
1097
|
-
context "when
|
1098
|
-
|
1099
|
-
context "when not providing options" do
|
1191
|
+
context "when tallying demongoizable values from typeless fields" do
|
1100
1192
|
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1193
|
+
let!(:person1) { Person.create!(ssn: /hello/) }
|
1194
|
+
let!(:person2) { Person.create!(ssn: BSON::Decimal128.new("1")) }
|
1195
|
+
let(:tally) { Person.tally("ssn") }
|
1104
1196
|
|
1105
|
-
|
1106
|
-
|
1197
|
+
let(:tallied_classes) do
|
1198
|
+
tally.keys.map(&:class).sort do |a, b|
|
1199
|
+
a.to_s.casecmp(b.to_s)
|
1107
1200
|
end
|
1201
|
+
end
|
1108
1202
|
|
1109
|
-
|
1110
|
-
|
1111
|
-
end
|
1203
|
+
context "< BSON 5" do
|
1204
|
+
max_bson_version '4.99.99'
|
1112
1205
|
|
1113
|
-
it "
|
1114
|
-
expect(
|
1206
|
+
it "stores the correct types in the database" do
|
1207
|
+
expect(Person.find(person1.id).attributes["ssn"]).to be_a BSON::Regexp::Raw
|
1208
|
+
expect(Person.find(person2.id).attributes["ssn"]).to be_a BSON::Decimal128
|
1115
1209
|
end
|
1116
1210
|
|
1117
|
-
it "
|
1118
|
-
expect(
|
1211
|
+
it "tallies the correct type" do
|
1212
|
+
expect(tallied_classes).to be == [ BSON::Decimal128, BSON::Regexp::Raw ]
|
1119
1213
|
end
|
1120
1214
|
end
|
1121
1215
|
|
1122
|
-
context
|
1216
|
+
context '>= BSON 5' do
|
1217
|
+
min_bson_version "5.0"
|
1123
1218
|
|
1124
|
-
|
1125
|
-
|
1219
|
+
it "stores the correct types in the database" do
|
1220
|
+
expect(Person.find(person1.id).ssn).to be_a BSON::Regexp::Raw
|
1221
|
+
expect(Person.find(person2.id).ssn).to be_a BigDecimal
|
1126
1222
|
end
|
1127
1223
|
|
1128
|
-
|
1129
|
-
|
1224
|
+
it "tallies the correct type" do
|
1225
|
+
expect(tallied_classes).to be == [ BigDecimal, BSON::Regexp::Raw ]
|
1130
1226
|
end
|
1227
|
+
end
|
1131
1228
|
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1229
|
+
context '>= BSON 5 with decimal128 allowed' do
|
1230
|
+
min_bson_version "5.0"
|
1231
|
+
config_override :allow_bson5_decimal128, true
|
1135
1232
|
|
1136
|
-
it "
|
1137
|
-
expect(
|
1233
|
+
it "stores the correct types in the database" do
|
1234
|
+
expect(Person.find(person1.id).ssn).to be_a BSON::Regexp::Raw
|
1235
|
+
expect(Person.find(person2.id).ssn).to be_a BSON::Decimal128
|
1138
1236
|
end
|
1139
1237
|
|
1140
|
-
it "
|
1141
|
-
expect(
|
1142
|
-
expect(tool.reload.name).to be_nil
|
1238
|
+
it "tallies the correct type" do
|
1239
|
+
expect(tallied_classes).to be == [ BSON::Decimal128, BSON::Regexp::Raw ]
|
1143
1240
|
end
|
1144
1241
|
end
|
1242
|
+
end
|
1243
|
+
end
|
1145
1244
|
|
1146
|
-
|
1245
|
+
describe "#each" do
|
1147
1246
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1247
|
+
before do
|
1248
|
+
Band.create!(name: "Depeche Mode")
|
1249
|
+
end
|
1151
1250
|
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1251
|
+
let(:criteria) do
|
1252
|
+
Band.where(name: "Depeche Mode")
|
1253
|
+
end
|
1155
1254
|
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1255
|
+
let(:context) do
|
1256
|
+
described_class.new(criteria)
|
1257
|
+
end
|
1159
1258
|
|
1160
|
-
|
1161
|
-
|
1162
|
-
end
|
1259
|
+
context 'when the criteria has a collation' do
|
1260
|
+
min_server_version '3.4'
|
1163
1261
|
|
1164
|
-
|
1165
|
-
|
1262
|
+
let(:criteria) do
|
1263
|
+
Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
it "yields mongoid documents to the block" do
|
1267
|
+
context.each do |doc|
|
1268
|
+
expect(doc).to be_a(Mongoid::Document)
|
1166
1269
|
end
|
1270
|
+
end
|
1167
1271
|
|
1168
|
-
|
1169
|
-
|
1272
|
+
it "iterates over the matching documents" do
|
1273
|
+
context.each do |doc|
|
1274
|
+
expect(doc.name).to eq("Depeche Mode")
|
1170
1275
|
end
|
1171
1276
|
end
|
1172
1277
|
|
1173
|
-
|
1278
|
+
it "returns self" do
|
1279
|
+
expect(context.each{}).to be(context)
|
1280
|
+
end
|
1281
|
+
end
|
1174
1282
|
|
1175
|
-
|
1176
|
-
Band.where(name: "Depeche Mode")
|
1177
|
-
end
|
1283
|
+
context "when providing a block" do
|
1178
1284
|
|
1179
|
-
|
1180
|
-
|
1285
|
+
it "yields mongoid documents to the block" do
|
1286
|
+
context.each do |doc|
|
1287
|
+
expect(doc).to be_a(Mongoid::Document)
|
1181
1288
|
end
|
1289
|
+
end
|
1182
1290
|
|
1183
|
-
|
1184
|
-
|
1291
|
+
it "iterates over the matching documents" do
|
1292
|
+
context.each do |doc|
|
1293
|
+
expect(doc.name).to eq("Depeche Mode")
|
1185
1294
|
end
|
1295
|
+
end
|
1186
1296
|
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1297
|
+
it "returns self" do
|
1298
|
+
expect(context.each{}).to be(context)
|
1299
|
+
end
|
1300
|
+
end
|
1190
1301
|
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1302
|
+
context "when no block is provided" do
|
1303
|
+
|
1304
|
+
let(:enum) do
|
1305
|
+
context.each
|
1195
1306
|
end
|
1196
1307
|
|
1197
|
-
|
1198
|
-
|
1308
|
+
it "returns an enumerator" do
|
1309
|
+
expect(enum).to be_a(Enumerator)
|
1310
|
+
end
|
1199
1311
|
|
1200
|
-
|
1201
|
-
Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
|
1202
|
-
end
|
1312
|
+
context "when iterating over the enumerator" do
|
1203
1313
|
|
1204
|
-
|
1205
|
-
described_class.new(criteria)
|
1206
|
-
end
|
1314
|
+
context "when iterating with each" do
|
1207
1315
|
|
1208
|
-
|
1209
|
-
|
1316
|
+
it "yields mongoid documents to the block" do
|
1317
|
+
enum.each do |doc|
|
1318
|
+
expect(doc).to be_a(Mongoid::Document)
|
1319
|
+
end
|
1320
|
+
end
|
1210
1321
|
end
|
1211
1322
|
|
1212
|
-
|
1213
|
-
expect(result).to eq(depeche)
|
1214
|
-
end
|
1323
|
+
context "when iterating with next" do
|
1215
1324
|
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1325
|
+
before do
|
1326
|
+
10.times { |i| Band.create!(name: "Test #{i}") }
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
let(:criteria) do
|
1330
|
+
Band.batch_size(5)
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
it "yields mongoid documents" do
|
1334
|
+
expect(enum.next).to be_a(Mongoid::Document)
|
1335
|
+
end
|
1336
|
+
|
1337
|
+
it "does not load all documents" do
|
1338
|
+
subscriber = Mrss::EventSubscriber.new
|
1339
|
+
context.view.client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
|
1340
|
+
|
1341
|
+
enum.next
|
1342
|
+
|
1343
|
+
find_events = subscriber.all_events.select do |evt|
|
1344
|
+
evt.command_name == 'find'
|
1345
|
+
end
|
1346
|
+
expect(find_events.length).to be(2)
|
1347
|
+
get_more_events = subscriber.all_events.select do |evt|
|
1348
|
+
evt.command_name == 'getMore'
|
1349
|
+
end
|
1350
|
+
expect(get_more_events.length).to be(0)
|
1351
|
+
ensure
|
1352
|
+
context.view.client.unsubscribe(Mongo::Monitoring::COMMAND, subscriber)
|
1353
|
+
end
|
1219
1354
|
end
|
1220
1355
|
end
|
1221
1356
|
end
|
1222
1357
|
|
1223
|
-
context
|
1358
|
+
context 'when the criteria has a parent document' do
|
1224
1359
|
|
1225
|
-
|
1226
|
-
|
1360
|
+
before do
|
1361
|
+
Post.create!(person: person)
|
1362
|
+
Post.create!(person: person)
|
1363
|
+
Post.create!(person: person)
|
1227
1364
|
end
|
1228
1365
|
|
1229
|
-
let(:
|
1230
|
-
|
1366
|
+
let(:person) do
|
1367
|
+
Person.new
|
1231
1368
|
end
|
1232
1369
|
|
1233
|
-
let(:
|
1234
|
-
|
1370
|
+
let(:criteria) do
|
1371
|
+
person.posts.all
|
1235
1372
|
end
|
1236
1373
|
|
1237
|
-
|
1238
|
-
|
1374
|
+
let(:persons) do
|
1375
|
+
criteria.collect(&:person)
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
it 'sets the same parent object on each related object' do
|
1379
|
+
expect(persons.uniq.size).to eq(1)
|
1239
1380
|
end
|
1240
1381
|
end
|
1241
1382
|
end
|
1242
1383
|
|
1243
|
-
describe "#
|
1384
|
+
describe "#eager_load" do
|
1244
1385
|
|
1245
|
-
let
|
1246
|
-
|
1386
|
+
let(:criteria) do
|
1387
|
+
Person.includes(:game)
|
1247
1388
|
end
|
1248
1389
|
|
1249
|
-
let
|
1250
|
-
|
1390
|
+
let(:context) do
|
1391
|
+
described_class.new(criteria)
|
1251
1392
|
end
|
1252
1393
|
|
1253
|
-
context "when
|
1394
|
+
context "when no documents are returned" do
|
1254
1395
|
|
1255
|
-
|
1396
|
+
let(:game_association) do
|
1397
|
+
Person.reflect_on_association(:game)
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
it "does not make any additional database queries" do
|
1401
|
+
expect(game_association).to receive(:eager_load).never
|
1402
|
+
context.send(:eager_load, [])
|
1403
|
+
end
|
1404
|
+
end
|
1405
|
+
end
|
1406
|
+
|
1407
|
+
describe "#exists?" do
|
1408
|
+
|
1409
|
+
let!(:band) do
|
1410
|
+
Band.create!(name: "Depeche Mode", active: true)
|
1411
|
+
end
|
1412
|
+
|
1413
|
+
context "when not passing options" do
|
1414
|
+
|
1415
|
+
context "when the count is zero" do
|
1256
1416
|
|
1257
1417
|
let(:criteria) do
|
1258
|
-
Band.where(name: "
|
1418
|
+
Band.where(name: "New Order")
|
1259
1419
|
end
|
1260
1420
|
|
1261
1421
|
let(:context) do
|
1262
1422
|
described_class.new(criteria)
|
1263
1423
|
end
|
1264
1424
|
|
1265
|
-
|
1266
|
-
context.
|
1267
|
-
end
|
1268
|
-
|
1269
|
-
it "returns the first matching document" do
|
1270
|
-
expect(result).to eq(depeche)
|
1271
|
-
end
|
1272
|
-
|
1273
|
-
it "updates the document in the database" do
|
1274
|
-
expect(depeche.reload.likes).to eq(1)
|
1425
|
+
it "returns false" do
|
1426
|
+
expect(context).to_not be_exists
|
1275
1427
|
end
|
1276
1428
|
end
|
1277
1429
|
|
1278
|
-
context "when
|
1430
|
+
context "when the count is greater than zero" do
|
1279
1431
|
|
1280
1432
|
let(:criteria) do
|
1281
|
-
Band.
|
1433
|
+
Band.where(name: "Depeche Mode")
|
1282
1434
|
end
|
1283
1435
|
|
1284
1436
|
let(:context) do
|
1285
1437
|
described_class.new(criteria)
|
1286
1438
|
end
|
1287
1439
|
|
1288
|
-
|
1289
|
-
context.
|
1440
|
+
it "returns true" do
|
1441
|
+
expect(context).to be_exists
|
1442
|
+
end
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
context "when caching is not enabled" do
|
1446
|
+
|
1447
|
+
let(:criteria) do
|
1448
|
+
Band.where(name: "Depeche Mode")
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
let(:context) do
|
1452
|
+
described_class.new(criteria)
|
1453
|
+
end
|
1454
|
+
|
1455
|
+
context "when exists? already called and query cache is enabled" do
|
1456
|
+
query_cache_enabled
|
1457
|
+
|
1458
|
+
before do
|
1459
|
+
context.exists?
|
1460
|
+
end
|
1461
|
+
|
1462
|
+
it "does not hit the database again" do
|
1463
|
+
expect_no_queries do
|
1464
|
+
expect(context).to be_exists
|
1465
|
+
end
|
1466
|
+
end
|
1467
|
+
end
|
1468
|
+
end
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
context "when passing an _id" do
|
1472
|
+
|
1473
|
+
context "when its of type BSON::ObjectId" do
|
1474
|
+
|
1475
|
+
context "when calling it on the class" do
|
1476
|
+
|
1477
|
+
it "returns true" do
|
1478
|
+
expect(Band.exists?(band._id)).to be true
|
1479
|
+
end
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
context "when calling it on a criteria that includes the object" do
|
1483
|
+
|
1484
|
+
it "returns true" do
|
1485
|
+
expect(Band.where(name: band.name).exists?(band._id)).to be true
|
1486
|
+
end
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
context "when calling it on a criteria that does not include the object" do
|
1490
|
+
|
1491
|
+
it "returns false" do
|
1492
|
+
expect(Band.where(name: "bogus").exists?(band._id)).to be false
|
1493
|
+
end
|
1494
|
+
end
|
1495
|
+
|
1496
|
+
context "when the id does not exist" do
|
1497
|
+
|
1498
|
+
it "returns false" do
|
1499
|
+
expect(Band.exists?(BSON::ObjectId.new)).to be false
|
1500
|
+
end
|
1501
|
+
end
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
context "when its of type String" do
|
1505
|
+
|
1506
|
+
context "when the id exists" do
|
1507
|
+
|
1508
|
+
it "returns true" do
|
1509
|
+
expect(Band.exists?(band._id.to_s)).to be true
|
1510
|
+
end
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
context "when the id does not exist" do
|
1514
|
+
|
1515
|
+
it "returns false" do
|
1516
|
+
expect(Band.exists?(BSON::ObjectId.new.to_s)).to be false
|
1517
|
+
end
|
1518
|
+
end
|
1519
|
+
end
|
1520
|
+
end
|
1521
|
+
|
1522
|
+
context "when passing a hash" do
|
1523
|
+
|
1524
|
+
context "when calling it on the class" do
|
1525
|
+
|
1526
|
+
it "returns true" do
|
1527
|
+
expect(Band.exists?(name: band.name)).to be true
|
1528
|
+
end
|
1529
|
+
end
|
1530
|
+
|
1531
|
+
context "when calling it on a criteria that includes the object" do
|
1532
|
+
|
1533
|
+
it "returns true" do
|
1534
|
+
expect(Band.where(active: true).exists?(name: band.name)).to be true
|
1535
|
+
end
|
1536
|
+
end
|
1537
|
+
|
1538
|
+
context "when calling it on a criteria that does not include the object" do
|
1539
|
+
|
1540
|
+
it "returns false" do
|
1541
|
+
expect(Band.where(active: false).exists?(name: band.name)).to be false
|
1542
|
+
end
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
context "when the conditions don't match" do
|
1546
|
+
|
1547
|
+
it "returns false" do
|
1548
|
+
expect(Band.exists?(name: "bogus")).to be false
|
1549
|
+
end
|
1550
|
+
end
|
1551
|
+
end
|
1552
|
+
|
1553
|
+
context "when passing false" do
|
1554
|
+
|
1555
|
+
it "returns false" do
|
1556
|
+
expect(Band.exists?(false)).to be false
|
1557
|
+
end
|
1558
|
+
end
|
1559
|
+
|
1560
|
+
context "when passing nil" do
|
1561
|
+
|
1562
|
+
it "returns false" do
|
1563
|
+
expect(Band.exists?(nil)).to be false
|
1564
|
+
end
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
context "when the limit is 0" do
|
1568
|
+
|
1569
|
+
it "returns false" do
|
1570
|
+
expect(Band.limit(0).exists?).to be false
|
1571
|
+
end
|
1572
|
+
end
|
1573
|
+
|
1574
|
+
context "when the criteria limit is 0" do
|
1575
|
+
|
1576
|
+
it "returns false" do
|
1577
|
+
expect(Band.criteria.limit(0).exists?).to be false
|
1578
|
+
end
|
1579
|
+
end
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
describe "#explain" do
|
1583
|
+
|
1584
|
+
let(:criteria) do
|
1585
|
+
Band.where(name: "Depeche Mode")
|
1586
|
+
end
|
1587
|
+
|
1588
|
+
let(:context) do
|
1589
|
+
described_class.new(criteria)
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
it "returns the criteria explain path" do
|
1593
|
+
explain = context.explain
|
1594
|
+
expect(explain).to_not be_empty
|
1595
|
+
expect(explain.keys).to include("queryPlanner", "executionStats", "serverInfo")
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
it "respects options passed to explain" do
|
1599
|
+
explain = context.explain(verbosity: :query_planner)
|
1600
|
+
expect(explain).to_not be_empty
|
1601
|
+
expect(explain.keys).to include("queryPlanner", "serverInfo")
|
1602
|
+
expect(explain.keys).not_to include("executionStats")
|
1603
|
+
end
|
1604
|
+
end
|
1605
|
+
|
1606
|
+
describe "#find_one_and_replace" do
|
1607
|
+
|
1608
|
+
let!(:depeche) do
|
1609
|
+
Band.create!(name: "Depeche Mode")
|
1610
|
+
end
|
1611
|
+
|
1612
|
+
let!(:tool) do
|
1613
|
+
Band.create!(name: "Tool")
|
1614
|
+
end
|
1615
|
+
|
1616
|
+
context "when the selector matches" do
|
1617
|
+
|
1618
|
+
context "when not providing options" do
|
1619
|
+
|
1620
|
+
let(:criteria) do
|
1621
|
+
Band.where(name: "Depeche Mode")
|
1622
|
+
end
|
1623
|
+
|
1624
|
+
let(:context) do
|
1625
|
+
described_class.new(criteria)
|
1626
|
+
end
|
1627
|
+
|
1628
|
+
let!(:result) do
|
1629
|
+
context.find_one_and_replace(name: 'FKA Twigs')
|
1630
|
+
end
|
1631
|
+
|
1632
|
+
it "returns the first matching document" do
|
1633
|
+
expect(result).to eq(depeche)
|
1634
|
+
end
|
1635
|
+
|
1636
|
+
it "updates the document in the database" do
|
1637
|
+
expect(depeche.reload.name).to eq('FKA Twigs')
|
1638
|
+
end
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
context "when sorting" do
|
1642
|
+
|
1643
|
+
let(:criteria) do
|
1644
|
+
Band.desc(:name)
|
1645
|
+
end
|
1646
|
+
|
1647
|
+
let(:context) do
|
1648
|
+
described_class.new(criteria)
|
1649
|
+
end
|
1650
|
+
|
1651
|
+
let!(:result) do
|
1652
|
+
context.find_one_and_replace(likes: 1)
|
1290
1653
|
end
|
1291
1654
|
|
1292
1655
|
it "returns the first matching document" do
|
@@ -1295,6 +1658,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1295
1658
|
|
1296
1659
|
it "updates the document in the database" do
|
1297
1660
|
expect(tool.reload.likes).to eq(1)
|
1661
|
+
expect(tool.reload.name).to be_nil
|
1298
1662
|
end
|
1299
1663
|
end
|
1300
1664
|
|
@@ -1309,7 +1673,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1309
1673
|
end
|
1310
1674
|
|
1311
1675
|
let!(:result) do
|
1312
|
-
context.
|
1676
|
+
context.find_one_and_replace(name: 'FKA Twigs', likes: 1)
|
1313
1677
|
end
|
1314
1678
|
|
1315
1679
|
it "returns the first matching document" do
|
@@ -1336,7 +1700,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1336
1700
|
end
|
1337
1701
|
|
1338
1702
|
let!(:result) do
|
1339
|
-
context.
|
1703
|
+
context.find_one_and_replace({ likes: 1 }, return_document: :after)
|
1340
1704
|
end
|
1341
1705
|
|
1342
1706
|
it "returns the first matching document" do
|
@@ -1344,6 +1708,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1344
1708
|
end
|
1345
1709
|
|
1346
1710
|
it "returns the updated document" do
|
1711
|
+
expect(result.name).to be_nil
|
1347
1712
|
expect(result.likes).to eq(1)
|
1348
1713
|
end
|
1349
1714
|
end
|
@@ -1360,7 +1725,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1360
1725
|
end
|
1361
1726
|
|
1362
1727
|
let!(:result) do
|
1363
|
-
context.
|
1728
|
+
context.find_one_and_replace({ likes: 1 }, return_document: :after)
|
1364
1729
|
end
|
1365
1730
|
|
1366
1731
|
it "returns the first matching document" do
|
@@ -1369,6 +1734,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1369
1734
|
|
1370
1735
|
it "returns the updated document" do
|
1371
1736
|
expect(result.likes).to eq(1)
|
1737
|
+
expect(result.name).to be_nil
|
1372
1738
|
end
|
1373
1739
|
end
|
1374
1740
|
end
|
@@ -1376,7 +1742,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1376
1742
|
context "when the selector does not match" do
|
1377
1743
|
|
1378
1744
|
let(:criteria) do
|
1379
|
-
Band.where(name: "
|
1745
|
+
Band.where(name: "DEPECHE MODE")
|
1380
1746
|
end
|
1381
1747
|
|
1382
1748
|
let(:context) do
|
@@ -1384,7 +1750,7 @@ describe Mongoid::Contextual::Mongo do
|
|
1384
1750
|
end
|
1385
1751
|
|
1386
1752
|
let(:result) do
|
1387
|
-
context.
|
1753
|
+
context.find_one_and_replace(name: 'FKA Twigs')
|
1388
1754
|
end
|
1389
1755
|
|
1390
1756
|
it "returns nil" do
|
@@ -1393,41 +1759,22 @@ describe Mongoid::Contextual::Mongo do
|
|
1393
1759
|
end
|
1394
1760
|
end
|
1395
1761
|
|
1396
|
-
describe "#
|
1762
|
+
describe "#find_one_and_update" do
|
1397
1763
|
|
1398
1764
|
let!(:depeche) do
|
1399
1765
|
Band.create!(name: "Depeche Mode")
|
1400
1766
|
end
|
1401
1767
|
|
1402
|
-
let(:
|
1403
|
-
Band.
|
1404
|
-
end
|
1405
|
-
|
1406
|
-
let(:context) do
|
1407
|
-
described_class.new(criteria)
|
1408
|
-
end
|
1409
|
-
|
1410
|
-
let!(:result) do
|
1411
|
-
context.find_one_and_delete
|
1768
|
+
let!(:tool) do
|
1769
|
+
Band.create!(name: "Tool")
|
1412
1770
|
end
|
1413
1771
|
|
1414
|
-
context
|
1415
|
-
|
1416
|
-
it "returns the first matching document" do
|
1417
|
-
expect(result).to eq(depeche)
|
1418
|
-
end
|
1419
|
-
|
1420
|
-
it "deletes the document from the database" do
|
1421
|
-
expect {
|
1422
|
-
depeche.reload
|
1423
|
-
}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
1424
|
-
end
|
1772
|
+
context "when the selector matches" do
|
1425
1773
|
|
1426
|
-
context
|
1427
|
-
min_server_version '3.4'
|
1774
|
+
context "when not providing options" do
|
1428
1775
|
|
1429
1776
|
let(:criteria) do
|
1430
|
-
Band.where(name: "
|
1777
|
+
Band.where(name: "Depeche Mode")
|
1431
1778
|
end
|
1432
1779
|
|
1433
1780
|
let(:context) do
|
@@ -1435,72 +1782,244 @@ describe Mongoid::Contextual::Mongo do
|
|
1435
1782
|
end
|
1436
1783
|
|
1437
1784
|
let!(:result) do
|
1438
|
-
context.
|
1785
|
+
context.find_one_and_update("$inc" => { likes: 1 })
|
1439
1786
|
end
|
1440
1787
|
|
1441
1788
|
it "returns the first matching document" do
|
1442
1789
|
expect(result).to eq(depeche)
|
1443
1790
|
end
|
1444
1791
|
|
1445
|
-
it "
|
1446
|
-
expect
|
1447
|
-
depeche.reload
|
1448
|
-
}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
1792
|
+
it "updates the document in the database" do
|
1793
|
+
expect(depeche.reload.likes).to eq(1)
|
1449
1794
|
end
|
1450
1795
|
end
|
1451
|
-
end
|
1452
|
-
|
1453
|
-
context 'when the selector does not match a document' do
|
1454
|
-
|
1455
|
-
let(:criteria) do
|
1456
|
-
Band.where(name: "Placebo")
|
1457
|
-
end
|
1458
|
-
|
1459
|
-
let(:context) do
|
1460
|
-
described_class.new(criteria)
|
1461
|
-
end
|
1462
|
-
|
1463
|
-
let(:result) do
|
1464
|
-
context.find_one_and_delete
|
1465
|
-
end
|
1466
|
-
|
1467
|
-
it "returns nil" do
|
1468
|
-
expect(result).to be_nil
|
1469
|
-
end
|
1470
|
-
end
|
1471
|
-
end
|
1472
|
-
|
1473
|
-
[ :first, :one ].each do |method|
|
1474
|
-
|
1475
|
-
describe "##{method}" do
|
1476
|
-
|
1477
|
-
let!(:depeche_mode) do
|
1478
|
-
Band.create!(name: "Depeche Mode")
|
1479
|
-
end
|
1480
|
-
|
1481
|
-
let!(:new_order) do
|
1482
|
-
Band.create!(name: "New Order")
|
1483
|
-
end
|
1484
|
-
|
1485
|
-
let!(:rolling_stones) do
|
1486
|
-
Band.create!(name: "The Rolling Stones")
|
1487
|
-
end
|
1488
1796
|
|
1489
|
-
context "when
|
1797
|
+
context "when sorting" do
|
1490
1798
|
|
1491
1799
|
let(:criteria) do
|
1492
|
-
Band.
|
1800
|
+
Band.desc(:name)
|
1493
1801
|
end
|
1494
1802
|
|
1495
1803
|
let(:context) do
|
1496
1804
|
described_class.new(criteria)
|
1497
1805
|
end
|
1498
1806
|
|
1499
|
-
|
1500
|
-
|
1807
|
+
let!(:result) do
|
1808
|
+
context.find_one_and_update("$inc" => { likes: 1 })
|
1501
1809
|
end
|
1502
1810
|
|
1503
|
-
|
1811
|
+
it "returns the first matching document" do
|
1812
|
+
expect(result).to eq(tool)
|
1813
|
+
end
|
1814
|
+
|
1815
|
+
it "updates the document in the database" do
|
1816
|
+
expect(tool.reload.likes).to eq(1)
|
1817
|
+
end
|
1818
|
+
end
|
1819
|
+
|
1820
|
+
context "when limiting fields" do
|
1821
|
+
|
1822
|
+
let(:criteria) do
|
1823
|
+
Band.only(:_id)
|
1824
|
+
end
|
1825
|
+
|
1826
|
+
let(:context) do
|
1827
|
+
described_class.new(criteria)
|
1828
|
+
end
|
1829
|
+
|
1830
|
+
let!(:result) do
|
1831
|
+
context.find_one_and_update("$inc" => { likes: 1 })
|
1832
|
+
end
|
1833
|
+
|
1834
|
+
it "returns the first matching document" do
|
1835
|
+
expect(result).to eq(depeche)
|
1836
|
+
end
|
1837
|
+
|
1838
|
+
it "limits the returned fields" do
|
1839
|
+
expect(result.name).to be_nil
|
1840
|
+
end
|
1841
|
+
|
1842
|
+
it "updates the document in the database" do
|
1843
|
+
expect(depeche.reload.likes).to eq(1)
|
1844
|
+
end
|
1845
|
+
end
|
1846
|
+
|
1847
|
+
context "when returning new" do
|
1848
|
+
|
1849
|
+
let(:criteria) do
|
1850
|
+
Band.where(name: "Depeche Mode")
|
1851
|
+
end
|
1852
|
+
|
1853
|
+
let(:context) do
|
1854
|
+
described_class.new(criteria)
|
1855
|
+
end
|
1856
|
+
|
1857
|
+
let!(:result) do
|
1858
|
+
context.find_one_and_update({ "$inc" => { likes: 1 }}, return_document: :after)
|
1859
|
+
end
|
1860
|
+
|
1861
|
+
it "returns the first matching document" do
|
1862
|
+
expect(result).to eq(depeche)
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
it "returns the updated document" do
|
1866
|
+
expect(result.likes).to eq(1)
|
1867
|
+
end
|
1868
|
+
end
|
1869
|
+
|
1870
|
+
context 'when a collation is specified on the criteria' do
|
1871
|
+
min_server_version '3.4'
|
1872
|
+
|
1873
|
+
let(:criteria) do
|
1874
|
+
Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
|
1875
|
+
end
|
1876
|
+
|
1877
|
+
let(:context) do
|
1878
|
+
described_class.new(criteria)
|
1879
|
+
end
|
1880
|
+
|
1881
|
+
let!(:result) do
|
1882
|
+
context.find_one_and_update({ "$inc" => { likes: 1 }}, return_document: :after)
|
1883
|
+
end
|
1884
|
+
|
1885
|
+
it "returns the first matching document" do
|
1886
|
+
expect(result).to eq(depeche)
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
it "returns the updated document" do
|
1890
|
+
expect(result.likes).to eq(1)
|
1891
|
+
end
|
1892
|
+
end
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
context "when the selector does not match" do
|
1896
|
+
|
1897
|
+
let(:criteria) do
|
1898
|
+
Band.where(name: "Placebo")
|
1899
|
+
end
|
1900
|
+
|
1901
|
+
let(:context) do
|
1902
|
+
described_class.new(criteria)
|
1903
|
+
end
|
1904
|
+
|
1905
|
+
let(:result) do
|
1906
|
+
context.find_one_and_update("$inc" => { likes: 1 })
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
it "returns nil" do
|
1910
|
+
expect(result).to be_nil
|
1911
|
+
end
|
1912
|
+
end
|
1913
|
+
end
|
1914
|
+
|
1915
|
+
describe "#find_one_and_delete" do
|
1916
|
+
|
1917
|
+
let!(:depeche) do
|
1918
|
+
Band.create!(name: "Depeche Mode")
|
1919
|
+
end
|
1920
|
+
|
1921
|
+
let(:criteria) do
|
1922
|
+
Band.where(name: "Depeche Mode")
|
1923
|
+
end
|
1924
|
+
|
1925
|
+
let(:context) do
|
1926
|
+
described_class.new(criteria)
|
1927
|
+
end
|
1928
|
+
|
1929
|
+
let!(:result) do
|
1930
|
+
context.find_one_and_delete
|
1931
|
+
end
|
1932
|
+
|
1933
|
+
context 'when the selector matches a document' do
|
1934
|
+
|
1935
|
+
it "returns the first matching document" do
|
1936
|
+
expect(result).to eq(depeche)
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
it "deletes the document from the database" do
|
1940
|
+
expect {
|
1941
|
+
depeche.reload
|
1942
|
+
}.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Band with id\(s\)/)
|
1943
|
+
end
|
1944
|
+
|
1945
|
+
context 'when a collation is specified on the criteria' do
|
1946
|
+
min_server_version '3.4'
|
1947
|
+
|
1948
|
+
let(:criteria) do
|
1949
|
+
Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
|
1950
|
+
end
|
1951
|
+
|
1952
|
+
let(:context) do
|
1953
|
+
described_class.new(criteria)
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
let!(:result) do
|
1957
|
+
context.find_one_and_delete
|
1958
|
+
end
|
1959
|
+
|
1960
|
+
it "returns the first matching document" do
|
1961
|
+
expect(result).to eq(depeche)
|
1962
|
+
end
|
1963
|
+
|
1964
|
+
it "deletes the document from the database" do
|
1965
|
+
expect {
|
1966
|
+
depeche.reload
|
1967
|
+
}.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Band with id\(s\)/)
|
1968
|
+
end
|
1969
|
+
end
|
1970
|
+
end
|
1971
|
+
|
1972
|
+
context 'when the selector does not match a document' do
|
1973
|
+
|
1974
|
+
let(:criteria) do
|
1975
|
+
Band.where(name: "Placebo")
|
1976
|
+
end
|
1977
|
+
|
1978
|
+
let(:context) do
|
1979
|
+
described_class.new(criteria)
|
1980
|
+
end
|
1981
|
+
|
1982
|
+
let(:result) do
|
1983
|
+
context.find_one_and_delete
|
1984
|
+
end
|
1985
|
+
|
1986
|
+
it "returns nil" do
|
1987
|
+
expect(result).to be_nil
|
1988
|
+
end
|
1989
|
+
end
|
1990
|
+
end
|
1991
|
+
|
1992
|
+
[ :first, :one ].each do |method|
|
1993
|
+
|
1994
|
+
describe "##{method}" do
|
1995
|
+
|
1996
|
+
let!(:depeche_mode) do
|
1997
|
+
Band.create!(name: "Depeche Mode")
|
1998
|
+
end
|
1999
|
+
|
2000
|
+
let!(:new_order) do
|
2001
|
+
Band.create!(name: "New Order")
|
2002
|
+
end
|
2003
|
+
|
2004
|
+
let!(:rolling_stones) do
|
2005
|
+
Band.create!(name: "The Rolling Stones")
|
2006
|
+
end
|
2007
|
+
|
2008
|
+
context "when the context is not cached" do
|
2009
|
+
|
2010
|
+
let(:criteria) do
|
2011
|
+
Band.where(name: "Depeche Mode")
|
2012
|
+
end
|
2013
|
+
|
2014
|
+
let(:context) do
|
2015
|
+
described_class.new(criteria)
|
2016
|
+
end
|
2017
|
+
|
2018
|
+
it "returns the first matching document" do
|
2019
|
+
expect(context.send(method)).to eq(depeche_mode)
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
context 'when the criteria has a collation' do
|
1504
2023
|
min_server_version '3.4'
|
1505
2024
|
|
1506
2025
|
let(:criteria) do
|
@@ -1554,31 +2073,13 @@ describe Mongoid::Contextual::Mongo do
|
|
1554
2073
|
expect(context.send(method)).to eq(depeche_mode)
|
1555
2074
|
end
|
1556
2075
|
|
1557
|
-
context
|
2076
|
+
context 'when calling #last' do
|
1558
2077
|
|
1559
|
-
it 'returns the
|
2078
|
+
it 'returns the last document, sorted by _id' do
|
1560
2079
|
expect(context.send(method)).to eq(depeche_mode)
|
1561
2080
|
expect(context.last).to eq(rolling_stones)
|
1562
2081
|
end
|
1563
2082
|
end
|
1564
|
-
|
1565
|
-
context 'with option { id_sort: :none }' do
|
1566
|
-
let(:opts) do
|
1567
|
-
{ id_sort: :none }
|
1568
|
-
end
|
1569
|
-
|
1570
|
-
it 'applies the sort on _id' do
|
1571
|
-
expect(context.send(method, opts)).to eq(depeche_mode)
|
1572
|
-
end
|
1573
|
-
|
1574
|
-
context "when calling ##{method}" do
|
1575
|
-
|
1576
|
-
it 'doesn\'t apply a sort on _id' do
|
1577
|
-
expect(context.send(method, opts)).to eq(depeche_mode)
|
1578
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
1579
|
-
end
|
1580
|
-
end
|
1581
|
-
end
|
1582
2083
|
end
|
1583
2084
|
|
1584
2085
|
context 'when the criteria has a sort' do
|
@@ -1602,25 +2103,6 @@ describe Mongoid::Contextual::Mongo do
|
|
1602
2103
|
expect(context.last).to eq(depeche_mode)
|
1603
2104
|
end
|
1604
2105
|
end
|
1605
|
-
|
1606
|
-
context 'with option { id_sort: :none }' do
|
1607
|
-
|
1608
|
-
let(:opts) do
|
1609
|
-
{ id_sort: :none }
|
1610
|
-
end
|
1611
|
-
|
1612
|
-
it 'uses the preexisting sort' do
|
1613
|
-
expect(context.send(method, opts)).to eq(rolling_stones)
|
1614
|
-
end
|
1615
|
-
|
1616
|
-
context 'when calling #last' do
|
1617
|
-
|
1618
|
-
it 'uses the preexisting sort' do
|
1619
|
-
expect(context.send(method, opts)).to eq(rolling_stones)
|
1620
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
1621
|
-
end
|
1622
|
-
end
|
1623
|
-
end
|
1624
2106
|
end
|
1625
2107
|
|
1626
2108
|
context "when using .sort" do
|
@@ -1649,28 +2131,17 @@ describe Mongoid::Contextual::Mongo do
|
|
1649
2131
|
end
|
1650
2132
|
end
|
1651
2133
|
|
1652
|
-
context "when the
|
2134
|
+
context "when the query cache is enabled" do
|
2135
|
+
query_cache_enabled
|
1653
2136
|
|
1654
2137
|
let(:criteria) do
|
1655
|
-
Band.where(name: "Depeche Mode")
|
2138
|
+
Band.where(name: "Depeche Mode")
|
1656
2139
|
end
|
1657
2140
|
|
1658
2141
|
let(:context) do
|
1659
2142
|
described_class.new(criteria)
|
1660
2143
|
end
|
1661
2144
|
|
1662
|
-
context "when the cache is loaded" do
|
1663
|
-
|
1664
|
-
before do
|
1665
|
-
context.to_a
|
1666
|
-
end
|
1667
|
-
|
1668
|
-
it "returns the first document without touching the database" do
|
1669
|
-
expect(context).to receive(:view).never
|
1670
|
-
expect(context.send(method)).to eq(depeche_mode)
|
1671
|
-
end
|
1672
|
-
end
|
1673
|
-
|
1674
2145
|
context "when first method was called before" do
|
1675
2146
|
|
1676
2147
|
before do
|
@@ -1678,8 +2149,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1678
2149
|
end
|
1679
2150
|
|
1680
2151
|
it "returns the first document without touching the database" do
|
1681
|
-
|
1682
|
-
|
2152
|
+
expect_no_queries do
|
2153
|
+
expect(context.send(method)).to eq(depeche_mode)
|
2154
|
+
end
|
1683
2155
|
end
|
1684
2156
|
end
|
1685
2157
|
end
|
@@ -1733,86 +2205,30 @@ describe Mongoid::Contextual::Mongo do
|
|
1733
2205
|
end
|
1734
2206
|
end
|
1735
2207
|
|
1736
|
-
context "when the
|
2208
|
+
context "when the query cache is enabled" do
|
1737
2209
|
|
1738
2210
|
let(:context) do
|
1739
2211
|
described_class.new(criteria)
|
1740
2212
|
end
|
1741
2213
|
|
1742
|
-
context "when
|
2214
|
+
context "when calling first beforehand" do
|
2215
|
+
query_cache_enabled
|
1743
2216
|
|
1744
|
-
|
1745
|
-
|
2217
|
+
let(:context) do
|
2218
|
+
described_class.new(criteria)
|
1746
2219
|
end
|
1747
2220
|
|
1748
|
-
|
2221
|
+
let(:criteria) do
|
2222
|
+
Band.all
|
2223
|
+
end
|
1749
2224
|
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
2225
|
+
before do
|
2226
|
+
context.first(before_limit)
|
2227
|
+
end
|
1753
2228
|
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
context.send(method, 3)
|
1758
|
-
end
|
1759
|
-
|
1760
|
-
it "returns all of the documents without touching the database" do
|
1761
|
-
expect(context).to receive(:view).never
|
1762
|
-
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
1763
|
-
end
|
1764
|
-
end
|
1765
|
-
|
1766
|
-
context "when requesting fewer than all of the documents" do
|
1767
|
-
|
1768
|
-
let(:docs) do
|
1769
|
-
context.send(method, 2)
|
1770
|
-
end
|
1771
|
-
|
1772
|
-
it "returns all of the documents without touching the database" do
|
1773
|
-
expect(context).to receive(:view).never
|
1774
|
-
expect(docs).to eq([ depeche_mode, new_order ])
|
1775
|
-
end
|
1776
|
-
end
|
1777
|
-
end
|
1778
|
-
|
1779
|
-
context "when only one document is cached" do
|
1780
|
-
|
1781
|
-
let(:criteria) do
|
1782
|
-
Band.where(name: "Depeche Mode").cache
|
1783
|
-
end
|
1784
|
-
|
1785
|
-
context "when requesting one document" do
|
1786
|
-
|
1787
|
-
let(:docs) do
|
1788
|
-
context.send(method, 1)
|
1789
|
-
end
|
1790
|
-
|
1791
|
-
it "returns one document without touching the database" do
|
1792
|
-
expect(context).to receive(:view).never
|
1793
|
-
expect(docs).to eq([ depeche_mode ])
|
1794
|
-
end
|
1795
|
-
end
|
1796
|
-
end
|
1797
|
-
end
|
1798
|
-
|
1799
|
-
context "when the first method was called before" do
|
1800
|
-
|
1801
|
-
let(:context) do
|
1802
|
-
described_class.new(criteria)
|
1803
|
-
end
|
1804
|
-
|
1805
|
-
let(:criteria) do
|
1806
|
-
Band.all.cache
|
1807
|
-
end
|
1808
|
-
|
1809
|
-
before do
|
1810
|
-
context.first(before_limit)
|
1811
|
-
end
|
1812
|
-
|
1813
|
-
let(:docs) do
|
1814
|
-
context.send(method, limit)
|
1815
|
-
end
|
2229
|
+
let(:docs) do
|
2230
|
+
context.send(method, limit)
|
2231
|
+
end
|
1816
2232
|
|
1817
2233
|
context "when getting all of the documents before" do
|
1818
2234
|
let(:before_limit) { 3 }
|
@@ -1821,8 +2237,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1821
2237
|
let(:limit) { 3 }
|
1822
2238
|
|
1823
2239
|
it "returns all documents without touching the database" do
|
1824
|
-
|
1825
|
-
|
2240
|
+
expect_no_queries do
|
2241
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2242
|
+
end
|
1826
2243
|
end
|
1827
2244
|
end
|
1828
2245
|
|
@@ -1830,8 +2247,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1830
2247
|
let(:limit) { 2 }
|
1831
2248
|
|
1832
2249
|
it "returns the correct documents without touching the database" do
|
1833
|
-
|
1834
|
-
|
2250
|
+
expect_no_queries do
|
2251
|
+
expect(docs).to eq([ depeche_mode, new_order ])
|
2252
|
+
end
|
1835
2253
|
end
|
1836
2254
|
end
|
1837
2255
|
end
|
@@ -1843,8 +2261,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1843
2261
|
let(:limit) { 2 }
|
1844
2262
|
|
1845
2263
|
it "returns the correct documents without touching the database" do
|
1846
|
-
|
1847
|
-
|
2264
|
+
expect_no_queries do
|
2265
|
+
expect(docs).to eq([ depeche_mode, new_order ])
|
2266
|
+
end
|
1848
2267
|
end
|
1849
2268
|
end
|
1850
2269
|
|
@@ -1852,8 +2271,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1852
2271
|
let(:limit) { 3 }
|
1853
2272
|
|
1854
2273
|
it "returns the correct documents and touches the database" do
|
1855
|
-
|
1856
|
-
|
2274
|
+
expect_query(1) do
|
2275
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2276
|
+
end
|
1857
2277
|
end
|
1858
2278
|
end
|
1859
2279
|
end
|
@@ -1865,8 +2285,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1865
2285
|
let(:limit) { 1 }
|
1866
2286
|
|
1867
2287
|
it "returns the correct documents without touching the database" do
|
1868
|
-
|
1869
|
-
|
2288
|
+
expect_no_queries do
|
2289
|
+
expect(docs).to eq([ depeche_mode ])
|
2290
|
+
end
|
1870
2291
|
end
|
1871
2292
|
end
|
1872
2293
|
|
@@ -1874,8 +2295,9 @@ describe Mongoid::Contextual::Mongo do
|
|
1874
2295
|
let(:limit) { 3 }
|
1875
2296
|
|
1876
2297
|
it "returns the correct documents and touches the database" do
|
1877
|
-
|
1878
|
-
|
2298
|
+
expect_query(1) do
|
2299
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2300
|
+
end
|
1879
2301
|
end
|
1880
2302
|
end
|
1881
2303
|
end
|
@@ -1883,24 +2305,15 @@ describe Mongoid::Contextual::Mongo do
|
|
1883
2305
|
end
|
1884
2306
|
end
|
1885
2307
|
|
1886
|
-
context "when
|
1887
|
-
|
1888
|
-
let(:criteria) { Band.criteria }
|
1889
|
-
let(:docs) { context.send(method, {}) }
|
1890
|
-
|
1891
|
-
it "behaves as if limit is nil" do
|
1892
|
-
expect(docs).to eq(depeche_mode)
|
1893
|
-
end
|
1894
|
-
end
|
1895
|
-
|
1896
|
-
context "when calling #first then #last" do
|
2308
|
+
context "when calling #first then #last and the query cache is enabled" do
|
2309
|
+
query_cache_enabled
|
1897
2310
|
|
1898
2311
|
let(:context) do
|
1899
2312
|
described_class.new(criteria)
|
1900
2313
|
end
|
1901
2314
|
|
1902
2315
|
let(:criteria) do
|
1903
|
-
Band.all
|
2316
|
+
Band.all
|
1904
2317
|
end
|
1905
2318
|
|
1906
2319
|
before do
|
@@ -1915,8 +2328,10 @@ describe Mongoid::Contextual::Mongo do
|
|
1915
2328
|
let(:before_limit) { 2 }
|
1916
2329
|
let(:limit) { 1 }
|
1917
2330
|
|
1918
|
-
it "gets the correct document" do
|
1919
|
-
|
2331
|
+
it "gets the correct document and hits the database" do
|
2332
|
+
expect_query(1) do
|
2333
|
+
expect(docs).to eq([rolling_stones])
|
2334
|
+
end
|
1920
2335
|
end
|
1921
2336
|
end
|
1922
2337
|
end
|
@@ -2006,30 +2421,10 @@ describe Mongoid::Contextual::Mongo do
|
|
2006
2421
|
context 'when calling #first' do
|
2007
2422
|
|
2008
2423
|
it 'returns the first document, sorted by _id' do
|
2009
|
-
pending "MONGOID-5416"
|
2010
2424
|
expect(context.last).to eq(rolling_stones)
|
2011
2425
|
expect(context.first).to eq(depeche_mode)
|
2012
2426
|
end
|
2013
2427
|
end
|
2014
|
-
|
2015
|
-
context 'with option { id_sort: :none }' do
|
2016
|
-
let(:opts) do
|
2017
|
-
{ id_sort: :none }
|
2018
|
-
end
|
2019
|
-
|
2020
|
-
it 'doesn\'t apply the sort on _id' do
|
2021
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
2022
|
-
end
|
2023
|
-
|
2024
|
-
context 'when calling #first' do
|
2025
|
-
|
2026
|
-
it 'doesn\'t apply the sort on _id' do
|
2027
|
-
pending "MONGOID-5416"
|
2028
|
-
expect(context.last(opts)).to eq(rolling_stones)
|
2029
|
-
expect(context.first(opts)).to eq(depeche_mode)
|
2030
|
-
end
|
2031
|
-
end
|
2032
|
-
end
|
2033
2428
|
end
|
2034
2429
|
|
2035
2430
|
context 'when the criteria has a sort' do
|
@@ -2054,25 +2449,6 @@ describe Mongoid::Contextual::Mongo do
|
|
2054
2449
|
expect(context.first).to eq(rolling_stones)
|
2055
2450
|
end
|
2056
2451
|
end
|
2057
|
-
|
2058
|
-
context 'with option { id_sort: :none }' do
|
2059
|
-
|
2060
|
-
let(:opts) do
|
2061
|
-
{ id_sort: :none }
|
2062
|
-
end
|
2063
|
-
|
2064
|
-
it 'uses the preexisting sort' do
|
2065
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
2066
|
-
end
|
2067
|
-
|
2068
|
-
context 'when calling #first' do
|
2069
|
-
|
2070
|
-
it 'uses the preexisting sort' do
|
2071
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
2072
|
-
expect(context.first(opts)).to eq(rolling_stones)
|
2073
|
-
end
|
2074
|
-
end
|
2075
|
-
end
|
2076
2452
|
end
|
2077
2453
|
|
2078
2454
|
context "when using .sort" do
|
@@ -2101,28 +2477,17 @@ describe Mongoid::Contextual::Mongo do
|
|
2101
2477
|
end
|
2102
2478
|
end
|
2103
2479
|
|
2104
|
-
context "when the
|
2480
|
+
context "when the query cache is enabled" do
|
2481
|
+
query_cache_enabled
|
2105
2482
|
|
2106
2483
|
let(:criteria) do
|
2107
|
-
Band.where(name: "Depeche Mode")
|
2484
|
+
Band.where(name: "Depeche Mode")
|
2108
2485
|
end
|
2109
2486
|
|
2110
2487
|
let(:context) do
|
2111
2488
|
described_class.new(criteria)
|
2112
2489
|
end
|
2113
2490
|
|
2114
|
-
context "when the cache is loaded" do
|
2115
|
-
|
2116
|
-
before do
|
2117
|
-
context.to_a
|
2118
|
-
end
|
2119
|
-
|
2120
|
-
it "returns the last document without touching the database" do
|
2121
|
-
expect(context).to receive(:view).never
|
2122
|
-
expect(context.last).to eq(depeche_mode)
|
2123
|
-
end
|
2124
|
-
end
|
2125
|
-
|
2126
2491
|
context "when last method was called before" do
|
2127
2492
|
|
2128
2493
|
before do
|
@@ -2130,8 +2495,9 @@ describe Mongoid::Contextual::Mongo do
|
|
2130
2495
|
end
|
2131
2496
|
|
2132
2497
|
it "returns the last document without touching the database" do
|
2133
|
-
|
2134
|
-
|
2498
|
+
expect_no_queries do
|
2499
|
+
expect(context.last).to eq(depeche_mode)
|
2500
|
+
end
|
2135
2501
|
end
|
2136
2502
|
end
|
2137
2503
|
end
|
@@ -2191,71 +2557,15 @@ describe Mongoid::Contextual::Mongo do
|
|
2191
2557
|
described_class.new(criteria)
|
2192
2558
|
end
|
2193
2559
|
|
2194
|
-
context "when
|
2195
|
-
|
2196
|
-
before do
|
2197
|
-
context.to_a
|
2198
|
-
end
|
2199
|
-
|
2200
|
-
context "when all of the documents are cached" do
|
2201
|
-
|
2202
|
-
let(:criteria) do
|
2203
|
-
Band.all.cache
|
2204
|
-
end
|
2205
|
-
|
2206
|
-
context "when requesting all of the documents" do
|
2207
|
-
|
2208
|
-
let(:docs) do
|
2209
|
-
context.last(3)
|
2210
|
-
end
|
2211
|
-
|
2212
|
-
it "returns all of the documents without touching the database" do
|
2213
|
-
expect(context).to receive(:view).never
|
2214
|
-
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2215
|
-
end
|
2216
|
-
end
|
2217
|
-
|
2218
|
-
context "when requesting fewer than all of the documents" do
|
2219
|
-
|
2220
|
-
let(:docs) do
|
2221
|
-
context.last(2)
|
2222
|
-
end
|
2223
|
-
|
2224
|
-
it "returns all of the documents without touching the database" do
|
2225
|
-
expect(context).to receive(:view).never
|
2226
|
-
expect(docs).to eq([ new_order, rolling_stones ])
|
2227
|
-
end
|
2228
|
-
end
|
2229
|
-
end
|
2230
|
-
|
2231
|
-
context "when only one document is cached" do
|
2232
|
-
|
2233
|
-
let(:criteria) do
|
2234
|
-
Band.where(name: "Depeche Mode").cache
|
2235
|
-
end
|
2236
|
-
|
2237
|
-
context "when requesting one document" do
|
2238
|
-
|
2239
|
-
let(:docs) do
|
2240
|
-
context.last(1)
|
2241
|
-
end
|
2242
|
-
|
2243
|
-
it "returns one document without touching the database" do
|
2244
|
-
expect(context).to receive(:view).never
|
2245
|
-
expect(docs).to eq([ depeche_mode ])
|
2246
|
-
end
|
2247
|
-
end
|
2248
|
-
end
|
2249
|
-
end
|
2250
|
-
|
2251
|
-
context "when the last method was called before" do
|
2560
|
+
context "when query cache is enabled" do
|
2561
|
+
query_cache_enabled
|
2252
2562
|
|
2253
2563
|
let(:context) do
|
2254
2564
|
described_class.new(criteria)
|
2255
2565
|
end
|
2256
2566
|
|
2257
2567
|
let(:criteria) do
|
2258
|
-
Band.all
|
2568
|
+
Band.all
|
2259
2569
|
end
|
2260
2570
|
|
2261
2571
|
before do
|
@@ -2272,18 +2582,20 @@ describe Mongoid::Contextual::Mongo do
|
|
2272
2582
|
context "when getting all of the documents" do
|
2273
2583
|
let(:limit) { 3 }
|
2274
2584
|
|
2275
|
-
it "returns all documents without touching the
|
2276
|
-
|
2277
|
-
|
2585
|
+
it "returns all documents without touching the db" do
|
2586
|
+
expect_no_queries do
|
2587
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2588
|
+
end
|
2278
2589
|
end
|
2279
2590
|
end
|
2280
2591
|
|
2281
2592
|
context "when getting fewer documents" do
|
2282
2593
|
let(:limit) { 2 }
|
2283
2594
|
|
2284
|
-
it "returns the correct documents without touching the
|
2285
|
-
|
2286
|
-
|
2595
|
+
it "returns the correct documents without touching the db" do
|
2596
|
+
expect_no_queries do
|
2597
|
+
expect(docs).to eq([ new_order, rolling_stones ])
|
2598
|
+
end
|
2287
2599
|
end
|
2288
2600
|
end
|
2289
2601
|
end
|
@@ -2294,9 +2606,10 @@ describe Mongoid::Contextual::Mongo do
|
|
2294
2606
|
context "when getting the same number of documents" do
|
2295
2607
|
let(:limit) { 2 }
|
2296
2608
|
|
2297
|
-
it "returns the correct documents without touching the
|
2298
|
-
|
2299
|
-
|
2609
|
+
it "returns the correct documents without touching the db" do
|
2610
|
+
expect_no_queries do
|
2611
|
+
expect(docs).to eq([ new_order, rolling_stones ])
|
2612
|
+
end
|
2300
2613
|
end
|
2301
2614
|
end
|
2302
2615
|
|
@@ -2304,8 +2617,9 @@ describe Mongoid::Contextual::Mongo do
|
|
2304
2617
|
let(:limit) { 3 }
|
2305
2618
|
|
2306
2619
|
it "returns the correct documents and touches the database" do
|
2307
|
-
|
2308
|
-
|
2620
|
+
expect_query(1) do
|
2621
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2622
|
+
end
|
2309
2623
|
end
|
2310
2624
|
end
|
2311
2625
|
end
|
@@ -2317,8 +2631,9 @@ describe Mongoid::Contextual::Mongo do
|
|
2317
2631
|
let(:limit) { 1 }
|
2318
2632
|
|
2319
2633
|
it "returns the correct documents without touching the database" do
|
2320
|
-
|
2321
|
-
|
2634
|
+
expect_no_queries do
|
2635
|
+
expect(docs).to eq([ rolling_stones ])
|
2636
|
+
end
|
2322
2637
|
end
|
2323
2638
|
end
|
2324
2639
|
|
@@ -2326,8 +2641,9 @@ describe Mongoid::Contextual::Mongo do
|
|
2326
2641
|
let(:limit) { 3 }
|
2327
2642
|
|
2328
2643
|
it "returns the correct documents and touches the database" do
|
2329
|
-
|
2330
|
-
|
2644
|
+
expect_query(1) do
|
2645
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
2646
|
+
end
|
2331
2647
|
end
|
2332
2648
|
end
|
2333
2649
|
end
|
@@ -2335,14 +2651,15 @@ describe Mongoid::Contextual::Mongo do
|
|
2335
2651
|
end
|
2336
2652
|
end
|
2337
2653
|
|
2338
|
-
context "when calling #last then #first" do
|
2654
|
+
context "when calling #last then #first and the query cache is enabled" do
|
2655
|
+
query_cache_enabled
|
2339
2656
|
|
2340
2657
|
let(:context) do
|
2341
2658
|
described_class.new(criteria)
|
2342
2659
|
end
|
2343
2660
|
|
2344
2661
|
let(:criteria) do
|
2345
|
-
Band.all
|
2662
|
+
Band.all
|
2346
2663
|
end
|
2347
2664
|
|
2348
2665
|
before do
|
@@ -2358,26 +2675,16 @@ describe Mongoid::Contextual::Mongo do
|
|
2358
2675
|
let(:limit) { 1 }
|
2359
2676
|
|
2360
2677
|
it "hits the database" do
|
2361
|
-
|
2362
|
-
|
2678
|
+
expect_query(1) do
|
2679
|
+
docs
|
2680
|
+
end
|
2363
2681
|
end
|
2364
2682
|
|
2365
2683
|
it "gets the correct document" do
|
2366
|
-
pending "MONGOID-5416"
|
2367
2684
|
expect(docs).to eq([ depeche_mode ])
|
2368
2685
|
end
|
2369
2686
|
end
|
2370
2687
|
end
|
2371
|
-
|
2372
|
-
context "when given an empty hash" do
|
2373
|
-
let(:context) { described_class.new(criteria) }
|
2374
|
-
let(:criteria) { Band.criteria }
|
2375
|
-
let(:docs) { context.last({}) }
|
2376
|
-
|
2377
|
-
it "behaves as if limit is nil" do
|
2378
|
-
expect(docs).to eq(rolling_stones)
|
2379
|
-
end
|
2380
|
-
end
|
2381
2688
|
end
|
2382
2689
|
|
2383
2690
|
describe "#initialize" do
|
@@ -2426,37 +2733,28 @@ describe Mongoid::Contextual::Mongo do
|
|
2426
2733
|
described_class.new(criteria)
|
2427
2734
|
end
|
2428
2735
|
|
2429
|
-
|
2430
|
-
|
2431
|
-
end
|
2736
|
+
context "when broken_view_options is false" do
|
2737
|
+
driver_config_override :broken_view_options, false
|
2432
2738
|
|
2433
|
-
|
2434
|
-
|
2435
|
-
expect(context.view).to receive(:count_documents).once.and_return(2)
|
2436
|
-
2.times { expect(context.send(method)).to eq(2) }
|
2739
|
+
it "returns the number of documents that match" do
|
2740
|
+
expect(context.send(method)).to eq(1)
|
2437
2741
|
end
|
2438
2742
|
end
|
2439
2743
|
|
2440
|
-
context "when
|
2441
|
-
|
2442
|
-
before do
|
2443
|
-
context.entries
|
2444
|
-
end
|
2744
|
+
context "when broken_view_options is true" do
|
2745
|
+
driver_config_override :broken_view_options, true
|
2445
2746
|
|
2446
|
-
it "returns the
|
2447
|
-
expect(context.view).to receive(:count_documents).once.and_return(2)
|
2747
|
+
it "returns the number of documents that match" do
|
2448
2748
|
expect(context.send(method)).to eq(2)
|
2449
2749
|
end
|
2750
|
+
end
|
2450
2751
|
|
2451
|
-
|
2452
|
-
|
2453
|
-
before do
|
2454
|
-
context.entries
|
2455
|
-
end
|
2752
|
+
context "when calling more than once with different limits" do
|
2753
|
+
driver_config_override :broken_view_options, false
|
2456
2754
|
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2755
|
+
it "does not cache the value" do
|
2756
|
+
expect(context.limit(1).send(method)).to eq(1)
|
2757
|
+
expect(context.limit(2).send(method)).to eq(2)
|
2460
2758
|
end
|
2461
2759
|
end
|
2462
2760
|
end
|
@@ -2475,10 +2773,12 @@ describe Mongoid::Contextual::Mongo do
|
|
2475
2773
|
expect(context.send(method)).to eq(1)
|
2476
2774
|
end
|
2477
2775
|
|
2478
|
-
context "when calling more than once" do
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2776
|
+
context "when calling more than once with different skips" do
|
2777
|
+
driver_config_override :broken_view_options, false
|
2778
|
+
|
2779
|
+
it "does not cache the value" do
|
2780
|
+
expect(context.skip(0).send(method)).to eq(1)
|
2781
|
+
expect(context.skip(1).send(method)).to eq(0)
|
2482
2782
|
end
|
2483
2783
|
end
|
2484
2784
|
|
@@ -2600,7 +2900,7 @@ describe Mongoid::Contextual::Mongo do
|
|
2600
2900
|
it "raises an error" do
|
2601
2901
|
expect do
|
2602
2902
|
Person.take!
|
2603
|
-
end.to raise_error(Mongoid::Errors::DocumentNotFound)
|
2903
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Person./)
|
2604
2904
|
end
|
2605
2905
|
end
|
2606
2906
|
end
|
@@ -2622,9 +2922,10 @@ describe Mongoid::Contextual::Mongo do
|
|
2622
2922
|
|
2623
2923
|
context "when passed the symbol field name" do
|
2624
2924
|
|
2625
|
-
it "
|
2626
|
-
expect
|
2627
|
-
|
2925
|
+
it "raises an error" do
|
2926
|
+
expect do
|
2927
|
+
context.map(:name)
|
2928
|
+
end.to raise_error(ArgumentError)
|
2628
2929
|
end
|
2629
2930
|
end
|
2630
2931
|
|
@@ -3065,7 +3366,805 @@ describe Mongoid::Contextual::Mongo do
|
|
3065
3366
|
end
|
3066
3367
|
end
|
3067
3368
|
|
3068
|
-
describe "#skip" do
|
3369
|
+
describe "#skip" do
|
3370
|
+
|
3371
|
+
let!(:depeche_mode) do
|
3372
|
+
Band.create!(name: "Depeche Mode")
|
3373
|
+
end
|
3374
|
+
|
3375
|
+
let!(:new_order) do
|
3376
|
+
Band.create!(name: "New Order")
|
3377
|
+
end
|
3378
|
+
|
3379
|
+
let(:criteria) do
|
3380
|
+
Band.all
|
3381
|
+
end
|
3382
|
+
|
3383
|
+
let(:context) do
|
3384
|
+
described_class.new(criteria)
|
3385
|
+
end
|
3386
|
+
|
3387
|
+
it "limits the results" do
|
3388
|
+
expect(context.skip(1).entries).to eq([ new_order ])
|
3389
|
+
end
|
3390
|
+
end
|
3391
|
+
|
3392
|
+
describe "#sort" do
|
3393
|
+
|
3394
|
+
let!(:depeche_mode) do
|
3395
|
+
Band.create!(name: "Depeche Mode")
|
3396
|
+
end
|
3397
|
+
|
3398
|
+
let!(:new_order) do
|
3399
|
+
Band.create!(name: "New Order")
|
3400
|
+
end
|
3401
|
+
|
3402
|
+
let(:criteria) do
|
3403
|
+
Band.all
|
3404
|
+
end
|
3405
|
+
|
3406
|
+
let(:context) do
|
3407
|
+
described_class.new(criteria)
|
3408
|
+
end
|
3409
|
+
|
3410
|
+
context "when providing a spec" do
|
3411
|
+
|
3412
|
+
it "sorts the results" do
|
3413
|
+
expect(context.sort(name: -1).entries).to eq([ new_order, depeche_mode ])
|
3414
|
+
end
|
3415
|
+
|
3416
|
+
it "returns the context" do
|
3417
|
+
expect(context.sort(name: 1)).to eq(context)
|
3418
|
+
end
|
3419
|
+
end
|
3420
|
+
|
3421
|
+
context "when providing a block" do
|
3422
|
+
|
3423
|
+
let(:sorted) do
|
3424
|
+
context.sort do |a, b|
|
3425
|
+
b.name <=> a.name
|
3426
|
+
end
|
3427
|
+
end
|
3428
|
+
|
3429
|
+
it "sorts the results in memory" do
|
3430
|
+
expect(sorted).to eq([ new_order, depeche_mode ])
|
3431
|
+
end
|
3432
|
+
end
|
3433
|
+
end
|
3434
|
+
|
3435
|
+
describe "#update" do
|
3436
|
+
|
3437
|
+
let!(:depeche_mode) do
|
3438
|
+
Band.create!(name: "Depeche Mode")
|
3439
|
+
end
|
3440
|
+
|
3441
|
+
let!(:new_order) do
|
3442
|
+
Band.create!(name: "New Order")
|
3443
|
+
end
|
3444
|
+
|
3445
|
+
let(:criteria) do
|
3446
|
+
Band.all
|
3447
|
+
end
|
3448
|
+
|
3449
|
+
let(:context) do
|
3450
|
+
described_class.new(criteria)
|
3451
|
+
end
|
3452
|
+
|
3453
|
+
context "when adding an element to a HABTM set" do
|
3454
|
+
|
3455
|
+
let(:person) do
|
3456
|
+
Person.create!
|
3457
|
+
end
|
3458
|
+
|
3459
|
+
let(:preference) do
|
3460
|
+
Preference.create!
|
3461
|
+
end
|
3462
|
+
|
3463
|
+
before do
|
3464
|
+
Person.where(id: person.id).
|
3465
|
+
update("$addToSet" => { preference_ids: preference.id })
|
3466
|
+
end
|
3467
|
+
|
3468
|
+
it "adds a single element to the array" do
|
3469
|
+
expect(person.reload.preference_ids).to eq([ preference.id ])
|
3470
|
+
end
|
3471
|
+
end
|
3472
|
+
|
3473
|
+
context "when providing attributes" do
|
3474
|
+
|
3475
|
+
context "when the attributes are of the correct type" do
|
3476
|
+
|
3477
|
+
before do
|
3478
|
+
context.update(name: "Smiths")
|
3479
|
+
end
|
3480
|
+
|
3481
|
+
it "updates only the first matching document" do
|
3482
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3483
|
+
end
|
3484
|
+
|
3485
|
+
it "does not update the last matching document" do
|
3486
|
+
expect(new_order.reload.name).to eq("New Order")
|
3487
|
+
end
|
3488
|
+
end
|
3489
|
+
|
3490
|
+
context "when the attributes must be mongoized" do
|
3491
|
+
|
3492
|
+
context "when coercing a string to integer" do
|
3493
|
+
|
3494
|
+
before do
|
3495
|
+
context.update(member_count: "1")
|
3496
|
+
end
|
3497
|
+
|
3498
|
+
it "updates the first matching document" do
|
3499
|
+
expect(depeche_mode.reload.member_count).to eq(1)
|
3500
|
+
end
|
3501
|
+
|
3502
|
+
it "does not update the last matching document" do
|
3503
|
+
expect(new_order.reload.member_count).to be_nil
|
3504
|
+
end
|
3505
|
+
end
|
3506
|
+
|
3507
|
+
context "when coercing a string to date" do
|
3508
|
+
|
3509
|
+
before do
|
3510
|
+
context.update(founded: "1979/1/1")
|
3511
|
+
end
|
3512
|
+
|
3513
|
+
it "updates the first matching document" do
|
3514
|
+
expect(depeche_mode.reload.founded).to eq(Date.new(1979, 1, 1))
|
3515
|
+
end
|
3516
|
+
|
3517
|
+
it "does not update the last matching document" do
|
3518
|
+
expect(new_order.reload.founded).to be_nil
|
3519
|
+
end
|
3520
|
+
end
|
3521
|
+
end
|
3522
|
+
end
|
3523
|
+
|
3524
|
+
context "when providing atomic operations" do
|
3525
|
+
|
3526
|
+
context "when only atomic operations are provided" do
|
3527
|
+
|
3528
|
+
context "when the attributes are in the correct type" do
|
3529
|
+
|
3530
|
+
before do
|
3531
|
+
context.update("$set" => { name: "Smiths" })
|
3532
|
+
end
|
3533
|
+
|
3534
|
+
it "updates the first matching document" do
|
3535
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3536
|
+
end
|
3537
|
+
|
3538
|
+
it "does not update the last matching document" do
|
3539
|
+
expect(new_order.reload.name).to eq("New Order")
|
3540
|
+
end
|
3541
|
+
end
|
3542
|
+
|
3543
|
+
context "when the attributes must be mongoized" do
|
3544
|
+
|
3545
|
+
before do
|
3546
|
+
context.update("$set" => { member_count: "1" })
|
3547
|
+
end
|
3548
|
+
|
3549
|
+
it "updates the first matching document" do
|
3550
|
+
expect(depeche_mode.reload.member_count).to eq(1)
|
3551
|
+
end
|
3552
|
+
|
3553
|
+
it "does not update the last matching document" do
|
3554
|
+
expect(new_order.reload.member_count).to be_nil
|
3555
|
+
end
|
3556
|
+
end
|
3557
|
+
end
|
3558
|
+
|
3559
|
+
context "when a mix are provided" do
|
3560
|
+
|
3561
|
+
before do
|
3562
|
+
context.update("$set" => { name: "Smiths" }, likes: 100)
|
3563
|
+
end
|
3564
|
+
|
3565
|
+
it "updates the first matching document's set" do
|
3566
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3567
|
+
end
|
3568
|
+
|
3569
|
+
it "updates the first matching document's updates" do
|
3570
|
+
expect(depeche_mode.reload.likes).to eq(100)
|
3571
|
+
end
|
3572
|
+
|
3573
|
+
it "does not update the last matching document's set" do
|
3574
|
+
expect(new_order.reload.name).to eq("New Order")
|
3575
|
+
end
|
3576
|
+
|
3577
|
+
it "does not update the last matching document's updates" do
|
3578
|
+
expect(new_order.reload.likes).to be_nil
|
3579
|
+
end
|
3580
|
+
end
|
3581
|
+
end
|
3582
|
+
|
3583
|
+
context "when providing no attributes" do
|
3584
|
+
|
3585
|
+
it "returns false" do
|
3586
|
+
expect(context.update).to be false
|
3587
|
+
end
|
3588
|
+
end
|
3589
|
+
|
3590
|
+
context 'when provided array filters' do
|
3591
|
+
min_server_version '3.6'
|
3592
|
+
|
3593
|
+
before do
|
3594
|
+
Band.delete_all
|
3595
|
+
b = Band.new(name: 'Depeche Mode')
|
3596
|
+
b.labels << Label.new(name: 'Warner')
|
3597
|
+
b.labels << Label.new(name: 'Sony')
|
3598
|
+
b.labels << Label.new(name: 'Cbs')
|
3599
|
+
b.save!
|
3600
|
+
|
3601
|
+
b = Band.new(name: 'FKA Twigs')
|
3602
|
+
b.labels << Label.new(name: 'Warner')
|
3603
|
+
b.labels << Label.new(name: 'Cbs')
|
3604
|
+
b.save!
|
3605
|
+
end
|
3606
|
+
|
3607
|
+
|
3608
|
+
let(:criteria) do
|
3609
|
+
Band.where(name: 'Depeche Mode')
|
3610
|
+
end
|
3611
|
+
|
3612
|
+
let!(:update) do
|
3613
|
+
context.update({ '$set' => { 'labels.$[i].name' => 'Sony' } },
|
3614
|
+
array_filters: [{ 'i.name' => 'Cbs' }])
|
3615
|
+
end
|
3616
|
+
|
3617
|
+
it 'applies the array filters' do
|
3618
|
+
expect(Band.where(name: 'Depeche Mode').first.labels.collect(&:name)).to match_array(['Warner', 'Sony', 'Sony'])
|
3619
|
+
end
|
3620
|
+
|
3621
|
+
it 'does not affect other documents' do
|
3622
|
+
expect(Band.where(name: 'FKA Twigs').first.labels.collect(&:name)).to match_array(['Warner', 'Cbs'])
|
3623
|
+
end
|
3624
|
+
end
|
3625
|
+
end
|
3626
|
+
|
3627
|
+
describe "#update_all" do
|
3628
|
+
|
3629
|
+
let!(:depeche_mode) do
|
3630
|
+
Band.create!(name: "Depeche Mode", origin: "Essex")
|
3631
|
+
end
|
3632
|
+
|
3633
|
+
let!(:new_order) do
|
3634
|
+
Band.create!(name: "New Order")
|
3635
|
+
end
|
3636
|
+
|
3637
|
+
let(:criteria) do
|
3638
|
+
Band.all
|
3639
|
+
end
|
3640
|
+
|
3641
|
+
let(:context) do
|
3642
|
+
described_class.new(criteria)
|
3643
|
+
end
|
3644
|
+
|
3645
|
+
context "when providing attributes" do
|
3646
|
+
|
3647
|
+
context "when the attributes are of the correct type" do
|
3648
|
+
|
3649
|
+
before do
|
3650
|
+
context.update_all(name: "Smiths")
|
3651
|
+
end
|
3652
|
+
|
3653
|
+
it "updates the first matching document" do
|
3654
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3655
|
+
end
|
3656
|
+
|
3657
|
+
it "does not clear out other attributes" do
|
3658
|
+
expect(depeche_mode.reload.origin).to eq("Essex")
|
3659
|
+
end
|
3660
|
+
|
3661
|
+
it "updates the last matching document" do
|
3662
|
+
expect(new_order.reload.name).to eq("Smiths")
|
3663
|
+
end
|
3664
|
+
end
|
3665
|
+
|
3666
|
+
context "when the attributes must be mongoized" do
|
3667
|
+
|
3668
|
+
before do
|
3669
|
+
context.update_all(member_count: "1")
|
3670
|
+
end
|
3671
|
+
|
3672
|
+
it "updates the first matching document" do
|
3673
|
+
expect(depeche_mode.reload.member_count).to eq(1)
|
3674
|
+
end
|
3675
|
+
|
3676
|
+
it "updates the last matching document" do
|
3677
|
+
expect(new_order.reload.member_count).to eq(1)
|
3678
|
+
end
|
3679
|
+
end
|
3680
|
+
|
3681
|
+
context "when using aliased field names" do
|
3682
|
+
|
3683
|
+
before do
|
3684
|
+
context.update_all(years: 100)
|
3685
|
+
end
|
3686
|
+
|
3687
|
+
it "updates the first matching document" do
|
3688
|
+
expect(depeche_mode.reload.years).to eq(100)
|
3689
|
+
end
|
3690
|
+
|
3691
|
+
it "updates the last matching document" do
|
3692
|
+
expect(new_order.reload.years).to eq(100)
|
3693
|
+
end
|
3694
|
+
end
|
3695
|
+
end
|
3696
|
+
|
3697
|
+
context "when providing atomic operations" do
|
3698
|
+
|
3699
|
+
context "when only atomic operations are provided" do
|
3700
|
+
|
3701
|
+
context "when the attributes are in the correct type" do
|
3702
|
+
|
3703
|
+
context "when operation is $set" do
|
3704
|
+
|
3705
|
+
before do
|
3706
|
+
context.update_all("$set" => { name: "Smiths" })
|
3707
|
+
end
|
3708
|
+
|
3709
|
+
it "updates the first matching document" do
|
3710
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3711
|
+
end
|
3712
|
+
|
3713
|
+
it "updates the last matching document" do
|
3714
|
+
expect(new_order.reload.name).to eq("Smiths")
|
3715
|
+
end
|
3716
|
+
end
|
3717
|
+
|
3718
|
+
context "when operation is $push" do
|
3719
|
+
|
3720
|
+
before do
|
3721
|
+
depeche_mode.update_attribute(:genres, ["electronic"])
|
3722
|
+
new_order.update_attribute(:genres, ["electronic"])
|
3723
|
+
context.update_all("$push" => { genres: "pop" })
|
3724
|
+
end
|
3725
|
+
|
3726
|
+
it "updates the first matching document" do
|
3727
|
+
expect(depeche_mode.reload.genres).to eq(["electronic", "pop"])
|
3728
|
+
end
|
3729
|
+
|
3730
|
+
it "updates the last matching document" do
|
3731
|
+
expect(new_order.reload.genres).to eq(["electronic", "pop"])
|
3732
|
+
end
|
3733
|
+
end
|
3734
|
+
|
3735
|
+
context "when operation is $addToSet" do
|
3736
|
+
|
3737
|
+
before do
|
3738
|
+
context.update_all("$addToSet" => { genres: "electronic" })
|
3739
|
+
end
|
3740
|
+
|
3741
|
+
it "updates the first matching document" do
|
3742
|
+
expect(depeche_mode.reload.genres).to eq(["electronic"])
|
3743
|
+
end
|
3744
|
+
|
3745
|
+
it "updates the last matching document" do
|
3746
|
+
expect(new_order.reload.genres).to eq(["electronic"])
|
3747
|
+
end
|
3748
|
+
end
|
3749
|
+
|
3750
|
+
context "when operation is $pull" do
|
3751
|
+
context "when pulling single element" do
|
3752
|
+
|
3753
|
+
before do
|
3754
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop"])
|
3755
|
+
new_order.update_attribute(:genres, ["electronic", "pop"])
|
3756
|
+
context.update_all("$pull" => { genres: "electronic" })
|
3757
|
+
end
|
3758
|
+
|
3759
|
+
it "updates the first matching document" do
|
3760
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3761
|
+
end
|
3762
|
+
|
3763
|
+
it "updates the last matching document" do
|
3764
|
+
expect(new_order.reload.genres).to eq(["pop"])
|
3765
|
+
end
|
3766
|
+
end
|
3767
|
+
|
3768
|
+
context "when pulling based on condition" do
|
3769
|
+
before do
|
3770
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3771
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3772
|
+
context.update_all("$pull" => { genres: { '$in' => ["electronic", "pop"] } })
|
3773
|
+
end
|
3774
|
+
|
3775
|
+
it "updates the first matching document" do
|
3776
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3777
|
+
end
|
3778
|
+
|
3779
|
+
it "updates the last matching document" do
|
3780
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3781
|
+
end
|
3782
|
+
end
|
3783
|
+
end
|
3784
|
+
|
3785
|
+
context "when operation is $pop" do
|
3786
|
+
|
3787
|
+
before do
|
3788
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic"])
|
3789
|
+
end
|
3790
|
+
|
3791
|
+
it "removes first element in array" do
|
3792
|
+
context.update_all("$pop" => { genres: -1 })
|
3793
|
+
expect(depeche_mode.reload.genres).to eq(["electronic"])
|
3794
|
+
end
|
3795
|
+
|
3796
|
+
it "removes last element in array" do
|
3797
|
+
context.update_all("$pop" => { genres: 1 })
|
3798
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3799
|
+
end
|
3800
|
+
end
|
3801
|
+
|
3802
|
+
context "when operation is $pullAll" do
|
3803
|
+
|
3804
|
+
before do
|
3805
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic", "dance", "pop" ])
|
3806
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "electronic", "dance"])
|
3807
|
+
context.update_all("$pullAll" => { genres: ["pop", "electronic"] })
|
3808
|
+
end
|
3809
|
+
|
3810
|
+
it "updates the first matching document" do
|
3811
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3812
|
+
end
|
3813
|
+
|
3814
|
+
it "updates the last matching document" do
|
3815
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3816
|
+
end
|
3817
|
+
end
|
3818
|
+
end
|
3819
|
+
|
3820
|
+
context 'when using aliased field names' do
|
3821
|
+
before do
|
3822
|
+
context.update_all('$set' => { years: 100 })
|
3823
|
+
end
|
3824
|
+
|
3825
|
+
it "updates the first matching document" do
|
3826
|
+
expect(depeche_mode.reload.years).to eq(100)
|
3827
|
+
end
|
3828
|
+
|
3829
|
+
it "updates the last matching document" do
|
3830
|
+
expect(new_order.reload.years).to eq(100)
|
3831
|
+
end
|
3832
|
+
end
|
3833
|
+
|
3834
|
+
context "when the attributes must be mongoized" do
|
3835
|
+
|
3836
|
+
before do
|
3837
|
+
context.update_all("$set" => { location: LatLng.new(52.30, 13.25) })
|
3838
|
+
end
|
3839
|
+
|
3840
|
+
it "updates the first matching document" do
|
3841
|
+
expect(depeche_mode.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3842
|
+
end
|
3843
|
+
|
3844
|
+
it "updates the last matching document" do
|
3845
|
+
expect(new_order.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3846
|
+
end
|
3847
|
+
end
|
3848
|
+
end
|
3849
|
+
|
3850
|
+
context "when a mix are provided" do
|
3851
|
+
|
3852
|
+
before do
|
3853
|
+
context.update_all("$set" => { name: "Smiths" }, likes: 100)
|
3854
|
+
end
|
3855
|
+
|
3856
|
+
it "updates the first matching document's set" do
|
3857
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3858
|
+
end
|
3859
|
+
|
3860
|
+
it "updates the first matching document's updates" do
|
3861
|
+
expect(depeche_mode.reload.likes).to eq(100)
|
3862
|
+
end
|
3863
|
+
|
3864
|
+
it "updates the last matching document's set" do
|
3865
|
+
expect(new_order.reload.name).to eq("Smiths")
|
3866
|
+
end
|
3867
|
+
|
3868
|
+
it "updates the last matching document's updates" do
|
3869
|
+
expect(new_order.reload.likes).to eq(100)
|
3870
|
+
end
|
3871
|
+
end
|
3872
|
+
end
|
3873
|
+
|
3874
|
+
context "when providing no attributes" do
|
3875
|
+
|
3876
|
+
it "returns false" do
|
3877
|
+
expect(context.update_all).to be false
|
3878
|
+
end
|
3879
|
+
end
|
3880
|
+
|
3881
|
+
context 'when provided array filters' do
|
3882
|
+
min_server_version '3.6'
|
3883
|
+
|
3884
|
+
before do
|
3885
|
+
Band.delete_all
|
3886
|
+
b = Band.new(name: 'Depeche Mode')
|
3887
|
+
b.labels << Label.new(name: 'Warner')
|
3888
|
+
b.labels << Label.new(name: 'Sony')
|
3889
|
+
b.labels << Label.new(name: 'Cbs')
|
3890
|
+
b.save!
|
3891
|
+
|
3892
|
+
b = Band.new(name: 'FKA Twigs')
|
3893
|
+
b.labels << Label.new(name: 'Warner')
|
3894
|
+
b.labels << Label.new(name: 'Cbs')
|
3895
|
+
b.save!
|
3896
|
+
end
|
3897
|
+
|
3898
|
+
|
3899
|
+
let(:criteria) do
|
3900
|
+
Band.all
|
3901
|
+
end
|
3902
|
+
|
3903
|
+
let!(:update) do
|
3904
|
+
context.update_all({ '$set' => { 'labels.$[i].name' => 'Sony' } },
|
3905
|
+
array_filters: [{ 'i.name' => 'Cbs' }])
|
3906
|
+
end
|
3907
|
+
|
3908
|
+
it 'applies the array filters' do
|
3909
|
+
expect(Band.where(name: 'Depeche Mode').first.labels.collect(&:name)).to match_array(['Warner', 'Sony', 'Sony'])
|
3910
|
+
end
|
3911
|
+
|
3912
|
+
it 'updates all documents' do
|
3913
|
+
expect(Band.where(name: 'FKA Twigs').first.labels.collect(&:name)).to match_array(['Warner', 'Sony'])
|
3914
|
+
end
|
3915
|
+
end
|
3916
|
+
end
|
3917
|
+
|
3918
|
+
describe '#pipeline' do
|
3919
|
+
|
3920
|
+
context 'when the criteria has a selector' do
|
3921
|
+
|
3922
|
+
before do
|
3923
|
+
Artist.index(name: "text")
|
3924
|
+
Artist.create_indexes
|
3925
|
+
end
|
3926
|
+
|
3927
|
+
let(:criteria) do
|
3928
|
+
Artist.text_search("New Order")
|
3929
|
+
end
|
3930
|
+
|
3931
|
+
let(:context) do
|
3932
|
+
described_class.new(criteria)
|
3933
|
+
end
|
3934
|
+
|
3935
|
+
let(:pipeline_match) do
|
3936
|
+
context.send(:pipeline, :some_field).first['$match']
|
3937
|
+
end
|
3938
|
+
|
3939
|
+
it 'creates a pipeline with the selector as one of the $match criteria' do
|
3940
|
+
expect(pipeline_match).to include({ '$text' => { '$search' => "New Order" } })
|
3941
|
+
end
|
3942
|
+
|
3943
|
+
it 'creates a pipeline with the $exists operator as one of the $match criteria' do
|
3944
|
+
expect(pipeline_match).to include({ 'some_field' => { '$exists' => true } })
|
3945
|
+
end
|
3946
|
+
end
|
3947
|
+
end
|
3948
|
+
|
3949
|
+
describe "#first!" do
|
3950
|
+
|
3951
|
+
let!(:depeche_mode) do
|
3952
|
+
Band.create!(name: "Depeche Mode")
|
3953
|
+
end
|
3954
|
+
|
3955
|
+
let!(:new_order) do
|
3956
|
+
Band.create!(name: "New Order")
|
3957
|
+
end
|
3958
|
+
|
3959
|
+
let!(:rolling_stones) do
|
3960
|
+
Band.create!(name: "The Rolling Stones")
|
3961
|
+
end
|
3962
|
+
|
3963
|
+
let!(:death_cab) do
|
3964
|
+
Band.create!(name: "Death Cab For Cutie")
|
3965
|
+
end
|
3966
|
+
|
3967
|
+
let(:context) do
|
3968
|
+
described_class.new(criteria)
|
3969
|
+
end
|
3970
|
+
|
3971
|
+
context "when there's no sort" do
|
3972
|
+
let(:criteria) do
|
3973
|
+
Band.all
|
3974
|
+
end
|
3975
|
+
|
3976
|
+
it "gets the first document" do
|
3977
|
+
expect(context.first!).to eq(depeche_mode)
|
3978
|
+
end
|
3979
|
+
end
|
3980
|
+
|
3981
|
+
context "when there's a custom sort" do
|
3982
|
+
let(:criteria) do
|
3983
|
+
Band.all
|
3984
|
+
end
|
3985
|
+
|
3986
|
+
it "gets the first document" do
|
3987
|
+
expect(context.sort(name: 1).first!).to eq(death_cab)
|
3988
|
+
end
|
3989
|
+
end
|
3990
|
+
|
3991
|
+
context "when there are no documents" do
|
3992
|
+
let(:criteria) do
|
3993
|
+
Band.where(name: "bogus")
|
3994
|
+
end
|
3995
|
+
|
3996
|
+
it "raises an error" do
|
3997
|
+
expect do
|
3998
|
+
context.first!
|
3999
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
4000
|
+
end
|
4001
|
+
end
|
4002
|
+
end
|
4003
|
+
|
4004
|
+
describe "#last!" do
|
4005
|
+
|
4006
|
+
let!(:depeche_mode) do
|
4007
|
+
Band.create!(name: "Depeche Mode")
|
4008
|
+
end
|
4009
|
+
|
4010
|
+
let!(:new_order) do
|
4011
|
+
Band.create!(name: "New Order")
|
4012
|
+
end
|
4013
|
+
|
4014
|
+
let!(:rolling_stones) do
|
4015
|
+
Band.create!(name: "The Rolling Stones")
|
4016
|
+
end
|
4017
|
+
|
4018
|
+
let!(:death_cab) do
|
4019
|
+
Band.create!(name: "Death Cab For Cutie")
|
4020
|
+
end
|
4021
|
+
|
4022
|
+
let(:context) do
|
4023
|
+
described_class.new(criteria)
|
4024
|
+
end
|
4025
|
+
|
4026
|
+
context "when there's no sort" do
|
4027
|
+
let(:criteria) do
|
4028
|
+
Band.all
|
4029
|
+
end
|
4030
|
+
|
4031
|
+
it "gets the last document" do
|
4032
|
+
expect(context.last!).to eq(death_cab)
|
4033
|
+
end
|
4034
|
+
end
|
4035
|
+
|
4036
|
+
context "when there's a custom sort" do
|
4037
|
+
let(:criteria) do
|
4038
|
+
Band.all
|
4039
|
+
end
|
4040
|
+
|
4041
|
+
it "gets the last document" do
|
4042
|
+
expect(context.sort(name: 1).last!).to eq(rolling_stones)
|
4043
|
+
end
|
4044
|
+
end
|
4045
|
+
|
4046
|
+
context "when there are no documents" do
|
4047
|
+
let(:criteria) do
|
4048
|
+
Band.where(name: "bogus")
|
4049
|
+
end
|
4050
|
+
|
4051
|
+
it "raises an error" do
|
4052
|
+
expect do
|
4053
|
+
context.last!
|
4054
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
4055
|
+
end
|
4056
|
+
end
|
4057
|
+
end
|
4058
|
+
|
4059
|
+
describe "#second" do
|
4060
|
+
|
4061
|
+
let!(:depeche_mode) do
|
4062
|
+
Band.create!(name: "Depeche Mode")
|
4063
|
+
end
|
4064
|
+
|
4065
|
+
let!(:new_order) do
|
4066
|
+
Band.create!(name: "New Order")
|
4067
|
+
end
|
4068
|
+
|
4069
|
+
let!(:rolling_stones) do
|
4070
|
+
Band.create!(name: "The Rolling Stones")
|
4071
|
+
end
|
4072
|
+
|
4073
|
+
let!(:death_cab) do
|
4074
|
+
Band.create!(name: "Death Cab For Cutie")
|
4075
|
+
end
|
4076
|
+
|
4077
|
+
let(:context) do
|
4078
|
+
described_class.new(criteria)
|
4079
|
+
end
|
4080
|
+
|
4081
|
+
context "when there's no sort" do
|
4082
|
+
let(:criteria) do
|
4083
|
+
Band.all
|
4084
|
+
end
|
4085
|
+
|
4086
|
+
it "gets the second document" do
|
4087
|
+
expect(context.second).to eq(new_order)
|
4088
|
+
end
|
4089
|
+
end
|
4090
|
+
|
4091
|
+
context "when there's a custom sort" do
|
4092
|
+
let(:criteria) do
|
4093
|
+
Band.all
|
4094
|
+
end
|
4095
|
+
|
4096
|
+
it "gets the second document" do
|
4097
|
+
expect(context.sort(name: 1).second).to eq(depeche_mode)
|
4098
|
+
end
|
4099
|
+
end
|
4100
|
+
|
4101
|
+
context "when there are no documents" do
|
4102
|
+
let(:criteria) do
|
4103
|
+
Band.where(name: "bogus")
|
4104
|
+
end
|
4105
|
+
|
4106
|
+
it "returns nil" do
|
4107
|
+
expect(context.second).to be_nil
|
4108
|
+
end
|
4109
|
+
end
|
4110
|
+
end
|
4111
|
+
|
4112
|
+
describe "#second!" do
|
4113
|
+
|
4114
|
+
let!(:depeche_mode) do
|
4115
|
+
Band.create!(name: "Depeche Mode")
|
4116
|
+
end
|
4117
|
+
|
4118
|
+
let!(:new_order) do
|
4119
|
+
Band.create!(name: "New Order")
|
4120
|
+
end
|
4121
|
+
|
4122
|
+
let!(:rolling_stones) do
|
4123
|
+
Band.create!(name: "The Rolling Stones")
|
4124
|
+
end
|
4125
|
+
|
4126
|
+
let!(:death_cab) do
|
4127
|
+
Band.create!(name: "Death Cab For Cutie")
|
4128
|
+
end
|
4129
|
+
|
4130
|
+
let(:context) do
|
4131
|
+
described_class.new(criteria)
|
4132
|
+
end
|
4133
|
+
|
4134
|
+
context "when there's no sort" do
|
4135
|
+
let(:criteria) do
|
4136
|
+
Band.all
|
4137
|
+
end
|
4138
|
+
|
4139
|
+
it "gets the second document" do
|
4140
|
+
expect(context.second!).to eq(new_order)
|
4141
|
+
end
|
4142
|
+
end
|
4143
|
+
|
4144
|
+
context "when there's a custom sort" do
|
4145
|
+
let(:criteria) do
|
4146
|
+
Band.all
|
4147
|
+
end
|
4148
|
+
|
4149
|
+
it "gets the second document" do
|
4150
|
+
expect(context.sort(name: 1).second!).to eq(depeche_mode)
|
4151
|
+
end
|
4152
|
+
end
|
4153
|
+
|
4154
|
+
context "when there are no documents" do
|
4155
|
+
let(:criteria) do
|
4156
|
+
Band.where(name: "bogus")
|
4157
|
+
end
|
4158
|
+
|
4159
|
+
it "raises an error" do
|
4160
|
+
expect do
|
4161
|
+
context.second!
|
4162
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
4163
|
+
end
|
4164
|
+
end
|
4165
|
+
end
|
4166
|
+
|
4167
|
+
describe "#third" do
|
3069
4168
|
|
3070
4169
|
let!(:depeche_mode) do
|
3071
4170
|
Band.create!(name: "Depeche Mode")
|
@@ -3075,20 +4174,50 @@ describe Mongoid::Contextual::Mongo do
|
|
3075
4174
|
Band.create!(name: "New Order")
|
3076
4175
|
end
|
3077
4176
|
|
3078
|
-
let(:
|
3079
|
-
Band.
|
4177
|
+
let!(:rolling_stones) do
|
4178
|
+
Band.create!(name: "The Rolling Stones")
|
4179
|
+
end
|
4180
|
+
|
4181
|
+
let!(:death_cab) do
|
4182
|
+
Band.create!(name: "Death Cab For Cutie")
|
3080
4183
|
end
|
3081
4184
|
|
3082
4185
|
let(:context) do
|
3083
4186
|
described_class.new(criteria)
|
3084
4187
|
end
|
3085
4188
|
|
3086
|
-
|
3087
|
-
|
4189
|
+
context "when there's no sort" do
|
4190
|
+
let(:criteria) do
|
4191
|
+
Band.all
|
4192
|
+
end
|
4193
|
+
|
4194
|
+
it "gets the third document" do
|
4195
|
+
expect(context.third).to eq(rolling_stones)
|
4196
|
+
end
|
4197
|
+
end
|
4198
|
+
|
4199
|
+
context "when there's a custom sort" do
|
4200
|
+
let(:criteria) do
|
4201
|
+
Band.all
|
4202
|
+
end
|
4203
|
+
|
4204
|
+
it "gets the third document" do
|
4205
|
+
expect(context.sort(name: 1).third).to eq(new_order)
|
4206
|
+
end
|
4207
|
+
end
|
4208
|
+
|
4209
|
+
context "when there are no documents" do
|
4210
|
+
let(:criteria) do
|
4211
|
+
Band.where(name: "bogus")
|
4212
|
+
end
|
4213
|
+
|
4214
|
+
it "returns nil" do
|
4215
|
+
expect(context.third).to be_nil
|
4216
|
+
end
|
3088
4217
|
end
|
3089
4218
|
end
|
3090
4219
|
|
3091
|
-
describe "#
|
4220
|
+
describe "#third!" do
|
3092
4221
|
|
3093
4222
|
let!(:depeche_mode) do
|
3094
4223
|
Band.create!(name: "Depeche Mode")
|
@@ -3098,40 +4227,52 @@ describe Mongoid::Contextual::Mongo do
|
|
3098
4227
|
Band.create!(name: "New Order")
|
3099
4228
|
end
|
3100
4229
|
|
3101
|
-
let(:
|
3102
|
-
Band.
|
4230
|
+
let!(:rolling_stones) do
|
4231
|
+
Band.create!(name: "The Rolling Stones")
|
4232
|
+
end
|
4233
|
+
|
4234
|
+
let!(:death_cab) do
|
4235
|
+
Band.create!(name: "Death Cab For Cutie")
|
3103
4236
|
end
|
3104
4237
|
|
3105
4238
|
let(:context) do
|
3106
4239
|
described_class.new(criteria)
|
3107
4240
|
end
|
3108
4241
|
|
3109
|
-
context "when
|
3110
|
-
|
3111
|
-
|
3112
|
-
expect(context.sort(name: -1).entries).to eq([ new_order, depeche_mode ])
|
4242
|
+
context "when there's no sort" do
|
4243
|
+
let(:criteria) do
|
4244
|
+
Band.all
|
3113
4245
|
end
|
3114
4246
|
|
3115
|
-
it "
|
3116
|
-
expect(context.
|
4247
|
+
it "gets the third document" do
|
4248
|
+
expect(context.third!).to eq(rolling_stones)
|
3117
4249
|
end
|
3118
4250
|
end
|
3119
4251
|
|
3120
|
-
context "when
|
4252
|
+
context "when there's a custom sort" do
|
4253
|
+
let(:criteria) do
|
4254
|
+
Band.all
|
4255
|
+
end
|
3121
4256
|
|
3122
|
-
|
3123
|
-
context.sort
|
3124
|
-
b.name <=> a.name
|
3125
|
-
end
|
4257
|
+
it "gets the third document" do
|
4258
|
+
expect(context.sort(name: 1).third!).to eq(new_order)
|
3126
4259
|
end
|
4260
|
+
end
|
3127
4261
|
|
3128
|
-
|
3129
|
-
|
4262
|
+
context "when there are no documents" do
|
4263
|
+
let(:criteria) do
|
4264
|
+
Band.where(name: "bogus")
|
4265
|
+
end
|
4266
|
+
|
4267
|
+
it "raises an error" do
|
4268
|
+
expect do
|
4269
|
+
context.third!
|
4270
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
3130
4271
|
end
|
3131
4272
|
end
|
3132
4273
|
end
|
3133
4274
|
|
3134
|
-
describe "#
|
4275
|
+
describe "#fourth" do
|
3135
4276
|
|
3136
4277
|
let!(:depeche_mode) do
|
3137
4278
|
Band.create!(name: "Depeche Mode")
|
@@ -3141,388 +4282,498 @@ describe Mongoid::Contextual::Mongo do
|
|
3141
4282
|
Band.create!(name: "New Order")
|
3142
4283
|
end
|
3143
4284
|
|
3144
|
-
let(:
|
3145
|
-
Band.
|
4285
|
+
let!(:rolling_stones) do
|
4286
|
+
Band.create!(name: "The Rolling Stones")
|
4287
|
+
end
|
4288
|
+
|
4289
|
+
let!(:death_cab) do
|
4290
|
+
Band.create!(name: "Death Cab For Cutie")
|
3146
4291
|
end
|
3147
4292
|
|
3148
4293
|
let(:context) do
|
3149
4294
|
described_class.new(criteria)
|
3150
4295
|
end
|
3151
4296
|
|
3152
|
-
context "when
|
3153
|
-
|
3154
|
-
|
3155
|
-
Person.create!
|
4297
|
+
context "when there's no sort" do
|
4298
|
+
let(:criteria) do
|
4299
|
+
Band.all
|
3156
4300
|
end
|
3157
4301
|
|
3158
|
-
|
3159
|
-
|
4302
|
+
it "gets the fourth document" do
|
4303
|
+
expect(context.fourth).to eq(death_cab)
|
3160
4304
|
end
|
4305
|
+
end
|
3161
4306
|
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
4307
|
+
context "when there's a custom sort" do
|
4308
|
+
let(:criteria) do
|
4309
|
+
Band.all
|
3165
4310
|
end
|
3166
4311
|
|
3167
|
-
it "
|
3168
|
-
expect(
|
4312
|
+
it "gets the fourth document" do
|
4313
|
+
expect(context.sort(name: 1).fourth).to eq(rolling_stones)
|
3169
4314
|
end
|
3170
4315
|
end
|
3171
4316
|
|
3172
|
-
context "when
|
4317
|
+
context "when there are no documents" do
|
4318
|
+
let(:criteria) do
|
4319
|
+
Band.where(name: "bogus")
|
4320
|
+
end
|
3173
4321
|
|
3174
|
-
|
4322
|
+
it "returns nil" do
|
4323
|
+
expect(context.fourth).to be_nil
|
4324
|
+
end
|
4325
|
+
end
|
4326
|
+
end
|
3175
4327
|
|
3176
|
-
|
3177
|
-
context.update(name: "Smiths")
|
3178
|
-
end
|
4328
|
+
describe "#fourth!" do
|
3179
4329
|
|
3180
|
-
|
3181
|
-
|
3182
|
-
|
4330
|
+
let!(:depeche_mode) do
|
4331
|
+
Band.create!(name: "Depeche Mode")
|
4332
|
+
end
|
3183
4333
|
|
3184
|
-
|
3185
|
-
|
3186
|
-
|
3187
|
-
end
|
4334
|
+
let!(:new_order) do
|
4335
|
+
Band.create!(name: "New Order")
|
4336
|
+
end
|
3188
4337
|
|
3189
|
-
|
4338
|
+
let!(:rolling_stones) do
|
4339
|
+
Band.create!(name: "The Rolling Stones")
|
4340
|
+
end
|
3190
4341
|
|
3191
|
-
|
4342
|
+
let!(:death_cab) do
|
4343
|
+
Band.create!(name: "Death Cab For Cutie")
|
4344
|
+
end
|
3192
4345
|
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
4346
|
+
let(:context) do
|
4347
|
+
described_class.new(criteria)
|
4348
|
+
end
|
3196
4349
|
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
4350
|
+
context "when there's no sort" do
|
4351
|
+
let(:criteria) do
|
4352
|
+
Band.all
|
4353
|
+
end
|
3200
4354
|
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
4355
|
+
it "gets the fourth document" do
|
4356
|
+
expect(context.fourth!).to eq(death_cab)
|
4357
|
+
end
|
4358
|
+
end
|
3205
4359
|
|
3206
|
-
|
4360
|
+
context "when there's a custom sort" do
|
4361
|
+
let(:criteria) do
|
4362
|
+
Band.all
|
4363
|
+
end
|
3207
4364
|
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
4365
|
+
it "gets the fourth document" do
|
4366
|
+
expect(context.sort(name: 1).fourth!).to eq(rolling_stones)
|
4367
|
+
end
|
4368
|
+
end
|
3211
4369
|
|
3212
|
-
|
3213
|
-
|
3214
|
-
|
4370
|
+
context "when there are no documents" do
|
4371
|
+
let(:criteria) do
|
4372
|
+
Band.where(name: "bogus")
|
4373
|
+
end
|
3215
4374
|
|
3216
|
-
|
3217
|
-
|
3218
|
-
|
3219
|
-
end
|
4375
|
+
it "raises an error" do
|
4376
|
+
expect do
|
4377
|
+
context.fourth!
|
4378
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
3220
4379
|
end
|
3221
4380
|
end
|
4381
|
+
end
|
3222
4382
|
|
3223
|
-
|
4383
|
+
describe "#fifth" do
|
3224
4384
|
|
3225
|
-
|
4385
|
+
let!(:depeche_mode) do
|
4386
|
+
Band.create!(name: "Depeche Mode")
|
4387
|
+
end
|
3226
4388
|
|
3227
|
-
|
4389
|
+
let!(:new_order) do
|
4390
|
+
Band.create!(name: "New Order")
|
4391
|
+
end
|
3228
4392
|
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
4393
|
+
let!(:rolling_stones) do
|
4394
|
+
Band.create!(name: "The Rolling Stones")
|
4395
|
+
end
|
3232
4396
|
|
3233
|
-
|
3234
|
-
|
3235
|
-
|
4397
|
+
let!(:death_cab) do
|
4398
|
+
Band.create!(name: "Death Cab For Cutie")
|
4399
|
+
end
|
3236
4400
|
|
3237
|
-
|
3238
|
-
|
3239
|
-
|
3240
|
-
end
|
4401
|
+
let!(:guns_and_roses) do
|
4402
|
+
Band.create!(name: "Guns and Roses")
|
4403
|
+
end
|
3241
4404
|
|
3242
|
-
|
4405
|
+
let(:context) do
|
4406
|
+
described_class.new(criteria)
|
4407
|
+
end
|
3243
4408
|
|
3244
|
-
|
3245
|
-
|
3246
|
-
|
4409
|
+
context "when there's no sort" do
|
4410
|
+
let(:criteria) do
|
4411
|
+
Band.all
|
4412
|
+
end
|
3247
4413
|
|
3248
|
-
|
3249
|
-
|
3250
|
-
|
4414
|
+
it "gets the fifth document" do
|
4415
|
+
expect(context.fifth).to eq(guns_and_roses)
|
4416
|
+
end
|
4417
|
+
end
|
3251
4418
|
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
3255
|
-
end
|
4419
|
+
context "when there's a custom sort" do
|
4420
|
+
let(:criteria) do
|
4421
|
+
Band.all
|
3256
4422
|
end
|
3257
4423
|
|
3258
|
-
|
4424
|
+
it "gets the fifth document" do
|
4425
|
+
expect(context.sort(name: 1).fifth).to eq(rolling_stones)
|
4426
|
+
end
|
4427
|
+
end
|
3259
4428
|
|
3260
|
-
|
3261
|
-
|
3262
|
-
|
4429
|
+
context "when there are no documents" do
|
4430
|
+
let(:criteria) do
|
4431
|
+
Band.where(name: "bogus")
|
4432
|
+
end
|
3263
4433
|
|
3264
|
-
|
3265
|
-
|
3266
|
-
|
4434
|
+
it "returns nil" do
|
4435
|
+
expect(context.fifth).to be_nil
|
4436
|
+
end
|
4437
|
+
end
|
4438
|
+
end
|
3267
4439
|
|
3268
|
-
|
3269
|
-
expect(depeche_mode.reload.likes).to eq(100)
|
3270
|
-
end
|
4440
|
+
describe "#fifth!" do
|
3271
4441
|
|
3272
|
-
|
3273
|
-
|
3274
|
-
|
4442
|
+
let!(:depeche_mode) do
|
4443
|
+
Band.create!(name: "Depeche Mode")
|
4444
|
+
end
|
3275
4445
|
|
3276
|
-
|
3277
|
-
|
3278
|
-
end
|
3279
|
-
end
|
4446
|
+
let!(:new_order) do
|
4447
|
+
Band.create!(name: "New Order")
|
3280
4448
|
end
|
3281
4449
|
|
3282
|
-
|
4450
|
+
let!(:rolling_stones) do
|
4451
|
+
Band.create!(name: "The Rolling Stones")
|
4452
|
+
end
|
3283
4453
|
|
3284
|
-
|
3285
|
-
|
3286
|
-
end
|
4454
|
+
let!(:death_cab) do
|
4455
|
+
Band.create!(name: "Death Cab For Cutie")
|
3287
4456
|
end
|
3288
4457
|
|
3289
|
-
|
3290
|
-
|
4458
|
+
let!(:guns_and_roses) do
|
4459
|
+
Band.create!(name: "Guns and Roses")
|
4460
|
+
end
|
3291
4461
|
|
3292
|
-
|
3293
|
-
|
3294
|
-
|
3295
|
-
b.labels << Label.new(name: 'Warner')
|
3296
|
-
b.labels << Label.new(name: 'Sony')
|
3297
|
-
b.labels << Label.new(name: 'Cbs')
|
3298
|
-
b.save!
|
4462
|
+
let(:context) do
|
4463
|
+
described_class.new(criteria)
|
4464
|
+
end
|
3299
4465
|
|
3300
|
-
|
3301
|
-
|
3302
|
-
|
3303
|
-
b.save!
|
4466
|
+
context "when there's no sort" do
|
4467
|
+
let(:criteria) do
|
4468
|
+
Band.all
|
3304
4469
|
end
|
3305
4470
|
|
4471
|
+
it "gets the fifth document" do
|
4472
|
+
expect(context.fifth!).to eq(guns_and_roses)
|
4473
|
+
end
|
4474
|
+
end
|
3306
4475
|
|
4476
|
+
context "when there's a custom sort" do
|
3307
4477
|
let(:criteria) do
|
3308
|
-
Band.
|
4478
|
+
Band.all
|
3309
4479
|
end
|
3310
4480
|
|
3311
|
-
|
3312
|
-
context.
|
3313
|
-
array_filters: [{ 'i.name' => 'Cbs' }])
|
4481
|
+
it "gets the fifth document" do
|
4482
|
+
expect(context.sort(name: 1).fifth!).to eq(rolling_stones)
|
3314
4483
|
end
|
4484
|
+
end
|
3315
4485
|
|
3316
|
-
|
3317
|
-
|
4486
|
+
context "when there are no documents" do
|
4487
|
+
let(:criteria) do
|
4488
|
+
Band.where(name: "bogus")
|
3318
4489
|
end
|
3319
4490
|
|
3320
|
-
it
|
3321
|
-
expect
|
4491
|
+
it "raises an error" do
|
4492
|
+
expect do
|
4493
|
+
context.fifth!
|
4494
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
3322
4495
|
end
|
3323
4496
|
end
|
3324
4497
|
end
|
3325
4498
|
|
3326
|
-
describe "#
|
4499
|
+
describe "#second_to_last" do
|
3327
4500
|
|
3328
4501
|
let!(:depeche_mode) do
|
3329
|
-
Band.create!(name: "Depeche Mode"
|
4502
|
+
Band.create!(name: "Depeche Mode")
|
3330
4503
|
end
|
3331
4504
|
|
3332
4505
|
let!(:new_order) do
|
3333
4506
|
Band.create!(name: "New Order")
|
3334
4507
|
end
|
3335
4508
|
|
3336
|
-
let(:
|
3337
|
-
Band.
|
4509
|
+
let!(:rolling_stones) do
|
4510
|
+
Band.create!(name: "The Rolling Stones")
|
4511
|
+
end
|
4512
|
+
|
4513
|
+
let!(:death_cab) do
|
4514
|
+
Band.create!(name: "Death Cab For Cutie")
|
3338
4515
|
end
|
3339
4516
|
|
3340
4517
|
let(:context) do
|
3341
4518
|
described_class.new(criteria)
|
3342
4519
|
end
|
3343
4520
|
|
3344
|
-
context "when
|
4521
|
+
context "when there's no sort" do
|
4522
|
+
let(:criteria) do
|
4523
|
+
Band.all
|
4524
|
+
end
|
3345
4525
|
|
3346
|
-
|
4526
|
+
it "gets the second_to_last document" do
|
4527
|
+
expect(context.second_to_last).to eq(rolling_stones)
|
4528
|
+
end
|
4529
|
+
end
|
3347
4530
|
|
3348
|
-
|
3349
|
-
|
3350
|
-
|
4531
|
+
context "when there's a custom sort" do
|
4532
|
+
let(:criteria) do
|
4533
|
+
Band.all
|
4534
|
+
end
|
3351
4535
|
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
4536
|
+
it "gets the second_to_last document" do
|
4537
|
+
expect(context.sort(name: 1).second_to_last).to eq(new_order)
|
4538
|
+
end
|
4539
|
+
end
|
3355
4540
|
|
3356
|
-
|
3357
|
-
|
3358
|
-
|
4541
|
+
context "when there are no documents" do
|
4542
|
+
let(:criteria) do
|
4543
|
+
Band.where(name: "bogus")
|
4544
|
+
end
|
3359
4545
|
|
3360
|
-
|
3361
|
-
|
3362
|
-
end
|
4546
|
+
it "returns nil" do
|
4547
|
+
expect(context.second_to_last).to be_nil
|
3363
4548
|
end
|
4549
|
+
end
|
4550
|
+
end
|
3364
4551
|
|
3365
|
-
|
4552
|
+
describe "#second_to_last!" do
|
3366
4553
|
|
3367
|
-
|
3368
|
-
|
3369
|
-
|
4554
|
+
let!(:depeche_mode) do
|
4555
|
+
Band.create!(name: "Depeche Mode")
|
4556
|
+
end
|
3370
4557
|
|
3371
|
-
|
3372
|
-
|
3373
|
-
|
4558
|
+
let!(:new_order) do
|
4559
|
+
Band.create!(name: "New Order")
|
4560
|
+
end
|
3374
4561
|
|
3375
|
-
|
3376
|
-
|
3377
|
-
|
3378
|
-
end
|
4562
|
+
let!(:rolling_stones) do
|
4563
|
+
Band.create!(name: "The Rolling Stones")
|
4564
|
+
end
|
3379
4565
|
|
3380
|
-
|
4566
|
+
let!(:death_cab) do
|
4567
|
+
Band.create!(name: "Death Cab For Cutie")
|
4568
|
+
end
|
3381
4569
|
|
3382
|
-
|
3383
|
-
|
3384
|
-
|
4570
|
+
let(:context) do
|
4571
|
+
described_class.new(criteria)
|
4572
|
+
end
|
3385
4573
|
|
3386
|
-
|
3387
|
-
|
3388
|
-
|
4574
|
+
context "when there's no sort" do
|
4575
|
+
let(:criteria) do
|
4576
|
+
Band.all
|
4577
|
+
end
|
3389
4578
|
|
3390
|
-
|
3391
|
-
|
3392
|
-
end
|
4579
|
+
it "gets the second_to_last document" do
|
4580
|
+
expect(context.second_to_last!).to eq(rolling_stones)
|
3393
4581
|
end
|
3394
4582
|
end
|
3395
4583
|
|
3396
|
-
context "when
|
4584
|
+
context "when there's a custom sort" do
|
4585
|
+
let(:criteria) do
|
4586
|
+
Band.all
|
4587
|
+
end
|
3397
4588
|
|
3398
|
-
|
4589
|
+
it "gets the second_to_last document" do
|
4590
|
+
expect(context.sort(name: 1).second_to_last!).to eq(new_order)
|
4591
|
+
end
|
4592
|
+
end
|
3399
4593
|
|
3400
|
-
|
4594
|
+
context "when there are no documents" do
|
4595
|
+
let(:criteria) do
|
4596
|
+
Band.where(name: "bogus")
|
4597
|
+
end
|
3401
4598
|
|
3402
|
-
|
3403
|
-
|
3404
|
-
|
4599
|
+
it "raises an error" do
|
4600
|
+
expect do
|
4601
|
+
context.second_to_last!
|
4602
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
4603
|
+
end
|
4604
|
+
end
|
4605
|
+
end
|
3405
4606
|
|
3406
|
-
|
3407
|
-
expect(depeche_mode.reload.name).to eq("Smiths")
|
3408
|
-
end
|
4607
|
+
describe "#third_to_last" do
|
3409
4608
|
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3413
|
-
end
|
4609
|
+
let!(:depeche_mode) do
|
4610
|
+
Band.create!(name: "Depeche Mode")
|
4611
|
+
end
|
3414
4612
|
|
3415
|
-
|
4613
|
+
let!(:new_order) do
|
4614
|
+
Band.create!(name: "New Order")
|
4615
|
+
end
|
3416
4616
|
|
3417
|
-
|
3418
|
-
|
3419
|
-
|
4617
|
+
let!(:rolling_stones) do
|
4618
|
+
Band.create!(name: "The Rolling Stones")
|
4619
|
+
end
|
3420
4620
|
|
3421
|
-
|
3422
|
-
|
3423
|
-
|
4621
|
+
let!(:death_cab) do
|
4622
|
+
Band.create!(name: "Death Cab For Cutie")
|
4623
|
+
end
|
3424
4624
|
|
3425
|
-
|
3426
|
-
|
3427
|
-
|
3428
|
-
end
|
3429
|
-
end
|
4625
|
+
let(:context) do
|
4626
|
+
described_class.new(criteria)
|
4627
|
+
end
|
3430
4628
|
|
3431
|
-
|
4629
|
+
context "when there's no sort" do
|
4630
|
+
let(:criteria) do
|
4631
|
+
Band.all
|
4632
|
+
end
|
3432
4633
|
|
3433
|
-
|
3434
|
-
|
3435
|
-
|
4634
|
+
it "gets the third_to_last document" do
|
4635
|
+
expect(context.third_to_last).to eq(new_order)
|
4636
|
+
end
|
4637
|
+
end
|
3436
4638
|
|
3437
|
-
|
3438
|
-
|
3439
|
-
|
4639
|
+
context "when there's a custom sort" do
|
4640
|
+
let(:criteria) do
|
4641
|
+
Band.all
|
4642
|
+
end
|
3440
4643
|
|
3441
|
-
|
3442
|
-
|
3443
|
-
|
4644
|
+
it "gets the third_to_last document" do
|
4645
|
+
expect(context.sort(name: 1).third_to_last).to eq(depeche_mode)
|
4646
|
+
end
|
4647
|
+
end
|
3444
4648
|
|
3445
|
-
|
3446
|
-
|
3447
|
-
|
4649
|
+
context "when there are no documents" do
|
4650
|
+
let(:criteria) do
|
4651
|
+
Band.where(name: "bogus")
|
4652
|
+
end
|
3448
4653
|
|
3449
|
-
|
3450
|
-
|
3451
|
-
end
|
4654
|
+
it "returns nil" do
|
4655
|
+
expect(context.third_to_last).to be_nil
|
3452
4656
|
end
|
3453
4657
|
end
|
4658
|
+
end
|
3454
4659
|
|
3455
|
-
|
4660
|
+
describe "#third_to_last!" do
|
3456
4661
|
|
3457
|
-
|
3458
|
-
|
3459
|
-
end
|
4662
|
+
let!(:depeche_mode) do
|
4663
|
+
Band.create!(name: "Depeche Mode")
|
3460
4664
|
end
|
3461
4665
|
|
3462
|
-
|
3463
|
-
|
4666
|
+
let!(:new_order) do
|
4667
|
+
Band.create!(name: "New Order")
|
4668
|
+
end
|
3464
4669
|
|
3465
|
-
|
3466
|
-
|
3467
|
-
|
3468
|
-
b.labels << Label.new(name: 'Warner')
|
3469
|
-
b.labels << Label.new(name: 'Sony')
|
3470
|
-
b.labels << Label.new(name: 'Cbs')
|
3471
|
-
b.save!
|
4670
|
+
let!(:rolling_stones) do
|
4671
|
+
Band.create!(name: "The Rolling Stones")
|
4672
|
+
end
|
3472
4673
|
|
3473
|
-
|
3474
|
-
|
3475
|
-
|
3476
|
-
|
4674
|
+
let!(:death_cab) do
|
4675
|
+
Band.create!(name: "Death Cab For Cutie")
|
4676
|
+
end
|
4677
|
+
|
4678
|
+
let(:context) do
|
4679
|
+
described_class.new(criteria)
|
4680
|
+
end
|
4681
|
+
|
4682
|
+
context "when there's no sort" do
|
4683
|
+
let(:criteria) do
|
4684
|
+
Band.all
|
3477
4685
|
end
|
3478
4686
|
|
4687
|
+
it "gets the third_to_last document" do
|
4688
|
+
expect(context.third_to_last!).to eq(new_order)
|
4689
|
+
end
|
4690
|
+
end
|
3479
4691
|
|
4692
|
+
context "when there's a custom sort" do
|
3480
4693
|
let(:criteria) do
|
3481
4694
|
Band.all
|
3482
4695
|
end
|
3483
4696
|
|
3484
|
-
|
3485
|
-
context.
|
3486
|
-
array_filters: [{ 'i.name' => 'Cbs' }])
|
4697
|
+
it "gets the third_to_last document" do
|
4698
|
+
expect(context.sort(name: 1).third_to_last!).to eq(depeche_mode)
|
3487
4699
|
end
|
4700
|
+
end
|
3488
4701
|
|
3489
|
-
|
3490
|
-
|
4702
|
+
context "when there are no documents" do
|
4703
|
+
let(:criteria) do
|
4704
|
+
Band.where(name: "bogus")
|
3491
4705
|
end
|
3492
4706
|
|
3493
|
-
it
|
3494
|
-
expect
|
4707
|
+
it "raises an error" do
|
4708
|
+
expect do
|
4709
|
+
context.third_to_last!
|
4710
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
3495
4711
|
end
|
3496
4712
|
end
|
3497
4713
|
end
|
3498
4714
|
|
3499
|
-
describe '#
|
4715
|
+
describe '#load_async' do
|
4716
|
+
let!(:band) do
|
4717
|
+
Band.create!(name: "Depeche Mode")
|
4718
|
+
end
|
3500
4719
|
|
3501
|
-
|
4720
|
+
let(:criteria) do
|
4721
|
+
Band.where(name: "Depeche Mode")
|
4722
|
+
end
|
3502
4723
|
|
3503
|
-
|
3504
|
-
|
3505
|
-
|
3506
|
-
end
|
4724
|
+
let(:context) do
|
4725
|
+
described_class.new(criteria)
|
4726
|
+
end
|
3507
4727
|
|
3508
|
-
|
3509
|
-
|
3510
|
-
end
|
4728
|
+
context 'with global thread pool async query executor' do
|
4729
|
+
config_override :async_query_executor, :global_thread_pool
|
3511
4730
|
|
3512
|
-
|
3513
|
-
|
4731
|
+
it 'preloads the documents' do
|
4732
|
+
context.load_async
|
4733
|
+
context.documents_loader.wait
|
4734
|
+
|
4735
|
+
expect(context.view).not_to receive(:map)
|
4736
|
+
expect(context.to_a).to eq([band])
|
3514
4737
|
end
|
3515
4738
|
|
3516
|
-
|
3517
|
-
|
4739
|
+
it 're-raises exception during preload' do
|
4740
|
+
expect_any_instance_of(Mongoid::Contextual::Mongo::DocumentsLoader)
|
4741
|
+
.to receive(:execute)
|
4742
|
+
.at_least(:once)
|
4743
|
+
.and_raise(Mongo::Error::OperationFailure)
|
4744
|
+
|
4745
|
+
context.load_async
|
4746
|
+
context.documents_loader.wait
|
4747
|
+
|
4748
|
+
expect do
|
4749
|
+
context.to_a
|
4750
|
+
end.to raise_error(Mongo::Error::OperationFailure)
|
3518
4751
|
end
|
4752
|
+
end
|
3519
4753
|
|
3520
|
-
|
3521
|
-
|
4754
|
+
context 'with immediate thread pool async query executor' do
|
4755
|
+
config_override :async_query_executor, :immediate
|
4756
|
+
|
4757
|
+
it 'preloads the documents' do
|
4758
|
+
context.load_async
|
4759
|
+
context.documents_loader.wait
|
4760
|
+
|
4761
|
+
expect(context.view).not_to receive(:map)
|
4762
|
+
expect(context.to_a).to eq([band])
|
3522
4763
|
end
|
3523
4764
|
|
3524
|
-
it '
|
3525
|
-
|
4765
|
+
it 're-raises exception during preload' do
|
4766
|
+
expect_any_instance_of(Mongoid::Contextual::Mongo::DocumentsLoader)
|
4767
|
+
.to receive(:execute)
|
4768
|
+
.at_least(:once)
|
4769
|
+
.and_raise(Mongo::Error::OperationFailure)
|
4770
|
+
|
4771
|
+
context.load_async
|
4772
|
+
context.documents_loader.wait
|
4773
|
+
|
4774
|
+
expect do
|
4775
|
+
context.to_a
|
4776
|
+
end.to raise_error(Mongo::Error::OperationFailure)
|
3526
4777
|
end
|
3527
4778
|
end
|
3528
4779
|
end
|