mongoid 7.5.1 → 8.1.4
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -3
- data/README.md +6 -6
- data/Rakefile +25 -0
- data/lib/config/locales/en.yml +92 -43
- data/lib/mongoid/association/accessors.rb +40 -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 +29 -7
- data/lib/mongoid/association/embedded/batchable.rb +54 -14
- 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/paths/embedded/many.rb +19 -0
- data/lib/mongoid/atomic.rb +7 -0
- 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 +3 -3
- data/lib/mongoid/attributes.rb +51 -42
- data/lib/mongoid/cacheable.rb +2 -2
- 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 +158 -17
- 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 +544 -333
- 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 +1 -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 +47 -38
- data/lib/mongoid/criteria/queryable/selector.rb +93 -8
- data/lib/mongoid/criteria/queryable/smash.rb +40 -7
- data/lib/mongoid/criteria/queryable/storable.rb +1 -1
- 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 +8 -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 +37 -8
- 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 +129 -20
- 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 +186 -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 +33 -13
- 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 +63 -10
- 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 +10 -6
- data/lib/mongoid/shardable.rb +35 -11
- 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 +1 -1
- data/lib/mongoid/timestamps/updated.rb +2 -2
- data/lib/mongoid/touchable.rb +2 -3
- data/lib/mongoid/traversable.rb +5 -4
- data/lib/mongoid/utils.rb +22 -0
- 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 +9 -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 +10 -14
- 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 +21 -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 +2 -1
- 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 +311 -65
- data/spec/mongoid/association/embedded/embeds_many_models.rb +158 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -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 +15 -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 +215 -228
- 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 +235 -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/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_spec.rb +554 -33
- data/spec/mongoid/cacheable_spec.rb +3 -3
- 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 +179 -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 +220 -30
- 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 +2307 -1105
- 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 +78 -86
- data/spec/mongoid/criteria/queryable/selector_spec.rb +90 -5
- data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
- 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 +32 -41
- 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 +500 -84
- 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 +824 -22
- data/spec/mongoid/interceptable_spec_models.rb +235 -4
- 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 +57 -58
- 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 +9 -30
- data/spec/mongoid/shardable_models.rb +14 -0
- data/spec/mongoid/shardable_spec.rb +157 -51
- 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_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/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 -10
- data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
- data/spec/rails/mongoid_spec.rb +4 -16
- data/spec/shared/lib/mrss/docker_runner.rb +8 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
- data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
- data/spec/shared/lib/mrss/utils.rb +28 -6
- data/spec/shared/share/Dockerfile.erb +36 -40
- data/spec/shared/shlib/server.sh +32 -8
- data/spec/shared/shlib/set_env.sh +4 -4
- 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 +4 -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/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
- data.tar.gz.sig +0 -0
- metadata +722 -640
- metadata.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
|
@@ -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
|
|
@@ -1561,24 +2080,6 @@ describe Mongoid::Contextual::Mongo do
|
|
|
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 #last' 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
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
Band.all.cache
|
|
1752
|
-
end
|
|
2221
|
+
let(:criteria) do
|
|
2222
|
+
Band.all
|
|
2223
|
+
end
|
|
1753
2224
|
|
|
1754
|
-
|
|
2225
|
+
before do
|
|
2226
|
+
context.first(before_limit)
|
|
2227
|
+
end
|
|
1755
2228
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
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,14 +2305,15 @@ describe Mongoid::Contextual::Mongo do
|
|
|
1883
2305
|
end
|
|
1884
2306
|
end
|
|
1885
2307
|
|
|
1886
|
-
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
|
|
1887
2310
|
|
|
1888
2311
|
let(:context) do
|
|
1889
2312
|
described_class.new(criteria)
|
|
1890
2313
|
end
|
|
1891
2314
|
|
|
1892
2315
|
let(:criteria) do
|
|
1893
|
-
Band.all
|
|
2316
|
+
Band.all
|
|
1894
2317
|
end
|
|
1895
2318
|
|
|
1896
2319
|
before do
|
|
@@ -1905,8 +2328,10 @@ describe Mongoid::Contextual::Mongo do
|
|
|
1905
2328
|
let(:before_limit) { 2 }
|
|
1906
2329
|
let(:limit) { 1 }
|
|
1907
2330
|
|
|
1908
|
-
it "gets the correct document" do
|
|
1909
|
-
|
|
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
|
|
1910
2335
|
end
|
|
1911
2336
|
end
|
|
1912
2337
|
end
|
|
@@ -1996,30 +2421,10 @@ describe Mongoid::Contextual::Mongo do
|
|
|
1996
2421
|
context 'when calling #first' do
|
|
1997
2422
|
|
|
1998
2423
|
it 'returns the first document, sorted by _id' do
|
|
1999
|
-
pending "MONGOID-5416"
|
|
2000
2424
|
expect(context.last).to eq(rolling_stones)
|
|
2001
2425
|
expect(context.first).to eq(depeche_mode)
|
|
2002
2426
|
end
|
|
2003
2427
|
end
|
|
2004
|
-
|
|
2005
|
-
context 'with option { id_sort: :none }' do
|
|
2006
|
-
let(:opts) do
|
|
2007
|
-
{ id_sort: :none }
|
|
2008
|
-
end
|
|
2009
|
-
|
|
2010
|
-
it 'doesn\'t apply the sort on _id' do
|
|
2011
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
|
2012
|
-
end
|
|
2013
|
-
|
|
2014
|
-
context 'when calling #first' do
|
|
2015
|
-
|
|
2016
|
-
it 'doesn\'t apply the sort on _id' do
|
|
2017
|
-
pending "MONGOID-5416"
|
|
2018
|
-
expect(context.last(opts)).to eq(rolling_stones)
|
|
2019
|
-
expect(context.first(opts)).to eq(depeche_mode)
|
|
2020
|
-
end
|
|
2021
|
-
end
|
|
2022
|
-
end
|
|
2023
2428
|
end
|
|
2024
2429
|
|
|
2025
2430
|
context 'when the criteria has a sort' do
|
|
@@ -2044,25 +2449,6 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2044
2449
|
expect(context.first).to eq(rolling_stones)
|
|
2045
2450
|
end
|
|
2046
2451
|
end
|
|
2047
|
-
|
|
2048
|
-
context 'with option { id_sort: :none }' do
|
|
2049
|
-
|
|
2050
|
-
let(:opts) do
|
|
2051
|
-
{ id_sort: :none }
|
|
2052
|
-
end
|
|
2053
|
-
|
|
2054
|
-
it 'uses the preexisting sort' do
|
|
2055
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
|
2056
|
-
end
|
|
2057
|
-
|
|
2058
|
-
context 'when calling #first' do
|
|
2059
|
-
|
|
2060
|
-
it 'uses the preexisting sort' do
|
|
2061
|
-
expect(context.last(opts)).to eq(depeche_mode)
|
|
2062
|
-
expect(context.first(opts)).to eq(rolling_stones)
|
|
2063
|
-
end
|
|
2064
|
-
end
|
|
2065
|
-
end
|
|
2066
2452
|
end
|
|
2067
2453
|
|
|
2068
2454
|
context "when using .sort" do
|
|
@@ -2091,28 +2477,17 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2091
2477
|
end
|
|
2092
2478
|
end
|
|
2093
2479
|
|
|
2094
|
-
context "when the
|
|
2480
|
+
context "when the query cache is enabled" do
|
|
2481
|
+
query_cache_enabled
|
|
2095
2482
|
|
|
2096
2483
|
let(:criteria) do
|
|
2097
|
-
Band.where(name: "Depeche Mode")
|
|
2484
|
+
Band.where(name: "Depeche Mode")
|
|
2098
2485
|
end
|
|
2099
2486
|
|
|
2100
2487
|
let(:context) do
|
|
2101
2488
|
described_class.new(criteria)
|
|
2102
2489
|
end
|
|
2103
2490
|
|
|
2104
|
-
context "when the cache is loaded" do
|
|
2105
|
-
|
|
2106
|
-
before do
|
|
2107
|
-
context.to_a
|
|
2108
|
-
end
|
|
2109
|
-
|
|
2110
|
-
it "returns the last document without touching the database" do
|
|
2111
|
-
expect(context).to receive(:view).never
|
|
2112
|
-
expect(context.last).to eq(depeche_mode)
|
|
2113
|
-
end
|
|
2114
|
-
end
|
|
2115
|
-
|
|
2116
2491
|
context "when last method was called before" do
|
|
2117
2492
|
|
|
2118
2493
|
before do
|
|
@@ -2120,8 +2495,9 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2120
2495
|
end
|
|
2121
2496
|
|
|
2122
2497
|
it "returns the last document without touching the database" do
|
|
2123
|
-
|
|
2124
|
-
|
|
2498
|
+
expect_no_queries do
|
|
2499
|
+
expect(context.last).to eq(depeche_mode)
|
|
2500
|
+
end
|
|
2125
2501
|
end
|
|
2126
2502
|
end
|
|
2127
2503
|
end
|
|
@@ -2181,71 +2557,15 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2181
2557
|
described_class.new(criteria)
|
|
2182
2558
|
end
|
|
2183
2559
|
|
|
2184
|
-
context "when
|
|
2185
|
-
|
|
2186
|
-
before do
|
|
2187
|
-
context.to_a
|
|
2188
|
-
end
|
|
2189
|
-
|
|
2190
|
-
context "when all of the documents are cached" do
|
|
2191
|
-
|
|
2192
|
-
let(:criteria) do
|
|
2193
|
-
Band.all.cache
|
|
2194
|
-
end
|
|
2195
|
-
|
|
2196
|
-
context "when requesting all of the documents" do
|
|
2197
|
-
|
|
2198
|
-
let(:docs) do
|
|
2199
|
-
context.last(3)
|
|
2200
|
-
end
|
|
2201
|
-
|
|
2202
|
-
it "returns all of the documents without touching the database" do
|
|
2203
|
-
expect(context).to receive(:view).never
|
|
2204
|
-
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
|
2205
|
-
end
|
|
2206
|
-
end
|
|
2207
|
-
|
|
2208
|
-
context "when requesting fewer than all of the documents" do
|
|
2209
|
-
|
|
2210
|
-
let(:docs) do
|
|
2211
|
-
context.last(2)
|
|
2212
|
-
end
|
|
2213
|
-
|
|
2214
|
-
it "returns all of the documents without touching the database" do
|
|
2215
|
-
expect(context).to receive(:view).never
|
|
2216
|
-
expect(docs).to eq([ new_order, rolling_stones ])
|
|
2217
|
-
end
|
|
2218
|
-
end
|
|
2219
|
-
end
|
|
2220
|
-
|
|
2221
|
-
context "when only one document is cached" do
|
|
2222
|
-
|
|
2223
|
-
let(:criteria) do
|
|
2224
|
-
Band.where(name: "Depeche Mode").cache
|
|
2225
|
-
end
|
|
2226
|
-
|
|
2227
|
-
context "when requesting one document" do
|
|
2228
|
-
|
|
2229
|
-
let(:docs) do
|
|
2230
|
-
context.last(1)
|
|
2231
|
-
end
|
|
2232
|
-
|
|
2233
|
-
it "returns one document without touching the database" do
|
|
2234
|
-
expect(context).to receive(:view).never
|
|
2235
|
-
expect(docs).to eq([ depeche_mode ])
|
|
2236
|
-
end
|
|
2237
|
-
end
|
|
2238
|
-
end
|
|
2239
|
-
end
|
|
2240
|
-
|
|
2241
|
-
context "when the last method was called before" do
|
|
2560
|
+
context "when query cache is enabled" do
|
|
2561
|
+
query_cache_enabled
|
|
2242
2562
|
|
|
2243
2563
|
let(:context) do
|
|
2244
2564
|
described_class.new(criteria)
|
|
2245
2565
|
end
|
|
2246
2566
|
|
|
2247
2567
|
let(:criteria) do
|
|
2248
|
-
Band.all
|
|
2568
|
+
Band.all
|
|
2249
2569
|
end
|
|
2250
2570
|
|
|
2251
2571
|
before do
|
|
@@ -2262,18 +2582,20 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2262
2582
|
context "when getting all of the documents" do
|
|
2263
2583
|
let(:limit) { 3 }
|
|
2264
2584
|
|
|
2265
|
-
it "returns all documents without touching the
|
|
2266
|
-
|
|
2267
|
-
|
|
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
|
|
2268
2589
|
end
|
|
2269
2590
|
end
|
|
2270
2591
|
|
|
2271
2592
|
context "when getting fewer documents" do
|
|
2272
2593
|
let(:limit) { 2 }
|
|
2273
2594
|
|
|
2274
|
-
it "returns the correct documents without touching the
|
|
2275
|
-
|
|
2276
|
-
|
|
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
|
|
2277
2599
|
end
|
|
2278
2600
|
end
|
|
2279
2601
|
end
|
|
@@ -2284,9 +2606,10 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2284
2606
|
context "when getting the same number of documents" do
|
|
2285
2607
|
let(:limit) { 2 }
|
|
2286
2608
|
|
|
2287
|
-
it "returns the correct documents without touching the
|
|
2288
|
-
|
|
2289
|
-
|
|
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
|
|
2290
2613
|
end
|
|
2291
2614
|
end
|
|
2292
2615
|
|
|
@@ -2294,8 +2617,9 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2294
2617
|
let(:limit) { 3 }
|
|
2295
2618
|
|
|
2296
2619
|
it "returns the correct documents and touches the database" do
|
|
2297
|
-
|
|
2298
|
-
|
|
2620
|
+
expect_query(1) do
|
|
2621
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
|
2622
|
+
end
|
|
2299
2623
|
end
|
|
2300
2624
|
end
|
|
2301
2625
|
end
|
|
@@ -2307,8 +2631,9 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2307
2631
|
let(:limit) { 1 }
|
|
2308
2632
|
|
|
2309
2633
|
it "returns the correct documents without touching the database" do
|
|
2310
|
-
|
|
2311
|
-
|
|
2634
|
+
expect_no_queries do
|
|
2635
|
+
expect(docs).to eq([ rolling_stones ])
|
|
2636
|
+
end
|
|
2312
2637
|
end
|
|
2313
2638
|
end
|
|
2314
2639
|
|
|
@@ -2316,8 +2641,9 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2316
2641
|
let(:limit) { 3 }
|
|
2317
2642
|
|
|
2318
2643
|
it "returns the correct documents and touches the database" do
|
|
2319
|
-
|
|
2320
|
-
|
|
2644
|
+
expect_query(1) do
|
|
2645
|
+
expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
|
|
2646
|
+
end
|
|
2321
2647
|
end
|
|
2322
2648
|
end
|
|
2323
2649
|
end
|
|
@@ -2325,14 +2651,15 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2325
2651
|
end
|
|
2326
2652
|
end
|
|
2327
2653
|
|
|
2328
|
-
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
|
|
2329
2656
|
|
|
2330
2657
|
let(:context) do
|
|
2331
2658
|
described_class.new(criteria)
|
|
2332
2659
|
end
|
|
2333
2660
|
|
|
2334
2661
|
let(:criteria) do
|
|
2335
|
-
Band.all
|
|
2662
|
+
Band.all
|
|
2336
2663
|
end
|
|
2337
2664
|
|
|
2338
2665
|
before do
|
|
@@ -2348,12 +2675,12 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2348
2675
|
let(:limit) { 1 }
|
|
2349
2676
|
|
|
2350
2677
|
it "hits the database" do
|
|
2351
|
-
|
|
2352
|
-
|
|
2678
|
+
expect_query(1) do
|
|
2679
|
+
docs
|
|
2680
|
+
end
|
|
2353
2681
|
end
|
|
2354
2682
|
|
|
2355
2683
|
it "gets the correct document" do
|
|
2356
|
-
pending "MONGOID-5416"
|
|
2357
2684
|
expect(docs).to eq([ depeche_mode ])
|
|
2358
2685
|
end
|
|
2359
2686
|
end
|
|
@@ -2406,37 +2733,28 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2406
2733
|
described_class.new(criteria)
|
|
2407
2734
|
end
|
|
2408
2735
|
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
end
|
|
2736
|
+
context "when broken_view_options is false" do
|
|
2737
|
+
driver_config_override :broken_view_options, false
|
|
2412
2738
|
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
expect(context.view).to receive(:count_documents).once.and_return(2)
|
|
2416
|
-
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)
|
|
2417
2741
|
end
|
|
2418
2742
|
end
|
|
2419
2743
|
|
|
2420
|
-
context "when
|
|
2421
|
-
|
|
2422
|
-
before do
|
|
2423
|
-
context.entries
|
|
2424
|
-
end
|
|
2744
|
+
context "when broken_view_options is true" do
|
|
2745
|
+
driver_config_override :broken_view_options, true
|
|
2425
2746
|
|
|
2426
|
-
it "returns the
|
|
2427
|
-
expect(context.view).to receive(:count_documents).once.and_return(2)
|
|
2747
|
+
it "returns the number of documents that match" do
|
|
2428
2748
|
expect(context.send(method)).to eq(2)
|
|
2429
2749
|
end
|
|
2750
|
+
end
|
|
2430
2751
|
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
before do
|
|
2434
|
-
context.entries
|
|
2435
|
-
end
|
|
2752
|
+
context "when calling more than once with different limits" do
|
|
2753
|
+
driver_config_override :broken_view_options, false
|
|
2436
2754
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
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)
|
|
2440
2758
|
end
|
|
2441
2759
|
end
|
|
2442
2760
|
end
|
|
@@ -2455,10 +2773,12 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2455
2773
|
expect(context.send(method)).to eq(1)
|
|
2456
2774
|
end
|
|
2457
2775
|
|
|
2458
|
-
context "when calling more than once" do
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
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)
|
|
2462
2782
|
end
|
|
2463
2783
|
end
|
|
2464
2784
|
|
|
@@ -2580,7 +2900,7 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2580
2900
|
it "raises an error" do
|
|
2581
2901
|
expect do
|
|
2582
2902
|
Person.take!
|
|
2583
|
-
end.to raise_error(Mongoid::Errors::DocumentNotFound)
|
|
2903
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Person./)
|
|
2584
2904
|
end
|
|
2585
2905
|
end
|
|
2586
2906
|
end
|
|
@@ -2602,9 +2922,10 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2602
2922
|
|
|
2603
2923
|
context "when passed the symbol field name" do
|
|
2604
2924
|
|
|
2605
|
-
it "
|
|
2606
|
-
expect
|
|
2607
|
-
|
|
2925
|
+
it "raises an error" do
|
|
2926
|
+
expect do
|
|
2927
|
+
context.map(:name)
|
|
2928
|
+
end.to raise_error(ArgumentError)
|
|
2608
2929
|
end
|
|
2609
2930
|
end
|
|
2610
2931
|
|
|
@@ -2833,219 +3154,948 @@ describe Mongoid::Contextual::Mongo do
|
|
|
2833
3154
|
described_class.new(criteria)
|
|
2834
3155
|
end
|
|
2835
3156
|
|
|
2836
|
-
let(:results) do
|
|
2837
|
-
context.map_reduce(map, reduce).out(inline: 1)
|
|
3157
|
+
let(:results) do
|
|
3158
|
+
context.map_reduce(map, reduce).out(inline: 1)
|
|
3159
|
+
end
|
|
3160
|
+
|
|
3161
|
+
it "returns the first aggregate result" do
|
|
3162
|
+
expect(results).to include(
|
|
3163
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3164
|
+
)
|
|
3165
|
+
end
|
|
3166
|
+
|
|
3167
|
+
it "returns the correct number of documents" do
|
|
3168
|
+
expect(results.count).to eq(1)
|
|
3169
|
+
end
|
|
3170
|
+
|
|
3171
|
+
it "contains the entire raw results" do
|
|
3172
|
+
expect(results["results"]).to eq([
|
|
3173
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3174
|
+
])
|
|
3175
|
+
end
|
|
3176
|
+
end
|
|
3177
|
+
|
|
3178
|
+
context "when the output is replace" do
|
|
3179
|
+
|
|
3180
|
+
let(:criteria) do
|
|
3181
|
+
Band.limit(1)
|
|
3182
|
+
end
|
|
3183
|
+
|
|
3184
|
+
let(:context) do
|
|
3185
|
+
described_class.new(criteria)
|
|
3186
|
+
end
|
|
3187
|
+
|
|
3188
|
+
let(:results) do
|
|
3189
|
+
context.map_reduce(map, reduce).out(replace: "mr-output")
|
|
3190
|
+
end
|
|
3191
|
+
|
|
3192
|
+
it "returns the correct number of documents" do
|
|
3193
|
+
expect(results.count).to eq(1)
|
|
3194
|
+
end
|
|
3195
|
+
|
|
3196
|
+
it "contains the entire results" do
|
|
3197
|
+
expect(results).to eq([
|
|
3198
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3199
|
+
])
|
|
3200
|
+
end
|
|
3201
|
+
end
|
|
3202
|
+
|
|
3203
|
+
context "when the output is reduce" do
|
|
3204
|
+
|
|
3205
|
+
let(:criteria) do
|
|
3206
|
+
Band.limit(1)
|
|
3207
|
+
end
|
|
3208
|
+
|
|
3209
|
+
let(:context) do
|
|
3210
|
+
described_class.new(criteria)
|
|
3211
|
+
end
|
|
3212
|
+
|
|
3213
|
+
let(:results) do
|
|
3214
|
+
context.map_reduce(map, reduce).out(reduce: :mr_output)
|
|
3215
|
+
end
|
|
3216
|
+
|
|
3217
|
+
it "returns the correct number of documents" do
|
|
3218
|
+
expect(results.count).to eq(1)
|
|
3219
|
+
end
|
|
3220
|
+
|
|
3221
|
+
it "contains the entire results" do
|
|
3222
|
+
expect(results).to eq([
|
|
3223
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3224
|
+
])
|
|
3225
|
+
end
|
|
3226
|
+
end
|
|
3227
|
+
|
|
3228
|
+
context "when the output is merge" do
|
|
3229
|
+
|
|
3230
|
+
let(:criteria) do
|
|
3231
|
+
Band.limit(1)
|
|
3232
|
+
end
|
|
3233
|
+
|
|
3234
|
+
let(:context) do
|
|
3235
|
+
described_class.new(criteria)
|
|
3236
|
+
end
|
|
3237
|
+
|
|
3238
|
+
let(:results) do
|
|
3239
|
+
context.map_reduce(map, reduce).out(merge: :mr_output)
|
|
3240
|
+
end
|
|
3241
|
+
|
|
3242
|
+
it "returns the correct number of documents" do
|
|
3243
|
+
expect(results.count).to eq(1)
|
|
3244
|
+
end
|
|
3245
|
+
|
|
3246
|
+
it "contains the entire results" do
|
|
3247
|
+
expect(results).to eq([
|
|
3248
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3249
|
+
])
|
|
3250
|
+
end
|
|
3251
|
+
end
|
|
3252
|
+
|
|
3253
|
+
context "when the output specifies a different db" do
|
|
3254
|
+
# Limit is not supported in sharded clusters
|
|
3255
|
+
require_topology :single, :replica_set
|
|
3256
|
+
|
|
3257
|
+
let(:criteria) do
|
|
3258
|
+
Band.limit(1)
|
|
3259
|
+
end
|
|
3260
|
+
|
|
3261
|
+
let(:context) do
|
|
3262
|
+
described_class.new(criteria)
|
|
3263
|
+
end
|
|
3264
|
+
|
|
3265
|
+
after do
|
|
3266
|
+
Band.with(database: 'another-db') do |b|
|
|
3267
|
+
b.all.delete
|
|
3268
|
+
end
|
|
3269
|
+
end
|
|
3270
|
+
|
|
3271
|
+
context 'when db is a string' do
|
|
3272
|
+
|
|
3273
|
+
let(:results) do
|
|
3274
|
+
context.map_reduce(map, reduce).out(merge: :mr_output, db: 'another-db')
|
|
3275
|
+
end
|
|
3276
|
+
|
|
3277
|
+
it "returns the correct number of documents" do
|
|
3278
|
+
expect(results.count).to eq(1)
|
|
3279
|
+
end
|
|
3280
|
+
|
|
3281
|
+
it "contains the entire results" do
|
|
3282
|
+
expect(results).to eq([
|
|
3283
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3284
|
+
])
|
|
3285
|
+
end
|
|
3286
|
+
|
|
3287
|
+
it 'writes to the specified db' do
|
|
3288
|
+
expect(Band.mongo_client.with(database: 'another-db')[:mr_output].find.count).to eq(1)
|
|
3289
|
+
end
|
|
3290
|
+
end
|
|
3291
|
+
|
|
3292
|
+
context 'when db is a symbol' do
|
|
3293
|
+
|
|
3294
|
+
let(:results) do
|
|
3295
|
+
context.map_reduce(map, reduce).out(merge: :mr_output, 'db' => 'another-db')
|
|
3296
|
+
end
|
|
3297
|
+
|
|
3298
|
+
it "returns the correct number of documents" do
|
|
3299
|
+
expect(results.count).to eq(1)
|
|
3300
|
+
end
|
|
3301
|
+
|
|
3302
|
+
it "contains the entire results" do
|
|
3303
|
+
expect(results).to eq([
|
|
3304
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
3305
|
+
])
|
|
3306
|
+
end
|
|
3307
|
+
|
|
3308
|
+
it 'writes to the specified db' do
|
|
3309
|
+
expect(Band.mongo_client.with(database: 'another-db')[:mr_output].find.count).to eq(1)
|
|
3310
|
+
end
|
|
3311
|
+
end
|
|
3312
|
+
end
|
|
3313
|
+
|
|
3314
|
+
context "when providing no output" do
|
|
3315
|
+
|
|
3316
|
+
let(:criteria) do
|
|
3317
|
+
Band.limit(1)
|
|
3318
|
+
end
|
|
3319
|
+
|
|
3320
|
+
let(:context) do
|
|
3321
|
+
described_class.new(criteria)
|
|
3322
|
+
end
|
|
3323
|
+
|
|
3324
|
+
let(:results) do
|
|
3325
|
+
context.map_reduce(map, reduce)
|
|
3326
|
+
end
|
|
3327
|
+
|
|
3328
|
+
it "raises an error" do
|
|
3329
|
+
expect {
|
|
3330
|
+
results.entries
|
|
3331
|
+
}.to raise_error(Mongoid::Errors::NoMapReduceOutput)
|
|
3332
|
+
end
|
|
3333
|
+
end
|
|
3334
|
+
|
|
3335
|
+
context "when providing a finalize" do
|
|
3336
|
+
|
|
3337
|
+
let(:criteria) do
|
|
3338
|
+
Band.limit(1)
|
|
3339
|
+
end
|
|
3340
|
+
|
|
3341
|
+
let(:context) do
|
|
3342
|
+
described_class.new(criteria)
|
|
3343
|
+
end
|
|
3344
|
+
|
|
3345
|
+
let(:finalize) do
|
|
3346
|
+
%Q{
|
|
3347
|
+
function(key, value) {
|
|
3348
|
+
value.extra = true;
|
|
3349
|
+
return value;
|
|
3350
|
+
}}
|
|
3351
|
+
end
|
|
3352
|
+
|
|
3353
|
+
let(:results) do
|
|
3354
|
+
context.map_reduce(map, reduce).out(inline: 1).finalize(finalize)
|
|
3355
|
+
end
|
|
3356
|
+
|
|
3357
|
+
it "returns the correct number of documents" do
|
|
3358
|
+
expect(results.count).to eq(1)
|
|
3359
|
+
end
|
|
3360
|
+
|
|
3361
|
+
it "contains the entire results" do
|
|
3362
|
+
expect(results).to eq([
|
|
3363
|
+
{ "_id" => "Depeche Mode", "value" => { "likes" => 200, "extra" => true }}
|
|
3364
|
+
])
|
|
3365
|
+
end
|
|
3366
|
+
end
|
|
3367
|
+
end
|
|
3368
|
+
|
|
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
|
+
end
|
|
3750
|
+
|
|
3751
|
+
context 'when using aliased field names' do
|
|
3752
|
+
before do
|
|
3753
|
+
context.update_all('$set' => { years: 100 })
|
|
3754
|
+
end
|
|
3755
|
+
|
|
3756
|
+
it "updates the first matching document" do
|
|
3757
|
+
expect(depeche_mode.reload.years).to eq(100)
|
|
3758
|
+
end
|
|
3759
|
+
|
|
3760
|
+
it "updates the last matching document" do
|
|
3761
|
+
expect(new_order.reload.years).to eq(100)
|
|
3762
|
+
end
|
|
3763
|
+
end
|
|
3764
|
+
|
|
3765
|
+
context "when the attributes must be mongoized" do
|
|
3766
|
+
|
|
3767
|
+
before do
|
|
3768
|
+
context.update_all("$set" => { member_count: "1" })
|
|
3769
|
+
end
|
|
3770
|
+
|
|
3771
|
+
it "updates the first matching document" do
|
|
3772
|
+
expect(depeche_mode.reload.member_count).to eq(1)
|
|
3773
|
+
end
|
|
3774
|
+
|
|
3775
|
+
it "updates the last matching document" do
|
|
3776
|
+
expect(new_order.reload.member_count).to eq(1)
|
|
3777
|
+
end
|
|
3778
|
+
end
|
|
3779
|
+
end
|
|
3780
|
+
|
|
3781
|
+
context "when a mix are provided" do
|
|
3782
|
+
|
|
3783
|
+
before do
|
|
3784
|
+
context.update_all("$set" => { name: "Smiths" }, likes: 100)
|
|
3785
|
+
end
|
|
3786
|
+
|
|
3787
|
+
it "updates the first matching document's set" do
|
|
3788
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
|
3789
|
+
end
|
|
3790
|
+
|
|
3791
|
+
it "updates the first matching document's updates" do
|
|
3792
|
+
expect(depeche_mode.reload.likes).to eq(100)
|
|
3793
|
+
end
|
|
3794
|
+
|
|
3795
|
+
it "updates the last matching document's set" do
|
|
3796
|
+
expect(new_order.reload.name).to eq("Smiths")
|
|
3797
|
+
end
|
|
3798
|
+
|
|
3799
|
+
it "updates the last matching document's updates" do
|
|
3800
|
+
expect(new_order.reload.likes).to eq(100)
|
|
3801
|
+
end
|
|
3802
|
+
end
|
|
3803
|
+
end
|
|
3804
|
+
|
|
3805
|
+
context "when providing no attributes" do
|
|
3806
|
+
|
|
3807
|
+
it "returns false" do
|
|
3808
|
+
expect(context.update_all).to be false
|
|
3809
|
+
end
|
|
3810
|
+
end
|
|
3811
|
+
|
|
3812
|
+
context 'when provided array filters' do
|
|
3813
|
+
min_server_version '3.6'
|
|
3814
|
+
|
|
3815
|
+
before do
|
|
3816
|
+
Band.delete_all
|
|
3817
|
+
b = Band.new(name: 'Depeche Mode')
|
|
3818
|
+
b.labels << Label.new(name: 'Warner')
|
|
3819
|
+
b.labels << Label.new(name: 'Sony')
|
|
3820
|
+
b.labels << Label.new(name: 'Cbs')
|
|
3821
|
+
b.save!
|
|
3822
|
+
|
|
3823
|
+
b = Band.new(name: 'FKA Twigs')
|
|
3824
|
+
b.labels << Label.new(name: 'Warner')
|
|
3825
|
+
b.labels << Label.new(name: 'Cbs')
|
|
3826
|
+
b.save!
|
|
3827
|
+
end
|
|
3828
|
+
|
|
3829
|
+
|
|
3830
|
+
let(:criteria) do
|
|
3831
|
+
Band.all
|
|
2838
3832
|
end
|
|
2839
3833
|
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
)
|
|
3834
|
+
let!(:update) do
|
|
3835
|
+
context.update_all({ '$set' => { 'labels.$[i].name' => 'Sony' } },
|
|
3836
|
+
array_filters: [{ 'i.name' => 'Cbs' }])
|
|
2844
3837
|
end
|
|
2845
3838
|
|
|
2846
|
-
it
|
|
2847
|
-
expect(
|
|
3839
|
+
it 'applies the array filters' do
|
|
3840
|
+
expect(Band.where(name: 'Depeche Mode').first.labels.collect(&:name)).to match_array(['Warner', 'Sony', 'Sony'])
|
|
2848
3841
|
end
|
|
2849
3842
|
|
|
2850
|
-
it
|
|
2851
|
-
expect(
|
|
2852
|
-
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
2853
|
-
])
|
|
3843
|
+
it 'updates all documents' do
|
|
3844
|
+
expect(Band.where(name: 'FKA Twigs').first.labels.collect(&:name)).to match_array(['Warner', 'Sony'])
|
|
2854
3845
|
end
|
|
2855
3846
|
end
|
|
3847
|
+
end
|
|
2856
3848
|
|
|
2857
|
-
|
|
3849
|
+
describe '#pipeline' do
|
|
3850
|
+
|
|
3851
|
+
context 'when the criteria has a selector' do
|
|
3852
|
+
|
|
3853
|
+
before do
|
|
3854
|
+
Artist.index(name: "text")
|
|
3855
|
+
Artist.create_indexes
|
|
3856
|
+
end
|
|
2858
3857
|
|
|
2859
3858
|
let(:criteria) do
|
|
2860
|
-
|
|
3859
|
+
Artist.text_search("New Order")
|
|
2861
3860
|
end
|
|
2862
3861
|
|
|
2863
3862
|
let(:context) do
|
|
2864
3863
|
described_class.new(criteria)
|
|
2865
3864
|
end
|
|
2866
3865
|
|
|
2867
|
-
let(:
|
|
2868
|
-
context.
|
|
3866
|
+
let(:pipeline_match) do
|
|
3867
|
+
context.send(:pipeline, :some_field).first['$match']
|
|
2869
3868
|
end
|
|
2870
3869
|
|
|
2871
|
-
it
|
|
2872
|
-
expect(
|
|
3870
|
+
it 'creates a pipeline with the selector as one of the $match criteria' do
|
|
3871
|
+
expect(pipeline_match).to include({ '$text' => { '$search' => "New Order" } })
|
|
2873
3872
|
end
|
|
2874
3873
|
|
|
2875
|
-
it
|
|
2876
|
-
expect(
|
|
2877
|
-
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
2878
|
-
])
|
|
3874
|
+
it 'creates a pipeline with the $exists operator as one of the $match criteria' do
|
|
3875
|
+
expect(pipeline_match).to include({ 'some_field' => { '$exists' => true } })
|
|
2879
3876
|
end
|
|
2880
3877
|
end
|
|
3878
|
+
end
|
|
2881
3879
|
|
|
2882
|
-
|
|
3880
|
+
describe "#first!" do
|
|
2883
3881
|
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
3882
|
+
let!(:depeche_mode) do
|
|
3883
|
+
Band.create!(name: "Depeche Mode")
|
|
3884
|
+
end
|
|
2887
3885
|
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
3886
|
+
let!(:new_order) do
|
|
3887
|
+
Band.create!(name: "New Order")
|
|
3888
|
+
end
|
|
2891
3889
|
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
3890
|
+
let!(:rolling_stones) do
|
|
3891
|
+
Band.create!(name: "The Rolling Stones")
|
|
3892
|
+
end
|
|
2895
3893
|
|
|
2896
|
-
|
|
2897
|
-
|
|
3894
|
+
let!(:death_cab) do
|
|
3895
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3896
|
+
end
|
|
3897
|
+
|
|
3898
|
+
let(:context) do
|
|
3899
|
+
described_class.new(criteria)
|
|
3900
|
+
end
|
|
3901
|
+
|
|
3902
|
+
context "when there's no sort" do
|
|
3903
|
+
let(:criteria) do
|
|
3904
|
+
Band.all
|
|
2898
3905
|
end
|
|
2899
3906
|
|
|
2900
|
-
it "
|
|
2901
|
-
expect(
|
|
2902
|
-
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
2903
|
-
])
|
|
3907
|
+
it "gets the first document" do
|
|
3908
|
+
expect(context.first!).to eq(depeche_mode)
|
|
2904
3909
|
end
|
|
2905
3910
|
end
|
|
2906
3911
|
|
|
2907
|
-
context "when
|
|
2908
|
-
|
|
3912
|
+
context "when there's a custom sort" do
|
|
2909
3913
|
let(:criteria) do
|
|
2910
|
-
Band.
|
|
3914
|
+
Band.all
|
|
2911
3915
|
end
|
|
2912
3916
|
|
|
2913
|
-
|
|
2914
|
-
|
|
3917
|
+
it "gets the first document" do
|
|
3918
|
+
expect(context.sort(name: 1).first!).to eq(death_cab)
|
|
2915
3919
|
end
|
|
3920
|
+
end
|
|
2916
3921
|
|
|
2917
|
-
|
|
2918
|
-
|
|
3922
|
+
context "when there are no documents" do
|
|
3923
|
+
let(:criteria) do
|
|
3924
|
+
Band.where(name: "bogus")
|
|
2919
3925
|
end
|
|
2920
3926
|
|
|
2921
|
-
it "
|
|
2922
|
-
expect
|
|
3927
|
+
it "raises an error" do
|
|
3928
|
+
expect do
|
|
3929
|
+
context.first!
|
|
3930
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
2923
3931
|
end
|
|
3932
|
+
end
|
|
3933
|
+
end
|
|
2924
3934
|
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
end
|
|
3935
|
+
describe "#last!" do
|
|
3936
|
+
|
|
3937
|
+
let!(:depeche_mode) do
|
|
3938
|
+
Band.create!(name: "Depeche Mode")
|
|
2930
3939
|
end
|
|
2931
3940
|
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
3941
|
+
let!(:new_order) do
|
|
3942
|
+
Band.create!(name: "New Order")
|
|
3943
|
+
end
|
|
3944
|
+
|
|
3945
|
+
let!(:rolling_stones) do
|
|
3946
|
+
Band.create!(name: "The Rolling Stones")
|
|
3947
|
+
end
|
|
3948
|
+
|
|
3949
|
+
let!(:death_cab) do
|
|
3950
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3951
|
+
end
|
|
2935
3952
|
|
|
3953
|
+
let(:context) do
|
|
3954
|
+
described_class.new(criteria)
|
|
3955
|
+
end
|
|
3956
|
+
|
|
3957
|
+
context "when there's no sort" do
|
|
2936
3958
|
let(:criteria) do
|
|
2937
|
-
Band.
|
|
3959
|
+
Band.all
|
|
2938
3960
|
end
|
|
2939
3961
|
|
|
2940
|
-
|
|
2941
|
-
|
|
3962
|
+
it "gets the last document" do
|
|
3963
|
+
expect(context.last!).to eq(death_cab)
|
|
2942
3964
|
end
|
|
3965
|
+
end
|
|
2943
3966
|
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
end
|
|
3967
|
+
context "when there's a custom sort" do
|
|
3968
|
+
let(:criteria) do
|
|
3969
|
+
Band.all
|
|
2948
3970
|
end
|
|
2949
3971
|
|
|
2950
|
-
|
|
3972
|
+
it "gets the last document" do
|
|
3973
|
+
expect(context.sort(name: 1).last!).to eq(rolling_stones)
|
|
3974
|
+
end
|
|
3975
|
+
end
|
|
2951
3976
|
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
3977
|
+
context "when there are no documents" do
|
|
3978
|
+
let(:criteria) do
|
|
3979
|
+
Band.where(name: "bogus")
|
|
3980
|
+
end
|
|
2955
3981
|
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
3982
|
+
it "raises an error" do
|
|
3983
|
+
expect do
|
|
3984
|
+
context.last!
|
|
3985
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3986
|
+
end
|
|
3987
|
+
end
|
|
3988
|
+
end
|
|
2959
3989
|
|
|
2960
|
-
|
|
2961
|
-
expect(results).to eq([
|
|
2962
|
-
{ "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
|
|
2963
|
-
])
|
|
2964
|
-
end
|
|
3990
|
+
describe "#second" do
|
|
2965
3991
|
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
end
|
|
3992
|
+
let!(:depeche_mode) do
|
|
3993
|
+
Band.create!(name: "Depeche Mode")
|
|
3994
|
+
end
|
|
2970
3995
|
|
|
2971
|
-
|
|
3996
|
+
let!(:new_order) do
|
|
3997
|
+
Band.create!(name: "New Order")
|
|
3998
|
+
end
|
|
2972
3999
|
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
4000
|
+
let!(:rolling_stones) do
|
|
4001
|
+
Band.create!(name: "The Rolling Stones")
|
|
4002
|
+
end
|
|
2976
4003
|
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
4004
|
+
let!(:death_cab) do
|
|
4005
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4006
|
+
end
|
|
2980
4007
|
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
])
|
|
2985
|
-
end
|
|
4008
|
+
let(:context) do
|
|
4009
|
+
described_class.new(criteria)
|
|
4010
|
+
end
|
|
2986
4011
|
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
4012
|
+
context "when there's no sort" do
|
|
4013
|
+
let(:criteria) do
|
|
4014
|
+
Band.all
|
|
2990
4015
|
end
|
|
2991
|
-
end
|
|
2992
4016
|
|
|
2993
|
-
|
|
4017
|
+
it "gets the second document" do
|
|
4018
|
+
expect(context.second).to eq(new_order)
|
|
4019
|
+
end
|
|
4020
|
+
end
|
|
2994
4021
|
|
|
4022
|
+
context "when there's a custom sort" do
|
|
2995
4023
|
let(:criteria) do
|
|
2996
|
-
Band.
|
|
4024
|
+
Band.all
|
|
2997
4025
|
end
|
|
2998
4026
|
|
|
2999
|
-
|
|
3000
|
-
|
|
4027
|
+
it "gets the second document" do
|
|
4028
|
+
expect(context.sort(name: 1).second).to eq(depeche_mode)
|
|
3001
4029
|
end
|
|
4030
|
+
end
|
|
3002
4031
|
|
|
3003
|
-
|
|
3004
|
-
|
|
4032
|
+
context "when there are no documents" do
|
|
4033
|
+
let(:criteria) do
|
|
4034
|
+
Band.where(name: "bogus")
|
|
3005
4035
|
end
|
|
3006
4036
|
|
|
3007
|
-
it "
|
|
3008
|
-
expect
|
|
3009
|
-
results.entries
|
|
3010
|
-
}.to raise_error(Mongoid::Errors::NoMapReduceOutput)
|
|
4037
|
+
it "returns nil" do
|
|
4038
|
+
expect(context.second).to be_nil
|
|
3011
4039
|
end
|
|
3012
4040
|
end
|
|
4041
|
+
end
|
|
3013
4042
|
|
|
3014
|
-
|
|
4043
|
+
describe "#second!" do
|
|
4044
|
+
|
|
4045
|
+
let!(:depeche_mode) do
|
|
4046
|
+
Band.create!(name: "Depeche Mode")
|
|
4047
|
+
end
|
|
4048
|
+
|
|
4049
|
+
let!(:new_order) do
|
|
4050
|
+
Band.create!(name: "New Order")
|
|
4051
|
+
end
|
|
4052
|
+
|
|
4053
|
+
let!(:rolling_stones) do
|
|
4054
|
+
Band.create!(name: "The Rolling Stones")
|
|
4055
|
+
end
|
|
4056
|
+
|
|
4057
|
+
let!(:death_cab) do
|
|
4058
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4059
|
+
end
|
|
4060
|
+
|
|
4061
|
+
let(:context) do
|
|
4062
|
+
described_class.new(criteria)
|
|
4063
|
+
end
|
|
3015
4064
|
|
|
4065
|
+
context "when there's no sort" do
|
|
3016
4066
|
let(:criteria) do
|
|
3017
|
-
Band.
|
|
4067
|
+
Band.all
|
|
3018
4068
|
end
|
|
3019
4069
|
|
|
3020
|
-
|
|
3021
|
-
|
|
4070
|
+
it "gets the second document" do
|
|
4071
|
+
expect(context.second!).to eq(new_order)
|
|
3022
4072
|
end
|
|
4073
|
+
end
|
|
3023
4074
|
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
value.extra = true;
|
|
3028
|
-
return value;
|
|
3029
|
-
}}
|
|
4075
|
+
context "when there's a custom sort" do
|
|
4076
|
+
let(:criteria) do
|
|
4077
|
+
Band.all
|
|
3030
4078
|
end
|
|
3031
4079
|
|
|
3032
|
-
|
|
3033
|
-
context.
|
|
4080
|
+
it "gets the second document" do
|
|
4081
|
+
expect(context.sort(name: 1).second!).to eq(depeche_mode)
|
|
3034
4082
|
end
|
|
4083
|
+
end
|
|
3035
4084
|
|
|
3036
|
-
|
|
3037
|
-
|
|
4085
|
+
context "when there are no documents" do
|
|
4086
|
+
let(:criteria) do
|
|
4087
|
+
Band.where(name: "bogus")
|
|
3038
4088
|
end
|
|
3039
4089
|
|
|
3040
|
-
it "
|
|
3041
|
-
expect
|
|
3042
|
-
|
|
3043
|
-
|
|
4090
|
+
it "raises an error" do
|
|
4091
|
+
expect do
|
|
4092
|
+
context.second!
|
|
4093
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3044
4094
|
end
|
|
3045
4095
|
end
|
|
3046
4096
|
end
|
|
3047
4097
|
|
|
3048
|
-
describe "#
|
|
4098
|
+
describe "#third" do
|
|
3049
4099
|
|
|
3050
4100
|
let!(:depeche_mode) do
|
|
3051
4101
|
Band.create!(name: "Depeche Mode")
|
|
@@ -3055,20 +4105,50 @@ describe Mongoid::Contextual::Mongo do
|
|
|
3055
4105
|
Band.create!(name: "New Order")
|
|
3056
4106
|
end
|
|
3057
4107
|
|
|
3058
|
-
let(:
|
|
3059
|
-
Band.
|
|
4108
|
+
let!(:rolling_stones) do
|
|
4109
|
+
Band.create!(name: "The Rolling Stones")
|
|
4110
|
+
end
|
|
4111
|
+
|
|
4112
|
+
let!(:death_cab) do
|
|
4113
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3060
4114
|
end
|
|
3061
4115
|
|
|
3062
4116
|
let(:context) do
|
|
3063
4117
|
described_class.new(criteria)
|
|
3064
4118
|
end
|
|
3065
4119
|
|
|
3066
|
-
|
|
3067
|
-
|
|
4120
|
+
context "when there's no sort" do
|
|
4121
|
+
let(:criteria) do
|
|
4122
|
+
Band.all
|
|
4123
|
+
end
|
|
4124
|
+
|
|
4125
|
+
it "gets the third document" do
|
|
4126
|
+
expect(context.third).to eq(rolling_stones)
|
|
4127
|
+
end
|
|
4128
|
+
end
|
|
4129
|
+
|
|
4130
|
+
context "when there's a custom sort" do
|
|
4131
|
+
let(:criteria) do
|
|
4132
|
+
Band.all
|
|
4133
|
+
end
|
|
4134
|
+
|
|
4135
|
+
it "gets the third document" do
|
|
4136
|
+
expect(context.sort(name: 1).third).to eq(new_order)
|
|
4137
|
+
end
|
|
4138
|
+
end
|
|
4139
|
+
|
|
4140
|
+
context "when there are no documents" do
|
|
4141
|
+
let(:criteria) do
|
|
4142
|
+
Band.where(name: "bogus")
|
|
4143
|
+
end
|
|
4144
|
+
|
|
4145
|
+
it "returns nil" do
|
|
4146
|
+
expect(context.third).to be_nil
|
|
4147
|
+
end
|
|
3068
4148
|
end
|
|
3069
4149
|
end
|
|
3070
4150
|
|
|
3071
|
-
describe "#
|
|
4151
|
+
describe "#third!" do
|
|
3072
4152
|
|
|
3073
4153
|
let!(:depeche_mode) do
|
|
3074
4154
|
Band.create!(name: "Depeche Mode")
|
|
@@ -3078,40 +4158,52 @@ describe Mongoid::Contextual::Mongo do
|
|
|
3078
4158
|
Band.create!(name: "New Order")
|
|
3079
4159
|
end
|
|
3080
4160
|
|
|
3081
|
-
let(:
|
|
3082
|
-
Band.
|
|
4161
|
+
let!(:rolling_stones) do
|
|
4162
|
+
Band.create!(name: "The Rolling Stones")
|
|
4163
|
+
end
|
|
4164
|
+
|
|
4165
|
+
let!(:death_cab) do
|
|
4166
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3083
4167
|
end
|
|
3084
4168
|
|
|
3085
4169
|
let(:context) do
|
|
3086
4170
|
described_class.new(criteria)
|
|
3087
4171
|
end
|
|
3088
4172
|
|
|
3089
|
-
context "when
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
expect(context.sort(name: -1).entries).to eq([ new_order, depeche_mode ])
|
|
4173
|
+
context "when there's no sort" do
|
|
4174
|
+
let(:criteria) do
|
|
4175
|
+
Band.all
|
|
3093
4176
|
end
|
|
3094
4177
|
|
|
3095
|
-
it "
|
|
3096
|
-
expect(context.
|
|
4178
|
+
it "gets the third document" do
|
|
4179
|
+
expect(context.third!).to eq(rolling_stones)
|
|
3097
4180
|
end
|
|
3098
4181
|
end
|
|
3099
4182
|
|
|
3100
|
-
context "when
|
|
4183
|
+
context "when there's a custom sort" do
|
|
4184
|
+
let(:criteria) do
|
|
4185
|
+
Band.all
|
|
4186
|
+
end
|
|
3101
4187
|
|
|
3102
|
-
|
|
3103
|
-
context.sort
|
|
3104
|
-
b.name <=> a.name
|
|
3105
|
-
end
|
|
4188
|
+
it "gets the third document" do
|
|
4189
|
+
expect(context.sort(name: 1).third!).to eq(new_order)
|
|
3106
4190
|
end
|
|
4191
|
+
end
|
|
3107
4192
|
|
|
3108
|
-
|
|
3109
|
-
|
|
4193
|
+
context "when there are no documents" do
|
|
4194
|
+
let(:criteria) do
|
|
4195
|
+
Band.where(name: "bogus")
|
|
4196
|
+
end
|
|
4197
|
+
|
|
4198
|
+
it "raises an error" do
|
|
4199
|
+
expect do
|
|
4200
|
+
context.third!
|
|
4201
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3110
4202
|
end
|
|
3111
4203
|
end
|
|
3112
4204
|
end
|
|
3113
4205
|
|
|
3114
|
-
describe "#
|
|
4206
|
+
describe "#fourth" do
|
|
3115
4207
|
|
|
3116
4208
|
let!(:depeche_mode) do
|
|
3117
4209
|
Band.create!(name: "Depeche Mode")
|
|
@@ -3121,388 +4213,498 @@ describe Mongoid::Contextual::Mongo do
|
|
|
3121
4213
|
Band.create!(name: "New Order")
|
|
3122
4214
|
end
|
|
3123
4215
|
|
|
3124
|
-
let(:
|
|
3125
|
-
Band.
|
|
4216
|
+
let!(:rolling_stones) do
|
|
4217
|
+
Band.create!(name: "The Rolling Stones")
|
|
4218
|
+
end
|
|
4219
|
+
|
|
4220
|
+
let!(:death_cab) do
|
|
4221
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3126
4222
|
end
|
|
3127
4223
|
|
|
3128
4224
|
let(:context) do
|
|
3129
4225
|
described_class.new(criteria)
|
|
3130
4226
|
end
|
|
3131
4227
|
|
|
3132
|
-
context "when
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
Person.create!
|
|
4228
|
+
context "when there's no sort" do
|
|
4229
|
+
let(:criteria) do
|
|
4230
|
+
Band.all
|
|
3136
4231
|
end
|
|
3137
4232
|
|
|
3138
|
-
|
|
3139
|
-
|
|
4233
|
+
it "gets the fourth document" do
|
|
4234
|
+
expect(context.fourth).to eq(death_cab)
|
|
3140
4235
|
end
|
|
4236
|
+
end
|
|
3141
4237
|
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
4238
|
+
context "when there's a custom sort" do
|
|
4239
|
+
let(:criteria) do
|
|
4240
|
+
Band.all
|
|
3145
4241
|
end
|
|
3146
4242
|
|
|
3147
|
-
it "
|
|
3148
|
-
expect(
|
|
4243
|
+
it "gets the fourth document" do
|
|
4244
|
+
expect(context.sort(name: 1).fourth).to eq(rolling_stones)
|
|
3149
4245
|
end
|
|
3150
4246
|
end
|
|
3151
4247
|
|
|
3152
|
-
context "when
|
|
4248
|
+
context "when there are no documents" do
|
|
4249
|
+
let(:criteria) do
|
|
4250
|
+
Band.where(name: "bogus")
|
|
4251
|
+
end
|
|
3153
4252
|
|
|
3154
|
-
|
|
4253
|
+
it "returns nil" do
|
|
4254
|
+
expect(context.fourth).to be_nil
|
|
4255
|
+
end
|
|
4256
|
+
end
|
|
4257
|
+
end
|
|
3155
4258
|
|
|
3156
|
-
|
|
3157
|
-
context.update(name: "Smiths")
|
|
3158
|
-
end
|
|
4259
|
+
describe "#fourth!" do
|
|
3159
4260
|
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
4261
|
+
let!(:depeche_mode) do
|
|
4262
|
+
Band.create!(name: "Depeche Mode")
|
|
4263
|
+
end
|
|
3163
4264
|
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
end
|
|
4265
|
+
let!(:new_order) do
|
|
4266
|
+
Band.create!(name: "New Order")
|
|
4267
|
+
end
|
|
3168
4268
|
|
|
3169
|
-
|
|
4269
|
+
let!(:rolling_stones) do
|
|
4270
|
+
Band.create!(name: "The Rolling Stones")
|
|
4271
|
+
end
|
|
3170
4272
|
|
|
3171
|
-
|
|
4273
|
+
let!(:death_cab) do
|
|
4274
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4275
|
+
end
|
|
3172
4276
|
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
4277
|
+
let(:context) do
|
|
4278
|
+
described_class.new(criteria)
|
|
4279
|
+
end
|
|
3176
4280
|
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
4281
|
+
context "when there's no sort" do
|
|
4282
|
+
let(:criteria) do
|
|
4283
|
+
Band.all
|
|
4284
|
+
end
|
|
3180
4285
|
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
4286
|
+
it "gets the fourth document" do
|
|
4287
|
+
expect(context.fourth!).to eq(death_cab)
|
|
4288
|
+
end
|
|
4289
|
+
end
|
|
3185
4290
|
|
|
3186
|
-
|
|
4291
|
+
context "when there's a custom sort" do
|
|
4292
|
+
let(:criteria) do
|
|
4293
|
+
Band.all
|
|
4294
|
+
end
|
|
3187
4295
|
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
4296
|
+
it "gets the fourth document" do
|
|
4297
|
+
expect(context.sort(name: 1).fourth!).to eq(rolling_stones)
|
|
4298
|
+
end
|
|
4299
|
+
end
|
|
3191
4300
|
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
4301
|
+
context "when there are no documents" do
|
|
4302
|
+
let(:criteria) do
|
|
4303
|
+
Band.where(name: "bogus")
|
|
4304
|
+
end
|
|
3195
4305
|
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
end
|
|
4306
|
+
it "raises an error" do
|
|
4307
|
+
expect do
|
|
4308
|
+
context.fourth!
|
|
4309
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3200
4310
|
end
|
|
3201
4311
|
end
|
|
4312
|
+
end
|
|
3202
4313
|
|
|
3203
|
-
|
|
4314
|
+
describe "#fifth" do
|
|
3204
4315
|
|
|
3205
|
-
|
|
4316
|
+
let!(:depeche_mode) do
|
|
4317
|
+
Band.create!(name: "Depeche Mode")
|
|
4318
|
+
end
|
|
3206
4319
|
|
|
3207
|
-
|
|
4320
|
+
let!(:new_order) do
|
|
4321
|
+
Band.create!(name: "New Order")
|
|
4322
|
+
end
|
|
3208
4323
|
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
4324
|
+
let!(:rolling_stones) do
|
|
4325
|
+
Band.create!(name: "The Rolling Stones")
|
|
4326
|
+
end
|
|
3212
4327
|
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
4328
|
+
let!(:death_cab) do
|
|
4329
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4330
|
+
end
|
|
3216
4331
|
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
end
|
|
4332
|
+
let!(:guns_and_roses) do
|
|
4333
|
+
Band.create!(name: "Guns and Roses")
|
|
4334
|
+
end
|
|
3221
4335
|
|
|
3222
|
-
|
|
4336
|
+
let(:context) do
|
|
4337
|
+
described_class.new(criteria)
|
|
4338
|
+
end
|
|
3223
4339
|
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
4340
|
+
context "when there's no sort" do
|
|
4341
|
+
let(:criteria) do
|
|
4342
|
+
Band.all
|
|
4343
|
+
end
|
|
3227
4344
|
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
4345
|
+
it "gets the fifth document" do
|
|
4346
|
+
expect(context.fifth).to eq(guns_and_roses)
|
|
4347
|
+
end
|
|
4348
|
+
end
|
|
3231
4349
|
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
end
|
|
4350
|
+
context "when there's a custom sort" do
|
|
4351
|
+
let(:criteria) do
|
|
4352
|
+
Band.all
|
|
3236
4353
|
end
|
|
3237
4354
|
|
|
3238
|
-
|
|
4355
|
+
it "gets the fifth document" do
|
|
4356
|
+
expect(context.sort(name: 1).fifth).to eq(rolling_stones)
|
|
4357
|
+
end
|
|
4358
|
+
end
|
|
3239
4359
|
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
4360
|
+
context "when there are no documents" do
|
|
4361
|
+
let(:criteria) do
|
|
4362
|
+
Band.where(name: "bogus")
|
|
4363
|
+
end
|
|
3243
4364
|
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
4365
|
+
it "returns nil" do
|
|
4366
|
+
expect(context.fifth).to be_nil
|
|
4367
|
+
end
|
|
4368
|
+
end
|
|
4369
|
+
end
|
|
3247
4370
|
|
|
3248
|
-
|
|
3249
|
-
expect(depeche_mode.reload.likes).to eq(100)
|
|
3250
|
-
end
|
|
4371
|
+
describe "#fifth!" do
|
|
3251
4372
|
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
4373
|
+
let!(:depeche_mode) do
|
|
4374
|
+
Band.create!(name: "Depeche Mode")
|
|
4375
|
+
end
|
|
3255
4376
|
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
end
|
|
3259
|
-
end
|
|
4377
|
+
let!(:new_order) do
|
|
4378
|
+
Band.create!(name: "New Order")
|
|
3260
4379
|
end
|
|
3261
4380
|
|
|
3262
|
-
|
|
4381
|
+
let!(:rolling_stones) do
|
|
4382
|
+
Band.create!(name: "The Rolling Stones")
|
|
4383
|
+
end
|
|
3263
4384
|
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
end
|
|
4385
|
+
let!(:death_cab) do
|
|
4386
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3267
4387
|
end
|
|
3268
4388
|
|
|
3269
|
-
|
|
3270
|
-
|
|
4389
|
+
let!(:guns_and_roses) do
|
|
4390
|
+
Band.create!(name: "Guns and Roses")
|
|
4391
|
+
end
|
|
3271
4392
|
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
b.labels << Label.new(name: 'Warner')
|
|
3276
|
-
b.labels << Label.new(name: 'Sony')
|
|
3277
|
-
b.labels << Label.new(name: 'Cbs')
|
|
3278
|
-
b.save!
|
|
4393
|
+
let(:context) do
|
|
4394
|
+
described_class.new(criteria)
|
|
4395
|
+
end
|
|
3279
4396
|
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
b.save!
|
|
4397
|
+
context "when there's no sort" do
|
|
4398
|
+
let(:criteria) do
|
|
4399
|
+
Band.all
|
|
3284
4400
|
end
|
|
3285
4401
|
|
|
4402
|
+
it "gets the fifth document" do
|
|
4403
|
+
expect(context.fifth!).to eq(guns_and_roses)
|
|
4404
|
+
end
|
|
4405
|
+
end
|
|
3286
4406
|
|
|
4407
|
+
context "when there's a custom sort" do
|
|
3287
4408
|
let(:criteria) do
|
|
3288
|
-
Band.
|
|
4409
|
+
Band.all
|
|
3289
4410
|
end
|
|
3290
4411
|
|
|
3291
|
-
|
|
3292
|
-
context.
|
|
3293
|
-
array_filters: [{ 'i.name' => 'Cbs' }])
|
|
4412
|
+
it "gets the fifth document" do
|
|
4413
|
+
expect(context.sort(name: 1).fifth!).to eq(rolling_stones)
|
|
3294
4414
|
end
|
|
4415
|
+
end
|
|
3295
4416
|
|
|
3296
|
-
|
|
3297
|
-
|
|
4417
|
+
context "when there are no documents" do
|
|
4418
|
+
let(:criteria) do
|
|
4419
|
+
Band.where(name: "bogus")
|
|
3298
4420
|
end
|
|
3299
4421
|
|
|
3300
|
-
it
|
|
3301
|
-
expect
|
|
4422
|
+
it "raises an error" do
|
|
4423
|
+
expect do
|
|
4424
|
+
context.fifth!
|
|
4425
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3302
4426
|
end
|
|
3303
4427
|
end
|
|
3304
4428
|
end
|
|
3305
4429
|
|
|
3306
|
-
describe "#
|
|
4430
|
+
describe "#second_to_last" do
|
|
3307
4431
|
|
|
3308
4432
|
let!(:depeche_mode) do
|
|
3309
|
-
Band.create!(name: "Depeche Mode"
|
|
4433
|
+
Band.create!(name: "Depeche Mode")
|
|
3310
4434
|
end
|
|
3311
4435
|
|
|
3312
4436
|
let!(:new_order) do
|
|
3313
4437
|
Band.create!(name: "New Order")
|
|
3314
4438
|
end
|
|
3315
4439
|
|
|
3316
|
-
let(:
|
|
3317
|
-
Band.
|
|
4440
|
+
let!(:rolling_stones) do
|
|
4441
|
+
Band.create!(name: "The Rolling Stones")
|
|
4442
|
+
end
|
|
4443
|
+
|
|
4444
|
+
let!(:death_cab) do
|
|
4445
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
3318
4446
|
end
|
|
3319
4447
|
|
|
3320
4448
|
let(:context) do
|
|
3321
4449
|
described_class.new(criteria)
|
|
3322
4450
|
end
|
|
3323
4451
|
|
|
3324
|
-
context "when
|
|
4452
|
+
context "when there's no sort" do
|
|
4453
|
+
let(:criteria) do
|
|
4454
|
+
Band.all
|
|
4455
|
+
end
|
|
3325
4456
|
|
|
3326
|
-
|
|
4457
|
+
it "gets the second_to_last document" do
|
|
4458
|
+
expect(context.second_to_last).to eq(rolling_stones)
|
|
4459
|
+
end
|
|
4460
|
+
end
|
|
3327
4461
|
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
4462
|
+
context "when there's a custom sort" do
|
|
4463
|
+
let(:criteria) do
|
|
4464
|
+
Band.all
|
|
4465
|
+
end
|
|
3331
4466
|
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
4467
|
+
it "gets the second_to_last document" do
|
|
4468
|
+
expect(context.sort(name: 1).second_to_last).to eq(new_order)
|
|
4469
|
+
end
|
|
4470
|
+
end
|
|
3335
4471
|
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
4472
|
+
context "when there are no documents" do
|
|
4473
|
+
let(:criteria) do
|
|
4474
|
+
Band.where(name: "bogus")
|
|
4475
|
+
end
|
|
3339
4476
|
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
end
|
|
4477
|
+
it "returns nil" do
|
|
4478
|
+
expect(context.second_to_last).to be_nil
|
|
3343
4479
|
end
|
|
4480
|
+
end
|
|
4481
|
+
end
|
|
3344
4482
|
|
|
3345
|
-
|
|
4483
|
+
describe "#second_to_last!" do
|
|
3346
4484
|
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
4485
|
+
let!(:depeche_mode) do
|
|
4486
|
+
Band.create!(name: "Depeche Mode")
|
|
4487
|
+
end
|
|
3350
4488
|
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
4489
|
+
let!(:new_order) do
|
|
4490
|
+
Band.create!(name: "New Order")
|
|
4491
|
+
end
|
|
3354
4492
|
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
end
|
|
4493
|
+
let!(:rolling_stones) do
|
|
4494
|
+
Band.create!(name: "The Rolling Stones")
|
|
4495
|
+
end
|
|
3359
4496
|
|
|
3360
|
-
|
|
4497
|
+
let!(:death_cab) do
|
|
4498
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4499
|
+
end
|
|
3361
4500
|
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
4501
|
+
let(:context) do
|
|
4502
|
+
described_class.new(criteria)
|
|
4503
|
+
end
|
|
3365
4504
|
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
4505
|
+
context "when there's no sort" do
|
|
4506
|
+
let(:criteria) do
|
|
4507
|
+
Band.all
|
|
4508
|
+
end
|
|
3369
4509
|
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
end
|
|
4510
|
+
it "gets the second_to_last document" do
|
|
4511
|
+
expect(context.second_to_last!).to eq(rolling_stones)
|
|
3373
4512
|
end
|
|
3374
4513
|
end
|
|
3375
4514
|
|
|
3376
|
-
context "when
|
|
4515
|
+
context "when there's a custom sort" do
|
|
4516
|
+
let(:criteria) do
|
|
4517
|
+
Band.all
|
|
4518
|
+
end
|
|
3377
4519
|
|
|
3378
|
-
|
|
4520
|
+
it "gets the second_to_last document" do
|
|
4521
|
+
expect(context.sort(name: 1).second_to_last!).to eq(new_order)
|
|
4522
|
+
end
|
|
4523
|
+
end
|
|
3379
4524
|
|
|
3380
|
-
|
|
4525
|
+
context "when there are no documents" do
|
|
4526
|
+
let(:criteria) do
|
|
4527
|
+
Band.where(name: "bogus")
|
|
4528
|
+
end
|
|
3381
4529
|
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
4530
|
+
it "raises an error" do
|
|
4531
|
+
expect do
|
|
4532
|
+
context.second_to_last!
|
|
4533
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
4534
|
+
end
|
|
4535
|
+
end
|
|
4536
|
+
end
|
|
3385
4537
|
|
|
3386
|
-
|
|
3387
|
-
expect(depeche_mode.reload.name).to eq("Smiths")
|
|
3388
|
-
end
|
|
4538
|
+
describe "#third_to_last" do
|
|
3389
4539
|
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
end
|
|
4540
|
+
let!(:depeche_mode) do
|
|
4541
|
+
Band.create!(name: "Depeche Mode")
|
|
4542
|
+
end
|
|
3394
4543
|
|
|
3395
|
-
|
|
4544
|
+
let!(:new_order) do
|
|
4545
|
+
Band.create!(name: "New Order")
|
|
4546
|
+
end
|
|
3396
4547
|
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
4548
|
+
let!(:rolling_stones) do
|
|
4549
|
+
Band.create!(name: "The Rolling Stones")
|
|
4550
|
+
end
|
|
3400
4551
|
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
4552
|
+
let!(:death_cab) do
|
|
4553
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4554
|
+
end
|
|
3404
4555
|
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
end
|
|
3409
|
-
end
|
|
4556
|
+
let(:context) do
|
|
4557
|
+
described_class.new(criteria)
|
|
4558
|
+
end
|
|
3410
4559
|
|
|
3411
|
-
|
|
4560
|
+
context "when there's no sort" do
|
|
4561
|
+
let(:criteria) do
|
|
4562
|
+
Band.all
|
|
4563
|
+
end
|
|
3412
4564
|
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
4565
|
+
it "gets the third_to_last document" do
|
|
4566
|
+
expect(context.third_to_last).to eq(new_order)
|
|
4567
|
+
end
|
|
4568
|
+
end
|
|
3416
4569
|
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
4570
|
+
context "when there's a custom sort" do
|
|
4571
|
+
let(:criteria) do
|
|
4572
|
+
Band.all
|
|
4573
|
+
end
|
|
3420
4574
|
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
4575
|
+
it "gets the third_to_last document" do
|
|
4576
|
+
expect(context.sort(name: 1).third_to_last).to eq(depeche_mode)
|
|
4577
|
+
end
|
|
4578
|
+
end
|
|
3424
4579
|
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
4580
|
+
context "when there are no documents" do
|
|
4581
|
+
let(:criteria) do
|
|
4582
|
+
Band.where(name: "bogus")
|
|
4583
|
+
end
|
|
3428
4584
|
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
end
|
|
4585
|
+
it "returns nil" do
|
|
4586
|
+
expect(context.third_to_last).to be_nil
|
|
3432
4587
|
end
|
|
3433
4588
|
end
|
|
4589
|
+
end
|
|
3434
4590
|
|
|
3435
|
-
|
|
4591
|
+
describe "#third_to_last!" do
|
|
3436
4592
|
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
end
|
|
4593
|
+
let!(:depeche_mode) do
|
|
4594
|
+
Band.create!(name: "Depeche Mode")
|
|
3440
4595
|
end
|
|
3441
4596
|
|
|
3442
|
-
|
|
3443
|
-
|
|
4597
|
+
let!(:new_order) do
|
|
4598
|
+
Band.create!(name: "New Order")
|
|
4599
|
+
end
|
|
3444
4600
|
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
b.labels << Label.new(name: 'Warner')
|
|
3449
|
-
b.labels << Label.new(name: 'Sony')
|
|
3450
|
-
b.labels << Label.new(name: 'Cbs')
|
|
3451
|
-
b.save!
|
|
4601
|
+
let!(:rolling_stones) do
|
|
4602
|
+
Band.create!(name: "The Rolling Stones")
|
|
4603
|
+
end
|
|
3452
4604
|
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
4605
|
+
let!(:death_cab) do
|
|
4606
|
+
Band.create!(name: "Death Cab For Cutie")
|
|
4607
|
+
end
|
|
4608
|
+
|
|
4609
|
+
let(:context) do
|
|
4610
|
+
described_class.new(criteria)
|
|
4611
|
+
end
|
|
4612
|
+
|
|
4613
|
+
context "when there's no sort" do
|
|
4614
|
+
let(:criteria) do
|
|
4615
|
+
Band.all
|
|
3457
4616
|
end
|
|
3458
4617
|
|
|
4618
|
+
it "gets the third_to_last document" do
|
|
4619
|
+
expect(context.third_to_last!).to eq(new_order)
|
|
4620
|
+
end
|
|
4621
|
+
end
|
|
3459
4622
|
|
|
4623
|
+
context "when there's a custom sort" do
|
|
3460
4624
|
let(:criteria) do
|
|
3461
4625
|
Band.all
|
|
3462
4626
|
end
|
|
3463
4627
|
|
|
3464
|
-
|
|
3465
|
-
context.
|
|
3466
|
-
array_filters: [{ 'i.name' => 'Cbs' }])
|
|
4628
|
+
it "gets the third_to_last document" do
|
|
4629
|
+
expect(context.sort(name: 1).third_to_last!).to eq(depeche_mode)
|
|
3467
4630
|
end
|
|
4631
|
+
end
|
|
3468
4632
|
|
|
3469
|
-
|
|
3470
|
-
|
|
4633
|
+
context "when there are no documents" do
|
|
4634
|
+
let(:criteria) do
|
|
4635
|
+
Band.where(name: "bogus")
|
|
3471
4636
|
end
|
|
3472
4637
|
|
|
3473
|
-
it
|
|
3474
|
-
expect
|
|
4638
|
+
it "raises an error" do
|
|
4639
|
+
expect do
|
|
4640
|
+
context.third_to_last!
|
|
4641
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
|
3475
4642
|
end
|
|
3476
4643
|
end
|
|
3477
4644
|
end
|
|
3478
4645
|
|
|
3479
|
-
describe '#
|
|
4646
|
+
describe '#load_async' do
|
|
4647
|
+
let!(:band) do
|
|
4648
|
+
Band.create!(name: "Depeche Mode")
|
|
4649
|
+
end
|
|
3480
4650
|
|
|
3481
|
-
|
|
4651
|
+
let(:criteria) do
|
|
4652
|
+
Band.where(name: "Depeche Mode")
|
|
4653
|
+
end
|
|
3482
4654
|
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
end
|
|
4655
|
+
let(:context) do
|
|
4656
|
+
described_class.new(criteria)
|
|
4657
|
+
end
|
|
3487
4658
|
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
end
|
|
4659
|
+
context 'with global thread pool async query executor' do
|
|
4660
|
+
config_override :async_query_executor, :global_thread_pool
|
|
3491
4661
|
|
|
3492
|
-
|
|
3493
|
-
|
|
4662
|
+
it 'preloads the documents' do
|
|
4663
|
+
context.load_async
|
|
4664
|
+
context.documents_loader.wait
|
|
4665
|
+
|
|
4666
|
+
expect(context.view).not_to receive(:map)
|
|
4667
|
+
expect(context.to_a).to eq([band])
|
|
3494
4668
|
end
|
|
3495
4669
|
|
|
3496
|
-
|
|
3497
|
-
|
|
4670
|
+
it 're-raises exception during preload' do
|
|
4671
|
+
expect_any_instance_of(Mongoid::Contextual::Mongo::DocumentsLoader)
|
|
4672
|
+
.to receive(:execute)
|
|
4673
|
+
.at_least(:once)
|
|
4674
|
+
.and_raise(Mongo::Error::OperationFailure)
|
|
4675
|
+
|
|
4676
|
+
context.load_async
|
|
4677
|
+
context.documents_loader.wait
|
|
4678
|
+
|
|
4679
|
+
expect do
|
|
4680
|
+
context.to_a
|
|
4681
|
+
end.to raise_error(Mongo::Error::OperationFailure)
|
|
3498
4682
|
end
|
|
4683
|
+
end
|
|
3499
4684
|
|
|
3500
|
-
|
|
3501
|
-
|
|
4685
|
+
context 'with immediate thread pool async query executor' do
|
|
4686
|
+
config_override :async_query_executor, :immediate
|
|
4687
|
+
|
|
4688
|
+
it 'preloads the documents' do
|
|
4689
|
+
context.load_async
|
|
4690
|
+
context.documents_loader.wait
|
|
4691
|
+
|
|
4692
|
+
expect(context.view).not_to receive(:map)
|
|
4693
|
+
expect(context.to_a).to eq([band])
|
|
3502
4694
|
end
|
|
3503
4695
|
|
|
3504
|
-
it '
|
|
3505
|
-
|
|
4696
|
+
it 're-raises exception during preload' do
|
|
4697
|
+
expect_any_instance_of(Mongoid::Contextual::Mongo::DocumentsLoader)
|
|
4698
|
+
.to receive(:execute)
|
|
4699
|
+
.at_least(:once)
|
|
4700
|
+
.and_raise(Mongo::Error::OperationFailure)
|
|
4701
|
+
|
|
4702
|
+
context.load_async
|
|
4703
|
+
context.documents_loader.wait
|
|
4704
|
+
|
|
4705
|
+
expect do
|
|
4706
|
+
context.to_a
|
|
4707
|
+
end.to raise_error(Mongo::Error::OperationFailure)
|
|
3506
4708
|
end
|
|
3507
4709
|
end
|
|
3508
4710
|
end
|