mongoid 7.0.12 → 7.3.3
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 +13 -13
- data/README.md +32 -19
- data/Rakefile +49 -0
- data/lib/config/locales/en.yml +113 -55
- data/lib/mongoid/association/accessors.rb +143 -53
- data/lib/mongoid/association/bindable.rb +7 -5
- data/lib/mongoid/association/builders.rb +4 -3
- data/lib/mongoid/association/constrainable.rb +5 -3
- data/lib/mongoid/association/depending.rb +10 -12
- data/lib/mongoid/association/eager_loadable.rb +2 -0
- data/lib/mongoid/association/embedded/batchable.rb +5 -3
- data/lib/mongoid/association/embedded/cyclic.rb +8 -6
- data/lib/mongoid/association/embedded/embedded_in/binding.rb +4 -1
- data/lib/mongoid/association/embedded/embedded_in/buildable.rb +8 -2
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +15 -12
- data/lib/mongoid/association/embedded/embedded_in.rb +7 -4
- data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -2
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +9 -3
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +60 -50
- data/lib/mongoid/association/embedded/embeds_many.rb +7 -4
- data/lib/mongoid/association/embedded/embeds_one/binding.rb +5 -2
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +10 -4
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +17 -14
- data/lib/mongoid/association/embedded/embeds_one.rb +7 -4
- data/lib/mongoid/association/embedded.rb +3 -0
- data/lib/mongoid/association/macros.rb +38 -36
- data/lib/mongoid/association/many.rb +16 -13
- data/lib/mongoid/association/marshalable.rb +3 -1
- data/lib/mongoid/association/nested/many.rb +18 -16
- data/lib/mongoid/association/nested/nested_buildable.rb +6 -3
- data/lib/mongoid/association/nested/one.rb +15 -11
- data/lib/mongoid/association/nested.rb +4 -1
- data/lib/mongoid/association/one.rb +3 -1
- data/lib/mongoid/association/options.rb +9 -6
- data/lib/mongoid/association/proxy.rb +37 -15
- data/lib/mongoid/association/referenced/auto_save.rb +6 -3
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +4 -2
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +7 -4
- data/lib/mongoid/association/referenced/belongs_to/eager.rb +40 -2
- data/lib/mongoid/association/referenced/belongs_to/proxy.rb +16 -14
- data/lib/mongoid/association/referenced/belongs_to.rb +6 -3
- data/lib/mongoid/association/referenced/counter_cache.rb +2 -0
- data/lib/mongoid/association/referenced/eager.rb +37 -15
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +12 -6
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +5 -2
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +2 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +26 -19
- data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +13 -6
- data/lib/mongoid/association/referenced/has_many/binding.rb +3 -1
- data/lib/mongoid/association/referenced/has_many/buildable.rb +5 -2
- data/lib/mongoid/association/referenced/has_many/eager.rb +2 -0
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -457
- data/lib/mongoid/association/referenced/has_many/proxy.rb +57 -47
- data/lib/mongoid/association/referenced/has_many.rb +7 -4
- data/lib/mongoid/association/referenced/has_one/binding.rb +4 -2
- data/lib/mongoid/association/referenced/has_one/buildable.rb +17 -2
- data/lib/mongoid/association/referenced/has_one/eager.rb +2 -0
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +13 -11
- data/lib/mongoid/association/referenced/has_one/proxy.rb +23 -16
- data/lib/mongoid/association/referenced/has_one.rb +5 -2
- data/lib/mongoid/association/referenced/syncable.rb +7 -5
- data/lib/mongoid/association/referenced.rb +3 -0
- data/lib/mongoid/association/reflections.rb +7 -5
- data/lib/mongoid/association/relatable.rb +19 -14
- data/lib/mongoid/association.rb +9 -6
- data/lib/mongoid/atomic/modifiers.rb +25 -2
- data/lib/mongoid/atomic/paths/embedded/many.rb +4 -2
- data/lib/mongoid/atomic/paths/embedded/one.rb +4 -2
- data/lib/mongoid/atomic/paths/embedded.rb +2 -0
- data/lib/mongoid/atomic/paths/root.rb +4 -2
- data/lib/mongoid/atomic/paths.rb +2 -0
- data/lib/mongoid/atomic.rb +28 -2
- data/lib/mongoid/attributes/dynamic.rb +3 -1
- data/lib/mongoid/attributes/nested.rb +7 -5
- data/lib/mongoid/attributes/processing.rb +8 -6
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/attributes/readonly.rb +3 -1
- data/lib/mongoid/attributes.rb +46 -27
- data/lib/mongoid/cacheable.rb +5 -3
- data/lib/mongoid/changeable.rb +3 -1
- data/lib/mongoid/clients/factory.rb +42 -10
- data/lib/mongoid/clients/options.rb +10 -8
- data/lib/mongoid/clients/sessions.rb +3 -0
- data/lib/mongoid/clients/storage_options.rb +7 -5
- data/lib/mongoid/clients/validators/storage.rb +2 -0
- data/lib/mongoid/clients/validators.rb +2 -0
- data/lib/mongoid/clients.rb +3 -1
- data/lib/mongoid/composable.rb +5 -2
- data/lib/mongoid/config/environment.rb +11 -1
- data/lib/mongoid/config/options.rb +20 -12
- data/lib/mongoid/config/validators/client.rb +2 -0
- data/lib/mongoid/config/validators/option.rb +2 -0
- data/lib/mongoid/config/validators.rb +2 -0
- data/lib/mongoid/config.rb +75 -12
- data/lib/mongoid/contextual/aggregable/memory.rb +3 -1
- data/lib/mongoid/contextual/aggregable/mongo.rb +13 -9
- data/lib/mongoid/contextual/atomic.rb +31 -8
- data/lib/mongoid/contextual/command.rb +2 -0
- data/lib/mongoid/contextual/geo_near.rb +5 -3
- data/lib/mongoid/contextual/map_reduce.rb +5 -2
- data/lib/mongoid/contextual/memory.rb +4 -2
- data/lib/mongoid/contextual/mongo.rb +29 -5
- data/lib/mongoid/contextual/none.rb +5 -0
- data/lib/mongoid/contextual/queryable.rb +2 -0
- data/lib/mongoid/contextual.rb +7 -4
- data/lib/mongoid/copyable.rb +11 -5
- data/lib/mongoid/criteria/findable.rb +12 -2
- data/lib/mongoid/criteria/includable.rb +8 -6
- data/lib/mongoid/criteria/inspectable.rb +2 -0
- data/lib/mongoid/criteria/marshalable.rb +2 -0
- data/lib/mongoid/criteria/modifiable.rb +2 -0
- data/lib/mongoid/criteria/options.rb +2 -0
- data/lib/mongoid/criteria/permission.rb +2 -0
- data/lib/mongoid/criteria/queryable/aggregable.rb +2 -0
- data/lib/mongoid/criteria/queryable/expandable.rb +69 -0
- data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/date.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +5 -6
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/object.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/range.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -4
- data/lib/mongoid/criteria/queryable/extensions/set.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/string.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/time.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +3 -1
- data/lib/mongoid/criteria/queryable/extensions.rb +1 -3
- data/lib/mongoid/criteria/queryable/key.rb +35 -7
- data/lib/mongoid/criteria/queryable/macroable.rb +3 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +179 -11
- data/lib/mongoid/criteria/queryable/optional.rb +5 -3
- data/lib/mongoid/criteria/queryable/options.rb +2 -0
- data/lib/mongoid/criteria/queryable/pipeline.rb +5 -2
- data/lib/mongoid/criteria/queryable/selectable.rb +397 -98
- data/lib/mongoid/criteria/queryable/selector.rb +37 -8
- data/lib/mongoid/criteria/queryable/smash.rb +2 -0
- data/lib/mongoid/criteria/queryable/storable.rb +233 -0
- data/lib/mongoid/criteria/queryable.rb +7 -2
- data/lib/mongoid/criteria/scopable.rb +2 -0
- data/lib/mongoid/criteria.rb +79 -15
- data/lib/mongoid/document.rb +21 -20
- data/lib/mongoid/equality.rb +3 -2
- data/lib/mongoid/errors/ambiguous_relationship.rb +4 -2
- data/lib/mongoid/errors/callback.rb +2 -0
- data/lib/mongoid/errors/criteria_argument_required.rb +19 -0
- data/lib/mongoid/errors/delete_restriction.rb +10 -10
- data/lib/mongoid/errors/document_not_destroyed.rb +2 -0
- data/lib/mongoid/errors/document_not_found.rb +2 -0
- data/lib/mongoid/errors/eager_load.rb +6 -2
- data/lib/mongoid/errors/empty_config_file.rb +26 -0
- data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -0
- data/lib/mongoid/errors/invalid_collection.rb +2 -0
- data/lib/mongoid/errors/invalid_config_file.rb +26 -0
- data/lib/mongoid/errors/invalid_config_option.rb +2 -0
- data/lib/mongoid/errors/invalid_dependent_strategy.rb +2 -0
- data/lib/mongoid/errors/invalid_discriminator_key_target.rb +25 -0
- data/lib/mongoid/errors/invalid_elem_match_operator.rb +33 -0
- data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +26 -0
- data/lib/mongoid/errors/invalid_expression_operator.rb +28 -0
- data/lib/mongoid/errors/invalid_field.rb +2 -0
- data/lib/mongoid/errors/invalid_field_operator.rb +33 -0
- data/lib/mongoid/errors/invalid_field_option.rb +2 -0
- data/lib/mongoid/errors/invalid_find.rb +2 -0
- data/lib/mongoid/errors/invalid_includes.rb +2 -0
- data/lib/mongoid/errors/invalid_index.rb +2 -0
- data/lib/mongoid/errors/invalid_options.rb +4 -2
- data/lib/mongoid/errors/invalid_path.rb +2 -0
- data/lib/mongoid/errors/invalid_persistence_option.rb +2 -0
- data/lib/mongoid/errors/invalid_query.rb +41 -0
- data/lib/mongoid/errors/invalid_relation.rb +4 -2
- data/lib/mongoid/errors/invalid_relation_option.rb +4 -2
- data/lib/mongoid/errors/invalid_scope.rb +2 -0
- data/lib/mongoid/errors/invalid_session_use.rb +2 -0
- data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -4
- data/lib/mongoid/errors/invalid_storage_options.rb +2 -0
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
- data/lib/mongoid/errors/invalid_time.rb +2 -0
- data/lib/mongoid/errors/invalid_value.rb +2 -0
- data/lib/mongoid/errors/inverse_not_found.rb +3 -1
- data/lib/mongoid/errors/mixed_client_configuration.rb +2 -0
- data/lib/mongoid/errors/mixed_relations.rb +2 -0
- data/lib/mongoid/errors/mongoid_error.rb +3 -1
- data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -1
- data/lib/mongoid/errors/no_client_config.rb +4 -2
- data/lib/mongoid/errors/no_client_database.rb +2 -0
- data/lib/mongoid/errors/no_client_hosts.rb +2 -0
- data/lib/mongoid/errors/no_clients_config.rb +2 -0
- data/lib/mongoid/errors/no_default_client.rb +3 -1
- data/lib/mongoid/errors/no_environment.rb +2 -0
- data/lib/mongoid/errors/no_map_reduce_output.rb +2 -0
- data/lib/mongoid/errors/no_metadata.rb +2 -0
- data/lib/mongoid/errors/no_parent.rb +2 -0
- data/lib/mongoid/errors/readonly_attribute.rb +2 -0
- data/lib/mongoid/errors/readonly_document.rb +2 -0
- data/lib/mongoid/errors/scope_overwrite.rb +2 -0
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -0
- data/lib/mongoid/errors/unknown_attribute.rb +2 -0
- data/lib/mongoid/errors/unknown_model.rb +2 -0
- data/lib/mongoid/errors/unsaved_document.rb +2 -0
- data/lib/mongoid/errors/unsupported_javascript.rb +2 -0
- data/lib/mongoid/errors/validations.rb +2 -0
- data/lib/mongoid/errors.rb +12 -0
- data/lib/mongoid/evolvable.rb +4 -2
- data/lib/mongoid/extensions/array.rb +23 -6
- data/lib/mongoid/extensions/big_decimal.rb +2 -0
- data/lib/mongoid/extensions/boolean.rb +3 -2
- data/lib/mongoid/extensions/date.rb +13 -3
- data/lib/mongoid/extensions/date_time.rb +4 -3
- data/lib/mongoid/extensions/decimal128.rb +2 -0
- data/lib/mongoid/extensions/false_class.rb +3 -1
- data/lib/mongoid/extensions/float.rb +5 -3
- data/lib/mongoid/extensions/hash.rb +49 -9
- data/lib/mongoid/extensions/integer.rb +5 -3
- data/lib/mongoid/extensions/module.rb +2 -0
- data/lib/mongoid/extensions/nil_class.rb +2 -0
- data/lib/mongoid/extensions/object.rb +16 -4
- data/lib/mongoid/extensions/object_id.rb +2 -0
- data/lib/mongoid/extensions/range.rb +2 -0
- data/lib/mongoid/extensions/regexp.rb +2 -0
- data/lib/mongoid/extensions/set.rb +2 -0
- data/lib/mongoid/extensions/string.rb +18 -9
- data/lib/mongoid/extensions/symbol.rb +2 -0
- data/lib/mongoid/extensions/time.rb +14 -0
- data/lib/mongoid/extensions/time_with_zone.rb +14 -0
- data/lib/mongoid/extensions/true_class.rb +3 -1
- data/lib/mongoid/extensions.rb +3 -0
- data/lib/mongoid/factory.rb +52 -12
- data/lib/mongoid/fields/foreign_key.rb +3 -1
- data/lib/mongoid/fields/localized.rb +2 -0
- data/lib/mongoid/fields/standard.rb +6 -3
- data/lib/mongoid/fields/validators/macro.rb +38 -11
- data/lib/mongoid/fields/validators.rb +2 -0
- data/lib/mongoid/fields.rb +49 -6
- data/lib/mongoid/findable.rb +59 -18
- data/lib/mongoid/indexable/specification.rb +3 -1
- data/lib/mongoid/indexable/validators/options.rb +2 -0
- data/lib/mongoid/indexable.rb +5 -3
- data/lib/mongoid/inspectable.rb +4 -2
- data/lib/mongoid/interceptable.rb +10 -4
- data/lib/mongoid/loggable.rb +13 -7
- data/lib/mongoid/matchable.rb +2 -148
- data/lib/mongoid/matcher/all.rb +22 -0
- data/lib/mongoid/matcher/and.rb +21 -0
- data/lib/mongoid/matcher/bits.rb +41 -0
- data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_all_set.rb +20 -0
- data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_any_set.rb +20 -0
- data/lib/mongoid/matcher/elem_match.rb +36 -0
- data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
- data/lib/mongoid/matcher/eq.rb +11 -0
- data/lib/mongoid/matcher/eq_impl.rb +32 -0
- data/lib/mongoid/matcher/eq_impl_with_regexp.rb +21 -0
- data/lib/mongoid/matcher/exists.rb +15 -0
- data/lib/mongoid/matcher/expression.rb +35 -0
- data/lib/mongoid/matcher/expression_operator.rb +19 -0
- data/lib/mongoid/matcher/field_expression.rb +62 -0
- data/lib/mongoid/matcher/field_operator.rb +54 -0
- data/lib/mongoid/matcher/gt.rb +17 -0
- data/lib/mongoid/matcher/gte.rb +17 -0
- data/lib/mongoid/matcher/in.rb +25 -0
- data/lib/mongoid/matcher/lt.rb +17 -0
- data/lib/mongoid/matcher/lte.rb +17 -0
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/ne.rb +16 -0
- data/lib/mongoid/matcher/nin.rb +11 -0
- data/lib/mongoid/matcher/nor.rb +25 -0
- data/lib/mongoid/matcher/not.rb +29 -0
- data/lib/mongoid/matcher/or.rb +21 -0
- data/lib/mongoid/matcher/regex.rb +41 -0
- data/lib/mongoid/matcher/size.rb +26 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/matcher.rb +110 -0
- data/lib/mongoid/persistable/creatable.rb +3 -1
- data/lib/mongoid/persistable/deletable.rb +5 -4
- data/lib/mongoid/persistable/destroyable.rb +11 -3
- data/lib/mongoid/persistable/incrementable.rb +6 -2
- data/lib/mongoid/persistable/logical.rb +4 -1
- data/lib/mongoid/persistable/poppable.rb +3 -1
- data/lib/mongoid/persistable/pullable.rb +3 -1
- data/lib/mongoid/persistable/pushable.rb +3 -1
- data/lib/mongoid/persistable/renamable.rb +10 -3
- data/lib/mongoid/persistable/savable.rb +3 -1
- data/lib/mongoid/persistable/settable.rb +3 -1
- data/lib/mongoid/persistable/unsettable.rb +8 -3
- data/lib/mongoid/persistable/updatable.rb +30 -3
- data/lib/mongoid/persistable/upsertable.rb +3 -1
- data/lib/mongoid/persistable.rb +133 -15
- data/lib/mongoid/persistence_context.rb +24 -10
- data/lib/mongoid/positional.rb +2 -0
- data/lib/mongoid/query_cache.rb +118 -100
- data/lib/mongoid/railtie.rb +3 -1
- data/lib/mongoid/railties/controller_runtime.rb +4 -1
- data/lib/mongoid/railties/database.rake +9 -0
- data/lib/mongoid/reloadable.rb +11 -4
- data/lib/mongoid/scopable.rb +2 -1
- data/lib/mongoid/selectable.rb +8 -8
- data/lib/mongoid/serializable.rb +24 -14
- data/lib/mongoid/shardable.rb +80 -10
- data/lib/mongoid/stateful.rb +3 -1
- data/lib/mongoid/stringified_symbol.rb +53 -0
- data/lib/mongoid/tasks/database.rake +12 -5
- data/lib/mongoid/tasks/database.rb +85 -0
- data/lib/mongoid/threaded/lifecycle.rb +2 -0
- data/lib/mongoid/threaded.rb +2 -0
- data/lib/mongoid/timestamps/created/short.rb +2 -0
- data/lib/mongoid/timestamps/created.rb +3 -1
- data/lib/mongoid/timestamps/short.rb +2 -0
- data/lib/mongoid/timestamps/timeless.rb +6 -2
- data/lib/mongoid/timestamps/updated/short.rb +2 -0
- data/lib/mongoid/timestamps/updated.rb +3 -1
- data/lib/mongoid/timestamps.rb +3 -1
- data/lib/mongoid/touchable.rb +53 -16
- data/lib/mongoid/traversable.rb +115 -6
- data/lib/mongoid/validatable/associated.rb +5 -3
- data/lib/mongoid/validatable/format.rb +2 -0
- data/lib/mongoid/validatable/length.rb +2 -0
- data/lib/mongoid/validatable/localizable.rb +2 -0
- data/lib/mongoid/validatable/macros.rb +2 -0
- data/lib/mongoid/validatable/presence.rb +7 -5
- data/lib/mongoid/validatable/queryable.rb +2 -0
- data/lib/mongoid/validatable/uniqueness.rb +5 -3
- data/lib/mongoid/validatable.rb +7 -5
- data/lib/mongoid/version.rb +2 -1
- data/lib/mongoid.rb +34 -2
- data/lib/rails/generators/mongoid/config/config_generator.rb +10 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +45 -30
- data/lib/rails/generators/mongoid/model/model_generator.rb +3 -1
- data/lib/rails/generators/mongoid_generator.rb +2 -0
- data/lib/rails/mongoid.rb +4 -2
- data/lib/support/ruby_version.rb +3 -0
- data/spec/README.md +19 -4
- data/spec/config/mongoid.yml +1 -0
- data/spec/integration/app_spec.rb +246 -94
- data/spec/integration/associations/belongs_to_spec.rb +3 -0
- data/spec/integration/associations/embedded_spec.rb +207 -0
- data/spec/integration/associations/embeds_many_spec.rb +68 -0
- data/spec/integration/associations/embeds_one_spec.rb +24 -0
- data/spec/integration/associations/foreign_key_spec.rb +99 -0
- data/spec/integration/associations/foreign_key_spec_models.rb +65 -0
- data/spec/integration/associations/has_many_spec.rb +129 -0
- data/spec/integration/associations/has_one_spec.rb +177 -0
- data/spec/integration/associations/nested_attributes_assignment_spec.rb +116 -0
- data/spec/integration/associations/reverse_population_spec.rb +35 -0
- data/spec/integration/associations/reverse_population_spec_models.rb +37 -0
- data/spec/integration/atomic/modifiers_spec.rb +117 -0
- data/spec/integration/bson_regexp_raw_spec.rb +20 -0
- data/spec/integration/contextual/empty_spec.rb +142 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/criteria/default_scope_spec.rb +21 -0
- data/spec/integration/criteria/logical_spec.rb +94 -0
- data/spec/integration/discriminator_key_spec.rb +354 -0
- data/spec/integration/discriminator_value_spec.rb +207 -0
- data/spec/integration/document_spec.rb +30 -0
- data/spec/integration/i18n_fallbacks_spec.rb +90 -0
- data/spec/integration/{matchable_spec.rb → matcher_examples_spec.rb} +120 -41
- data/spec/integration/matcher_operator_data/all.yml +140 -0
- data/spec/integration/matcher_operator_data/and.yml +93 -0
- data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
- data/spec/integration/matcher_operator_data/comment.yml +22 -0
- data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
- data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
- data/spec/integration/matcher_operator_data/eq.yml +191 -0
- data/spec/integration/matcher_operator_data/exists.yml +213 -0
- data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
- data/spec/integration/matcher_operator_data/gt.yml +132 -0
- data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
- data/spec/integration/matcher_operator_data/gte.yml +132 -0
- data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/implicit.yml +331 -0
- data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
- data/spec/integration/matcher_operator_data/in.yml +210 -0
- data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
- data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
- data/spec/integration/matcher_operator_data/lt.yml +132 -0
- data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
- data/spec/integration/matcher_operator_data/lte.yml +132 -0
- data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/multiple.yml +29 -0
- data/spec/integration/matcher_operator_data/ne.yml +150 -0
- data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
- data/spec/integration/matcher_operator_data/nin.yml +114 -0
- data/spec/integration/matcher_operator_data/nor.yml +126 -0
- data/spec/integration/matcher_operator_data/not.yml +196 -0
- data/spec/integration/matcher_operator_data/or.yml +137 -0
- data/spec/integration/matcher_operator_data/regex.yml +174 -0
- data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
- data/spec/integration/matcher_operator_data/size.yml +174 -0
- data/spec/integration/matcher_operator_data/type.yml +70 -0
- data/spec/integration/matcher_operator_data/type_array.yml +16 -0
- data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
- data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
- data/spec/integration/matcher_operator_data/type_code.yml +26 -0
- data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
- data/spec/integration/matcher_operator_data/type_date.yml +39 -0
- data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
- data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
- data/spec/integration/matcher_operator_data/type_double.yml +15 -0
- data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
- data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
- data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_null.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
- data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
- data/spec/integration/matcher_operator_data/type_string.yml +15 -0
- data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
- data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
- data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
- data/spec/integration/matcher_operator_spec.rb +100 -0
- data/spec/integration/matcher_spec.rb +189 -0
- data/spec/integration/server_query_spec.rb +142 -0
- data/spec/integration/shardable_spec.rb +149 -0
- data/spec/integration/stringified_symbol_field_spec.rb +190 -0
- data/spec/lite_spec_helper.rb +15 -5
- data/spec/mongoid/association/accessors_spec.rb +241 -63
- data/spec/mongoid/association/auto_save_spec.rb +3 -0
- data/spec/mongoid/association/builders_spec.rb +3 -0
- data/spec/mongoid/association/constrainable_spec.rb +3 -0
- data/spec/mongoid/association/counter_cache_spec.rb +3 -0
- data/spec/mongoid/association/depending_spec.rb +427 -333
- data/spec/mongoid/association/eager_spec.rb +3 -0
- data/spec/mongoid/association/embedded/cyclic_spec.rb +3 -0
- data/spec/mongoid/association/embedded/dirty_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embedded_in_spec.rb +4 -1
- data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +53 -4
- data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +52 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +4 -1
- data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +3 -0
- data/spec/mongoid/association/embedded/embeds_one_models.rb +4 -0
- data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +29 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +4 -1
- data/spec/mongoid/association/macros_spec.rb +3 -0
- data/spec/mongoid/association/nested/many_spec.rb +3 -0
- data/spec/mongoid/association/nested/one_spec.rb +19 -12
- data/spec/mongoid/association/options_spec.rb +3 -0
- data/spec/mongoid/association/polymorphic_spec.rb +3 -0
- data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +3 -0
- data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +3 -0
- data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +205 -10
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +45 -8
- data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +58 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +4 -1
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +16 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +26 -5
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +37 -14
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -2
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +40 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +26 -2
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +4 -1
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_many/eager_spec.rb +18 -3
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +248 -93
- data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +1 -0
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +463 -186
- data/spec/mongoid/association/referenced/has_many_models.rb +41 -0
- data/spec/mongoid/association/referenced/has_many_query_spec.rb +38 -0
- data/spec/mongoid/association/referenced/has_many_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_one/binding_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_one/eager_spec.rb +18 -3
- data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +3 -0
- data/spec/mongoid/association/referenced/has_one_models.rb +32 -0
- data/spec/mongoid/association/referenced/has_one_query_spec.rb +38 -0
- data/spec/mongoid/association/referenced/has_one_spec.rb +4 -1
- data/spec/mongoid/association/reflections_spec.rb +3 -0
- data/spec/mongoid/association/syncable_spec.rb +3 -0
- data/spec/mongoid/association_spec.rb +3 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +50 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +3 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +3 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +3 -0
- data/spec/mongoid/atomic/paths_spec.rb +67 -12
- data/spec/mongoid/atomic_spec.rb +26 -0
- data/spec/mongoid/attributes/nested_spec.rb +4 -1
- data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
- data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
- data/spec/mongoid/attributes/projector_spec.rb +41 -0
- data/spec/mongoid/attributes/readonly_spec.rb +3 -0
- data/spec/mongoid/attributes_spec.rb +336 -0
- data/spec/mongoid/cacheable_spec.rb +3 -0
- data/spec/mongoid/changeable_spec.rb +26 -0
- data/spec/mongoid/clients/factory_spec.rb +137 -28
- data/spec/mongoid/clients/options_spec.rb +42 -23
- data/spec/mongoid/clients/sessions_spec.rb +4 -6
- data/spec/mongoid/clients/transactions_spec.rb +6 -3
- data/spec/mongoid/clients_spec.rb +3 -0
- data/spec/mongoid/composable_spec.rb +3 -0
- data/spec/mongoid/config/environment_spec.rb +89 -8
- data/spec/mongoid/config/options_spec.rb +23 -3
- data/spec/mongoid/config_spec.rb +172 -0
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +3 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +3 -0
- data/spec/mongoid/contextual/atomic_spec.rb +181 -29
- data/spec/mongoid/contextual/geo_near_spec.rb +4 -1
- data/spec/mongoid/contextual/map_reduce_spec.rb +3 -0
- data/spec/mongoid/contextual/memory_spec.rb +3 -0
- data/spec/mongoid/contextual/mongo_spec.rb +77 -18
- data/spec/mongoid/contextual/none_spec.rb +3 -0
- data/spec/mongoid/copyable_spec.rb +200 -18
- data/spec/mongoid/copyable_spec_models.rb +31 -0
- data/spec/mongoid/criteria/findable_spec.rb +58 -0
- data/spec/mongoid/criteria/inspectable_spec.rb +3 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +3 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +8 -4
- data/spec/mongoid/criteria/options_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/expandable_spec.rb +62 -0
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +4 -1
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +36 -17
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +4 -1
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +24 -16
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/key_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +146 -12
- data/spec/mongoid/criteria/queryable/optional_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/options_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/pipeline_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1593 -285
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1048 -2773
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
- data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/smash_spec.rb +3 -0
- data/spec/mongoid/criteria/queryable/storable_spec.rb +190 -0
- data/spec/mongoid/criteria/scopable_spec.rb +3 -0
- data/spec/mongoid/criteria_projection_spec.rb +411 -0
- data/spec/mongoid/criteria_spec.rb +241 -278
- data/spec/mongoid/document_fields_spec.rb +26 -0
- data/spec/mongoid/document_query_spec.rb +90 -0
- data/spec/mongoid/document_spec.rb +113 -16
- data/spec/mongoid/equality_spec.rb +3 -1
- data/spec/mongoid/errors/ambiguous_relationship_spec.rb +6 -3
- data/spec/mongoid/errors/callback_spec.rb +3 -0
- data/spec/mongoid/errors/delete_restriction_spec.rb +5 -2
- data/spec/mongoid/errors/document_not_destroyed_spec.rb +3 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +3 -0
- data/spec/mongoid/errors/eager_load_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_collection_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_config_file_spec.rb +32 -0
- data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_field_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_find_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_includes_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_index_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_options_spec.rb +5 -2
- data/spec/mongoid/errors/invalid_path_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_relation_spec.rb +5 -2
- data/spec/mongoid/errors/invalid_scope_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -0
- data/spec/mongoid/errors/invalid_time_spec.rb +3 -0
- data/spec/mongoid/errors/inverse_not_found_spec.rb +4 -1
- data/spec/mongoid/errors/mixed_client_configuration_spec.rb +3 -0
- data/spec/mongoid/errors/mixed_relations_spec.rb +3 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +23 -8
- data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +6 -3
- data/spec/mongoid/errors/no_client_config_spec.rb +5 -2
- data/spec/mongoid/errors/no_client_database_spec.rb +6 -3
- data/spec/mongoid/errors/no_client_hosts_spec.rb +6 -3
- data/spec/mongoid/errors/no_clients_config_spec.rb +3 -0
- data/spec/mongoid/errors/no_environment_spec.rb +3 -0
- data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -0
- data/spec/mongoid/errors/no_metadata_spec.rb +5 -2
- data/spec/mongoid/errors/no_parent_spec.rb +4 -1
- data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -0
- data/spec/mongoid/errors/readonly_document_spec.rb +3 -0
- data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -0
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -0
- data/spec/mongoid/errors/unknown_attribute_spec.rb +3 -0
- data/spec/mongoid/errors/unsaved_document_spec.rb +4 -1
- data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -0
- data/spec/mongoid/errors/validations_spec.rb +3 -0
- data/spec/mongoid/extensions/array_spec.rb +26 -43
- data/spec/mongoid/extensions/big_decimal_spec.rb +3 -0
- data/spec/mongoid/extensions/binary_spec.rb +3 -0
- data/spec/mongoid/extensions/boolean_spec.rb +3 -0
- data/spec/mongoid/extensions/date_class_mongoize_spec.rb +336 -0
- data/spec/mongoid/extensions/date_spec.rb +9 -160
- data/spec/mongoid/extensions/date_time_spec.rb +18 -60
- data/spec/mongoid/extensions/decimal128_spec.rb +3 -0
- data/spec/mongoid/extensions/false_class_spec.rb +4 -1
- data/spec/mongoid/extensions/float_spec.rb +18 -3
- data/spec/mongoid/extensions/hash_spec.rb +106 -0
- data/spec/mongoid/extensions/integer_spec.rb +15 -2
- data/spec/mongoid/extensions/module_spec.rb +3 -0
- data/spec/mongoid/extensions/nil_class_spec.rb +3 -0
- data/spec/mongoid/extensions/object_id_spec.rb +3 -0
- data/spec/mongoid/extensions/object_spec.rb +14 -24
- data/spec/mongoid/extensions/range_spec.rb +3 -0
- data/spec/mongoid/extensions/regexp_spec.rb +3 -0
- data/spec/mongoid/extensions/set_spec.rb +3 -0
- data/spec/mongoid/extensions/string_spec.rb +59 -25
- data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
- data/spec/mongoid/extensions/symbol_spec.rb +3 -0
- data/spec/mongoid/extensions/time_spec.rb +30 -0
- data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -0
- data/spec/mongoid/extensions/true_class_spec.rb +4 -1
- data/spec/mongoid/extensions_spec.rb +3 -0
- data/spec/mongoid/factory_spec.rb +287 -27
- data/spec/mongoid/fields/foreign_key_spec.rb +3 -0
- data/spec/mongoid/fields/localized_spec.rb +7 -4
- data/spec/mongoid/fields/standard_spec.rb +3 -0
- data/spec/mongoid/fields_spec.rb +93 -6
- data/spec/mongoid/findable_spec.rb +35 -0
- data/spec/mongoid/indexable/specification_spec.rb +3 -0
- data/spec/mongoid/indexable_spec.rb +31 -2
- data/spec/mongoid/inspectable_spec.rb +40 -2
- data/spec/mongoid/interceptable_spec.rb +67 -2
- data/spec/mongoid/interceptable_spec_models.rb +76 -0
- data/spec/mongoid/loggable_spec.rb +3 -0
- data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
- data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
- data/spec/mongoid/matcher/extract_attribute_spec.rb +37 -0
- data/spec/mongoid/persistable/creatable_spec.rb +111 -25
- data/spec/mongoid/persistable/deletable_spec.rb +264 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +194 -3
- data/spec/mongoid/persistable/incrementable_spec.rb +17 -0
- data/spec/mongoid/persistable/logical_spec.rb +17 -0
- data/spec/mongoid/persistable/poppable_spec.rb +17 -0
- data/spec/mongoid/persistable/pullable_spec.rb +31 -0
- data/spec/mongoid/persistable/pushable_spec.rb +31 -0
- data/spec/mongoid/persistable/renamable_spec.rb +17 -0
- data/spec/mongoid/persistable/savable_spec.rb +175 -16
- data/spec/mongoid/persistable/settable_spec.rb +47 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +17 -0
- data/spec/mongoid/persistable/updatable_spec.rb +5 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +4 -1
- data/spec/mongoid/persistable_spec.rb +85 -8
- data/spec/mongoid/persistence_context_spec.rb +3 -0
- data/spec/mongoid/positional_spec.rb +3 -0
- data/spec/mongoid/query_cache_middleware_spec.rb +69 -0
- data/spec/mongoid/query_cache_spec.rb +466 -82
- data/spec/mongoid/relations/proxy_spec.rb +3 -0
- data/spec/mongoid/reloadable_spec.rb +93 -1
- data/spec/mongoid/scopable_spec.rb +3 -0
- data/spec/mongoid/selectable_spec.rb +3 -0
- data/spec/mongoid/serializable_spec.rb +152 -20
- data/spec/mongoid/shardable_models.rb +61 -0
- data/spec/mongoid/shardable_spec.rb +116 -16
- data/spec/mongoid/stateful_spec.rb +3 -0
- data/spec/mongoid/tasks/database_rake_spec.rb +3 -0
- data/spec/mongoid/tasks/database_spec.rb +3 -0
- data/spec/mongoid/threaded_spec.rb +3 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +3 -0
- data/spec/mongoid/timestamps/created_spec.rb +3 -0
- data/spec/mongoid/timestamps/timeless_spec.rb +3 -0
- data/spec/mongoid/timestamps/updated/short_spec.rb +3 -0
- data/spec/mongoid/timestamps/updated_spec.rb +3 -0
- data/spec/mongoid/timestamps_spec.rb +3 -0
- data/spec/mongoid/touchable_spec.rb +171 -19
- data/spec/mongoid/touchable_spec_models.rb +54 -0
- data/spec/mongoid/traversable_spec.rb +1103 -0
- data/spec/mongoid/validatable/associated_spec.rb +3 -0
- data/spec/mongoid/validatable/format_spec.rb +3 -0
- data/spec/mongoid/validatable/length_spec.rb +3 -0
- data/spec/mongoid/validatable/numericality_spec.rb +3 -0
- data/spec/mongoid/validatable/presence_spec.rb +3 -0
- data/spec/mongoid/validatable/uniqueness_spec.rb +3 -0
- data/spec/mongoid/validatable_spec.rb +4 -1
- data/spec/mongoid_spec.rb +3 -0
- data/spec/rails/controller_extension/controller_runtime_spec.rb +4 -1
- data/spec/rails/mongoid_spec.rb +5 -2
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/cluster_config.rb +19 -4
- data/spec/shared/lib/mrss/constraints.rb +67 -12
- data/spec/shared/lib/mrss/docker_runner.rb +10 -1
- data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +84 -33
- data/spec/shared/lib/mrss/spec_organizer.rb +32 -2
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +126 -32
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/server.sh +123 -26
- data/spec/shared/shlib/set_env.sh +4 -1
- data/spec/spec_helper.rb +31 -17
- data/spec/support/authorization.rb +3 -0
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/constraints.rb +15 -233
- data/spec/support/expectations.rb +6 -1
- data/spec/support/helpers.rb +11 -0
- data/spec/support/macros.rb +1 -0
- data/spec/{app → support}/models/account.rb +3 -0
- data/spec/{app → support}/models/acolyte.rb +3 -0
- data/spec/{app → support}/models/actor.rb +4 -1
- data/spec/support/models/actress.rb +5 -0
- data/spec/{app → support}/models/address.rb +7 -0
- data/spec/{app → support}/models/address_component.rb +3 -0
- data/spec/{app → support}/models/address_number.rb +3 -0
- data/spec/{app → support}/models/agency.rb +3 -0
- data/spec/{app → support}/models/agent.rb +3 -0
- data/spec/{app → support}/models/album.rb +3 -0
- data/spec/{app → support}/models/alert.rb +3 -0
- data/spec/{app → support}/models/animal.rb +3 -0
- data/spec/{app → support}/models/answer.rb +3 -0
- data/spec/{app → support}/models/appointment.rb +3 -0
- data/spec/support/models/armrest.rb +10 -0
- data/spec/{app → support}/models/array_field.rb +1 -0
- data/spec/{app → support}/models/article.rb +3 -0
- data/spec/{app → support}/models/artist.rb +3 -0
- data/spec/{app → support}/models/artwork.rb +3 -0
- data/spec/{app → support}/models/audio.rb +3 -0
- data/spec/{app → support}/models/augmentation.rb +3 -0
- data/spec/{app → support}/models/author.rb +3 -0
- data/spec/{app → support}/models/baby.rb +3 -0
- data/spec/{app → support}/models/band.rb +3 -0
- data/spec/{app → support}/models/bar.rb +3 -0
- data/spec/{app → support}/models/basic.rb +3 -0
- data/spec/support/models/bed.rb +4 -0
- data/spec/support/models/big_palette.rb +5 -0
- data/spec/{app → support}/models/birthday.rb +3 -0
- data/spec/support/models/bolt.rb +8 -0
- data/spec/{app → support}/models/bomb.rb +3 -0
- data/spec/{app → support}/models/book.rb +3 -0
- data/spec/{app → support}/models/breed.rb +3 -0
- data/spec/support/models/browser.rb +9 -0
- data/spec/{app → support}/models/building.rb +3 -0
- data/spec/{app → support}/models/building_address.rb +3 -0
- data/spec/{app → support}/models/bus.rb +3 -0
- data/spec/{app → support}/models/business.rb +3 -0
- data/spec/{app → support}/models/callback_test.rb +3 -0
- data/spec/{app → support}/models/canvas.rb +4 -1
- data/spec/support/models/car.rb +4 -0
- data/spec/{app → support}/models/cat.rb +3 -0
- data/spec/{app → support}/models/category.rb +3 -0
- data/spec/{app → support}/models/child.rb +3 -0
- data/spec/{app → support}/models/child_doc.rb +3 -0
- data/spec/{app → support}/models/church.rb +3 -0
- data/spec/{app → support}/models/circle.rb +3 -0
- data/spec/{app → support}/models/circuit.rb +3 -0
- data/spec/{app → support}/models/circus.rb +3 -0
- data/spec/{app → support}/models/code.rb +3 -0
- data/spec/support/models/coding/pull_request.rb +12 -0
- data/spec/support/models/coding.rb +4 -0
- data/spec/{app → support}/models/comment.rb +3 -0
- data/spec/{app → support}/models/company.rb +3 -0
- data/spec/{app → support}/models/consumption_period.rb +3 -0
- data/spec/{app → support}/models/contextable_item.rb +3 -0
- data/spec/{app → support}/models/contractor.rb +3 -0
- data/spec/{app → support}/models/cookie.rb +3 -0
- data/spec/{app → support}/models/country_code.rb +3 -0
- data/spec/{app → support}/models/courier_job.rb +3 -0
- data/spec/support/models/crate.rb +13 -0
- data/spec/{app → support}/models/customer.rb +0 -0
- data/spec/{app → support}/models/customer_address.rb +0 -0
- data/spec/support/models/deed.rb +8 -0
- data/spec/{app → support}/models/definition.rb +3 -0
- data/spec/{app → support}/models/delegating_patient.rb +0 -0
- data/spec/{app → support}/models/description.rb +3 -0
- data/spec/{app → support}/models/dictionary.rb +9 -0
- data/spec/{app → support}/models/division.rb +3 -0
- data/spec/{app → support}/models/doctor.rb +3 -0
- data/spec/{app → support}/models/dog.rb +3 -0
- data/spec/{app → support}/models/dokument.rb +3 -0
- data/spec/{app → support}/models/draft.rb +3 -0
- data/spec/{app → support}/models/dragon.rb +3 -0
- data/spec/{app → support}/models/driver.rb +4 -1
- data/spec/{app → support}/models/drug.rb +3 -0
- data/spec/{app → support}/models/dungeon.rb +3 -0
- data/spec/{app → support}/models/edit.rb +3 -0
- data/spec/{app → support}/models/email.rb +3 -0
- data/spec/support/models/employer.rb +8 -0
- data/spec/{app → support}/models/entry.rb +3 -0
- data/spec/support/models/eraser.rb +4 -0
- data/spec/{app → support}/models/even.rb +3 -0
- data/spec/{app → support}/models/event.rb +3 -0
- data/spec/{app → support}/models/exhibition.rb +3 -0
- data/spec/{app → support}/models/exhibitor.rb +3 -0
- data/spec/{app → support}/models/explosion.rb +3 -0
- data/spec/{app → support}/models/eye.rb +3 -0
- data/spec/{app → support}/models/eye_bowl.rb +3 -0
- data/spec/{app → support}/models/face.rb +3 -0
- data/spec/{app → support}/models/favorite.rb +3 -0
- data/spec/{app → support}/models/filesystem.rb +3 -0
- data/spec/{app → support}/models/fire_hydrant.rb +3 -0
- data/spec/{app → support}/models/firefox.rb +3 -0
- data/spec/{app → support}/models/fish.rb +3 -0
- data/spec/{app → support}/models/folder.rb +3 -0
- data/spec/{app → support}/models/folder_item.rb +3 -0
- data/spec/{app → support}/models/fruits.rb +3 -0
- data/spec/{app → support}/models/game.rb +3 -0
- data/spec/{app → support}/models/ghost.rb +3 -0
- data/spec/support/models/guitar.rb +5 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/{app → support}/models/home.rb +3 -0
- data/spec/{app → support}/models/house.rb +3 -0
- data/spec/support/models/html_writer.rb +6 -0
- data/spec/{app → support}/models/id_key.rb +3 -0
- data/spec/support/models/idnodef.rb +8 -0
- data/spec/{app → support}/models/image.rb +3 -0
- data/spec/{app → support}/models/implant.rb +3 -0
- data/spec/support/models/instrument.rb +9 -0
- data/spec/{app → support}/models/item.rb +4 -1
- data/spec/{app → support}/models/jar.rb +3 -0
- data/spec/{app → support}/models/kaleidoscope.rb +3 -0
- data/spec/{app → support}/models/kangaroo.rb +4 -1
- data/spec/{app → support}/models/label.rb +3 -0
- data/spec/{app → support}/models/language.rb +3 -0
- data/spec/{app → support}/models/lat_lng.rb +3 -0
- data/spec/{app → support}/models/league.rb +3 -0
- data/spec/support/models/learner.rb +5 -0
- data/spec/{app → support}/models/line_item.rb +3 -0
- data/spec/{app → support}/models/location.rb +3 -0
- data/spec/{app → support}/models/login.rb +3 -0
- data/spec/{app → support}/models/manufacturer.rb +3 -0
- data/spec/{app → support}/models/meat.rb +3 -0
- data/spec/{app → support}/models/membership.rb +3 -0
- data/spec/{app → support}/models/message.rb +3 -0
- data/spec/{app → support}/models/minim.rb +1 -1
- data/spec/{app → support}/models/mixed_drink.rb +3 -0
- data/spec/support/models/mop.rb +25 -0
- data/spec/{app → support}/models/movie.rb +3 -0
- data/spec/support/models/my_hash.rb +5 -0
- data/spec/{app → support}/models/name.rb +3 -0
- data/spec/support/models/name_only.rb +9 -0
- data/spec/{app → support}/models/node.rb +3 -0
- data/spec/{app → support}/models/note.rb +3 -0
- data/spec/support/models/nut.rb +8 -0
- data/spec/{app → support}/models/odd.rb +3 -0
- data/spec/support/models/order.rb +11 -0
- data/spec/{app → support}/models/ordered_post.rb +3 -0
- data/spec/{app → support}/models/ordered_preference.rb +3 -0
- data/spec/{app → support}/models/oscar.rb +3 -0
- data/spec/support/models/other_owner_object.rb +5 -0
- data/spec/{app → support}/models/override.rb +3 -0
- data/spec/{app → support}/models/ownable.rb +3 -0
- data/spec/{app → support}/models/owner.rb +5 -0
- data/spec/support/models/pack.rb +6 -0
- data/spec/{app → support}/models/page.rb +3 -0
- data/spec/{app → support}/models/page_question.rb +3 -0
- data/spec/{app → support}/models/palette.rb +4 -1
- data/spec/{app → support}/models/parent.rb +3 -0
- data/spec/{app → support}/models/parent_doc.rb +3 -0
- data/spec/{app → support}/models/passport.rb +4 -0
- data/spec/{app → support}/models/patient.rb +3 -0
- data/spec/support/models/pdf_writer.rb +6 -0
- data/spec/support/models/pencil.rb +4 -0
- data/spec/{app → support}/models/person.rb +21 -1
- data/spec/{app → support}/models/pet.rb +3 -0
- data/spec/{app → support}/models/pet_owner.rb +3 -0
- data/spec/{app → support}/models/phone.rb +4 -0
- data/spec/support/models/piano.rb +5 -0
- data/spec/{app → support}/models/pizza.rb +3 -0
- data/spec/{app → support}/models/player.rb +3 -0
- data/spec/{app → support}/models/post.rb +3 -0
- data/spec/{app → support}/models/post_genre.rb +3 -0
- data/spec/{app → support}/models/powerup.rb +3 -0
- data/spec/{app → support}/models/preference.rb +3 -0
- data/spec/{app → support}/models/princess.rb +3 -0
- data/spec/{app → support}/models/product.rb +3 -0
- data/spec/support/models/profile.rb +18 -0
- data/spec/{app → support}/models/pronunciation.rb +3 -0
- data/spec/{app → support}/models/pub.rb +3 -0
- data/spec/support/models/publication/encyclopedia.rb +12 -0
- data/spec/support/models/publication/review.rb +14 -0
- data/spec/support/models/publication.rb +5 -0
- data/spec/{app → support}/models/purchase.rb +3 -0
- data/spec/{app → support}/models/question.rb +3 -0
- data/spec/{app → support}/models/quiz.rb +3 -0
- data/spec/{app → support}/models/rating.rb +3 -0
- data/spec/{app → support}/models/record.rb +3 -0
- data/spec/{app → support}/models/registry.rb +3 -0
- data/spec/{app → support}/models/role.rb +3 -0
- data/spec/{app → support}/models/root_category.rb +3 -0
- data/spec/{app → support}/models/sandwich.rb +3 -0
- data/spec/{app → support}/models/scheduler.rb +3 -0
- data/spec/support/models/scribe.rb +8 -0
- data/spec/support/models/sealer.rb +8 -0
- data/spec/support/models/seat.rb +25 -0
- data/spec/{app → support}/models/seo.rb +3 -0
- data/spec/support/models/series.rb +8 -0
- data/spec/{app → support}/models/server.rb +3 -0
- data/spec/{app → support}/models/service.rb +3 -0
- data/spec/{app → support}/models/shape.rb +5 -2
- data/spec/{app → support}/models/shelf.rb +3 -0
- data/spec/{app → support}/models/shipment_address.rb +3 -0
- data/spec/{app → support}/models/shipping_container.rb +3 -0
- data/spec/{app → support}/models/shipping_pack.rb +3 -0
- data/spec/support/models/shirt.rb +12 -0
- data/spec/{app → support}/models/shop.rb +3 -0
- data/spec/{app → support}/models/short_agent.rb +3 -0
- data/spec/{app → support}/models/short_quiz.rb +3 -0
- data/spec/{app → support}/models/simple.rb +3 -0
- data/spec/{app → support}/models/slave.rb +3 -0
- data/spec/{app → support}/models/song.rb +3 -0
- data/spec/{app → support}/models/sound.rb +3 -0
- data/spec/support/models/spacer.rb +8 -0
- data/spec/{app → support}/models/square.rb +3 -0
- data/spec/{app → support}/models/staff.rb +3 -0
- data/spec/{app → support}/models/store_as_dup_test1.rb +3 -0
- data/spec/{app → support}/models/store_as_dup_test2.rb +3 -0
- data/spec/{app → support}/models/store_as_dup_test3.rb +1 -0
- data/spec/{app → support}/models/store_as_dup_test4.rb +1 -0
- data/spec/support/models/strategy.rb +6 -0
- data/spec/support/models/sub_item.rb +6 -0
- data/spec/{app → support}/models/subscription.rb +3 -0
- data/spec/{app → support}/models/survey.rb +3 -0
- data/spec/{app → support}/models/symptom.rb +3 -0
- data/spec/support/models/system_role.rb +7 -0
- data/spec/{app → support}/models/tag.rb +3 -0
- data/spec/{app → support}/models/target.rb +3 -0
- data/spec/{app → support}/models/template.rb +3 -0
- data/spec/{app → support}/models/thing.rb +3 -0
- data/spec/support/models/threadlocker.rb +8 -0
- data/spec/support/models/title.rb +6 -0
- data/spec/support/models/tool.rb +11 -0
- data/spec/{app → support}/models/topping.rb +3 -0
- data/spec/support/models/toy.rb +10 -0
- data/spec/{app → support}/models/track.rb +3 -0
- data/spec/{app → support}/models/translation.rb +3 -0
- data/spec/{app → support}/models/tree.rb +3 -0
- data/spec/support/models/truck.rb +8 -0
- data/spec/{app → support}/models/updatable.rb +1 -0
- data/spec/{app → support}/models/user.rb +3 -0
- data/spec/{app → support}/models/user_account.rb +3 -0
- data/spec/{app → support}/models/validation_callback.rb +3 -0
- data/spec/support/models/vehicle.rb +19 -0
- data/spec/{app → support}/models/version.rb +3 -0
- data/spec/{app → support}/models/vertex.rb +4 -1
- data/spec/{app → support}/models/vet_visit.rb +3 -0
- data/spec/{app → support}/models/video.rb +3 -0
- data/spec/support/models/video_game.rb +4 -0
- data/spec/support/models/washer.rb +8 -0
- data/spec/{app → support}/models/weapon.rb +3 -0
- data/spec/{app → support}/models/wiki_page.rb +4 -0
- data/spec/{app → support}/models/word.rb +3 -0
- data/spec/{app → support}/models/word_origin.rb +3 -0
- data/spec/{app → support}/models/writer.rb +5 -2
- data/spec/support/shared/time.rb +54 -0
- data/spec/support/spec_config.rb +14 -3
- data.tar.gz.sig +0 -0
- metadata +1035 -732
- metadata.gz.sig +2 -2
- data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
- data/lib/mongoid/matchable/all.rb +0 -28
- data/lib/mongoid/matchable/and.rb +0 -30
- data/lib/mongoid/matchable/default.rb +0 -119
- data/lib/mongoid/matchable/elem_match.rb +0 -34
- data/lib/mongoid/matchable/eq.rb +0 -22
- data/lib/mongoid/matchable/exists.rb +0 -23
- data/lib/mongoid/matchable/gt.rb +0 -23
- data/lib/mongoid/matchable/gte.rb +0 -23
- data/lib/mongoid/matchable/in.rb +0 -24
- data/lib/mongoid/matchable/lt.rb +0 -23
- data/lib/mongoid/matchable/lte.rb +0 -23
- data/lib/mongoid/matchable/ne.rb +0 -21
- data/lib/mongoid/matchable/nin.rb +0 -22
- data/lib/mongoid/matchable/nor.rb +0 -37
- data/lib/mongoid/matchable/or.rb +0 -33
- data/lib/mongoid/matchable/regexp.rb +0 -27
- data/lib/mongoid/matchable/size.rb +0 -21
- data/spec/app/models/actress.rb +0 -2
- data/spec/app/models/bed.rb +0 -1
- data/spec/app/models/big_palette.rb +0 -2
- data/spec/app/models/browser.rb +0 -6
- data/spec/app/models/car.rb +0 -1
- data/spec/app/models/employer.rb +0 -5
- data/spec/app/models/eraser.rb +0 -1
- data/spec/app/models/html_writer.rb +0 -3
- data/spec/app/models/learner.rb +0 -2
- data/spec/app/models/my_hash.rb +0 -2
- data/spec/app/models/other_owner_object.rb +0 -2
- data/spec/app/models/pack.rb +0 -3
- data/spec/app/models/pdf_writer.rb +0 -3
- data/spec/app/models/pencil.rb +0 -1
- data/spec/app/models/profile.rb +0 -5
- data/spec/app/models/series.rb +0 -4
- data/spec/app/models/strategy.rb +0 -3
- data/spec/app/models/sub_item.rb +0 -3
- data/spec/app/models/title.rb +0 -3
- data/spec/app/models/tool.rb +0 -8
- data/spec/app/models/truck.rb +0 -3
- data/spec/app/models/vehicle.rb +0 -11
- data/spec/app/models/video_game.rb +0 -1
- data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
- data/spec/mongoid/matchable/all_spec.rb +0 -31
- data/spec/mongoid/matchable/and_spec.rb +0 -187
- data/spec/mongoid/matchable/default_spec.rb +0 -137
- data/spec/mongoid/matchable/elem_match_spec.rb +0 -106
- data/spec/mongoid/matchable/eq_spec.rb +0 -48
- data/spec/mongoid/matchable/exists_spec.rb +0 -57
- data/spec/mongoid/matchable/gt_spec.rb +0 -86
- data/spec/mongoid/matchable/gte_spec.rb +0 -84
- data/spec/mongoid/matchable/in_spec.rb +0 -49
- data/spec/mongoid/matchable/lt_spec.rb +0 -85
- data/spec/mongoid/matchable/lte_spec.rb +0 -85
- data/spec/mongoid/matchable/ne_spec.rb +0 -46
- data/spec/mongoid/matchable/nin_spec.rb +0 -48
- data/spec/mongoid/matchable/nor_spec.rb +0 -209
- data/spec/mongoid/matchable/or_spec.rb +0 -131
- data/spec/mongoid/matchable/regexp_spec.rb +0 -59
- data/spec/mongoid/matchable/size_spec.rb +0 -25
- data/spec/mongoid/matchable_spec.rb +0 -853
- data/spec/support/child_process_helper.rb +0 -76
- data/spec/support/cluster_config.rb +0 -158
|
@@ -9,138 +9,1084 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
9
9
|
Mongoid::Query.new("id" => "_id")
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
shared_examples_for 'returns a cloned query' do
|
|
13
|
+
|
|
14
|
+
it "returns a cloned query" do
|
|
15
|
+
expect(selection).to_not equal(query)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Hoisting means the operator can be elided, for example
|
|
20
|
+
# Foo.and(a: 1) produces simply {'a' => 1}.
|
|
21
|
+
shared_examples_for 'a hoisting logical operation' do
|
|
22
|
+
|
|
23
|
+
let(:query) do
|
|
24
|
+
Mongoid::Query.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "when provided a single criterion" do
|
|
28
|
+
|
|
29
|
+
shared_examples_for 'adds the conditions to top level' do
|
|
30
|
+
|
|
31
|
+
it "adds the conditions to top level" do
|
|
32
|
+
expect(selection.selector).to eq(
|
|
33
|
+
"field" => [ 1, 2 ]
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it_behaves_like 'returns a cloned query'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
let(:selection) do
|
|
41
|
+
query.send(tested_method, field: [ 1, 2 ])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it_behaves_like 'adds the conditions to top level'
|
|
45
|
+
|
|
46
|
+
context 'when the criterion is wrapped in an array' do
|
|
47
|
+
let(:selection) do
|
|
48
|
+
query.send(tested_method, [{field: [ 1, 2 ] }])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it_behaves_like 'adds the conditions to top level'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'when the criterion is wrapped in a deep array with nil elements' do
|
|
55
|
+
let(:selection) do
|
|
56
|
+
query.send(tested_method, [[[{field: [ 1, 2 ] }]], [nil]])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it_behaves_like 'adds the conditions to top level'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'when argument is a Criteria' do
|
|
64
|
+
let(:base) do
|
|
65
|
+
query.where(hello: 'world')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
let(:other) do
|
|
69
|
+
query.where(foo: 'bar')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
let(:result) { base.send(tested_method, other) }
|
|
73
|
+
|
|
74
|
+
it 'combines' do
|
|
75
|
+
expect(result.selector).to eq(
|
|
76
|
+
'hello' => 'world',
|
|
77
|
+
'foo' => 'bar',
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "when provided a single criterion that is handled via Key" do
|
|
83
|
+
|
|
84
|
+
shared_examples_for 'adds the conditions to top level' do
|
|
85
|
+
|
|
86
|
+
it "adds the conditions to top level" do
|
|
87
|
+
expect(selection.selector).to eq({
|
|
88
|
+
"field" => {'$gt' => 3},
|
|
89
|
+
})
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it_behaves_like 'returns a cloned query'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
let(:selection) do
|
|
96
|
+
query.send(tested_method, :field.gt => 3)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it_behaves_like 'adds the conditions to top level'
|
|
100
|
+
|
|
101
|
+
context 'when the criterion is wrapped in an array' do
|
|
102
|
+
let(:selection) do
|
|
103
|
+
query.send(tested_method, [{ :field.gt => 3 }])
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it_behaves_like 'adds the conditions to top level'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'when the criterion is wrapped in a deep array with nil elements' do
|
|
110
|
+
let(:selection) do
|
|
111
|
+
query.send(tested_method, [[[{ :field.gt => 3 }]], [nil]])
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it_behaves_like 'adds the conditions to top level'
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'when the criterion is a time' do
|
|
118
|
+
let(:selection) do
|
|
119
|
+
query.send(tested_method, :field.gte => Time.new(2020, 1, 1))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'adds the conditions' do
|
|
123
|
+
expect(selection.selector).to eq({
|
|
124
|
+
"field" => {'$gte' => Time.new(2020, 1, 1)},
|
|
125
|
+
})
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'keeps argument type' do
|
|
129
|
+
selection.selector['field']['$gte'].should be_a(Time)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context 'when the criterion is a datetime' do
|
|
134
|
+
let(:selection) do
|
|
135
|
+
query.send(tested_method, :field.gte => DateTime.new(2020, 1, 1))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'adds the conditions' do
|
|
139
|
+
expect(selection.selector).to eq({
|
|
140
|
+
"field" => {'$gte' => Time.utc(2020, 1, 1)},
|
|
141
|
+
})
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'converts argument to a time' do
|
|
145
|
+
selection.selector['field']['$gte'].should be_a(Time)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
context 'when the criterion is a date' do
|
|
150
|
+
let(:selection) do
|
|
151
|
+
query.send(tested_method, :field.gte => Date.new(2020, 1, 1))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'adds the conditions' do
|
|
155
|
+
expect(selection.selector).to eq({
|
|
156
|
+
"field" => {'$gte' => Time.utc(2020, 1, 1)},
|
|
157
|
+
})
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'converts argument to a time' do
|
|
161
|
+
selection.selector['field']['$gte'].should be_a(Time)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "when provided a nested criterion" do
|
|
167
|
+
|
|
168
|
+
let(:selection) do
|
|
169
|
+
query.send(tested_method, :test.elem_match => { :field.in => [ 1, 2 ] })
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "builds the correct selector" do
|
|
173
|
+
expect(selection.selector).to eq({
|
|
174
|
+
"test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}
|
|
175
|
+
})
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it_behaves_like 'returns a cloned query'
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
context "when chaining the criteria" do
|
|
182
|
+
|
|
183
|
+
context "when the criteria are for different fields" do
|
|
184
|
+
|
|
185
|
+
let(:selection) do
|
|
186
|
+
query.and(first: [ 1, 2 ]).send(tested_method, second: [ 3, 4 ])
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "adds the conditions to top level" do
|
|
190
|
+
expect(selection.selector).to eq({
|
|
191
|
+
"first" => [ 1, 2 ],
|
|
192
|
+
"second" => [ 3, 4 ],
|
|
193
|
+
})
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it_behaves_like 'returns a cloned query'
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context "when the criteria are on the same field" do
|
|
200
|
+
|
|
201
|
+
let(:selection) do
|
|
202
|
+
query.and(first: [ 1, 2 ]).send(tested_method, first: [ 3, 4 ])
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "combines via $and operator" do
|
|
206
|
+
expect(selection.selector).to eq({
|
|
207
|
+
"first" => [ 1, 2 ],
|
|
208
|
+
"$and" => [
|
|
209
|
+
{ "first" => [ 3, 4 ] }
|
|
210
|
+
]
|
|
211
|
+
})
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it_behaves_like 'returns a cloned query'
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Non-hoisting means the operator is always present, for example
|
|
220
|
+
# Foo.or(a: 1) produces {'$or' => [{'a' => 1}]}.
|
|
221
|
+
shared_examples_for 'a non-hoisting logical operation' do
|
|
222
|
+
|
|
223
|
+
context 'when there is a single predicate' do
|
|
224
|
+
let(:query) do
|
|
225
|
+
Mongoid::Query.new.send(tested_method, hello: 'world')
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it 'adds the predicate' do
|
|
229
|
+
expect(query.selector).to eq(expected_operator => [{'hello' => 'world'}])
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
context 'when the single predicate is wrapped in an array' do
|
|
234
|
+
let(:query) do
|
|
235
|
+
Mongoid::Query.new.send(tested_method, [{hello: 'world'}])
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'adds the predicate' do
|
|
239
|
+
expect(query.selector).to eq(expected_operator => [{'hello' => 'world'}])
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
context 'when argument is a Criteria' do
|
|
244
|
+
let(:query) do
|
|
245
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
let(:other) do
|
|
249
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
let(:result) { query.send(tested_method, other) }
|
|
253
|
+
|
|
254
|
+
it 'combines' do
|
|
255
|
+
# This is used for $or / $nor, the two conditions should remain
|
|
256
|
+
# as separate hashes
|
|
257
|
+
expect(result.selector).to eq(expected_operator => [{'hello' => 'world'}, {'foo' => 'bar'}])
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
context 'when argument is a mix of Criteria and hashes' do
|
|
262
|
+
let(:query) do
|
|
263
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
let(:other1) do
|
|
267
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
let(:other2) do
|
|
271
|
+
{bar: 42}
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
let(:other3) do
|
|
275
|
+
Mongoid::Query.new.where(a: 2)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
let(:result) { query.send(tested_method, other1, other2, other3) }
|
|
279
|
+
|
|
280
|
+
it 'combines' do
|
|
281
|
+
expect(result.selector).to eq(expected_operator => [
|
|
282
|
+
{'hello' => 'world'},
|
|
283
|
+
{'foo' => 'bar'},
|
|
284
|
+
{'bar' => 42},
|
|
285
|
+
{'a' => 2},
|
|
286
|
+
])
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
12
291
|
describe "#and" do
|
|
13
292
|
|
|
14
|
-
|
|
293
|
+
let(:tested_method) { :and }
|
|
294
|
+
let(:expected_operator) { '$and' }
|
|
295
|
+
|
|
296
|
+
it_behaves_like 'a hoisting logical operation'
|
|
297
|
+
|
|
298
|
+
context "when provided no criterion" do
|
|
299
|
+
|
|
300
|
+
let(:selection) do
|
|
301
|
+
query.and
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it "does not add any criterion" do
|
|
305
|
+
expect(selection.selector).to eq({})
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it "returns the query" do
|
|
309
|
+
expect(selection).to eq(query)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it_behaves_like 'returns a cloned query'
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
context "when provided nil" do
|
|
316
|
+
|
|
317
|
+
let(:selection) do
|
|
318
|
+
query.and(nil)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "does not add any criterion" do
|
|
322
|
+
expect(selection.selector).to eq({})
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
it "returns the query" do
|
|
326
|
+
expect(selection).to eq(query)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it_behaves_like 'returns a cloned query'
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
context "when provided multiple criteria" do
|
|
333
|
+
|
|
334
|
+
context "when the criterion is already included" do
|
|
335
|
+
|
|
336
|
+
context 'simple criterion' do
|
|
337
|
+
let(:selection) do
|
|
338
|
+
query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it "adds all conditions" do
|
|
342
|
+
expect(selection.selector).to eq({
|
|
343
|
+
'first' => [1, 2],
|
|
344
|
+
"$and" => [
|
|
345
|
+
{ "first" => [ 1, 2 ] }
|
|
346
|
+
]
|
|
347
|
+
})
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it_behaves_like 'returns a cloned query'
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context 'Key criterion' do
|
|
354
|
+
let(:selection) do
|
|
355
|
+
query.and({ first: [ 1, 2 ] }).and(:first.gt => 3)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
it "adds all conditions" do
|
|
359
|
+
expect(selection.selector).to eq({
|
|
360
|
+
'first' => [1, 2],
|
|
361
|
+
"$and" => [
|
|
362
|
+
{ "first" => {'$gt' => 3} }
|
|
363
|
+
]
|
|
364
|
+
})
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it_behaves_like 'returns a cloned query'
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context 'Key criterion when existing criterion is an operator' do
|
|
371
|
+
let(:selection) do
|
|
372
|
+
query.and(:first.lt => 5).and(:first.gt => 3)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "adds all conditions" do
|
|
376
|
+
expect(selection.selector).to eq({
|
|
377
|
+
'first' => {'$lt' => 5, '$gt' => 3},
|
|
378
|
+
})
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it_behaves_like 'returns a cloned query'
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
context "when the new criteria are for different fields" do
|
|
386
|
+
|
|
387
|
+
let(:selection) do
|
|
388
|
+
query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
it "adds all conditions to top level" do
|
|
392
|
+
expect(selection.selector).to eq({
|
|
393
|
+
"first" => [ 1, 2 ],
|
|
394
|
+
"second" => [ 3, 4 ],
|
|
395
|
+
})
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it_behaves_like 'returns a cloned query'
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
context "when the new criteria are for the same field" do
|
|
402
|
+
|
|
403
|
+
context 'when criteria are simple' do
|
|
404
|
+
let(:selection) do
|
|
405
|
+
query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it "combines via $and operator" do
|
|
409
|
+
expect(selection.selector).to eq({
|
|
410
|
+
"first" => [ 1, 2 ],
|
|
411
|
+
"$and" => [
|
|
412
|
+
{ "first" => [ 3, 4 ] }
|
|
413
|
+
]
|
|
414
|
+
})
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
it_behaves_like 'returns a cloned query'
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
context 'when criteria use operators' do
|
|
421
|
+
shared_examples 'behave correctly' do
|
|
422
|
+
let(:selection) do
|
|
423
|
+
query.and(
|
|
424
|
+
{ field: {first_operator => [ 1, 2 ] }},
|
|
425
|
+
{ field: {second_operator => [ 3, 4 ] }},
|
|
426
|
+
)
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
it "combines via $and operator and stringifies all keys" do
|
|
430
|
+
expect(selection.selector).to eq({
|
|
431
|
+
"field" => {'$in' => [ 1, 2 ]},
|
|
432
|
+
"$and" => [
|
|
433
|
+
{ "field" => {'$in' => [ 3, 4 ] }}
|
|
434
|
+
]
|
|
435
|
+
})
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
[
|
|
440
|
+
['$in', '$in'],
|
|
441
|
+
[:$in, '$in'],
|
|
442
|
+
['$in', :$in],
|
|
443
|
+
[:$in, :$in],
|
|
444
|
+
].each do |first_operator, second_operator|
|
|
445
|
+
context "when first operator is #{first_operator.inspect} and second operator is #{second_operator.inspect}" do
|
|
446
|
+
let(:first_operator) { first_operator }
|
|
447
|
+
let(:second_operator) { second_operator }
|
|
448
|
+
|
|
449
|
+
include_examples 'behave correctly'
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
context 'when criteria are handled via Key' do
|
|
455
|
+
shared_examples_for 'adds the conditions to top level' do
|
|
456
|
+
|
|
457
|
+
it "adds the conditions to top level" do
|
|
458
|
+
expect(selection.selector).to eq({
|
|
459
|
+
"field" => {'$gt' => 3, '$lt' => 5},
|
|
460
|
+
})
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it_behaves_like 'returns a cloned query'
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
context 'criteria are provided in the same hash' do
|
|
467
|
+
let(:selection) do
|
|
468
|
+
query.send(tested_method, :field.gt => 3, :field.lt => 5)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
it_behaves_like 'adds the conditions to top level'
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
context 'criteria are provided in separate hashes' do
|
|
475
|
+
let(:selection) do
|
|
476
|
+
query.send(tested_method, {:field.gt => 3}, {:field.lt => 5})
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it_behaves_like 'adds the conditions to top level'
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
context 'when the criterion is wrapped in an array' do
|
|
483
|
+
let(:selection) do
|
|
484
|
+
query.send(tested_method, [:field.gt => 3], [:field.lt => 5])
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it_behaves_like 'adds the conditions to top level'
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
context 'when criteria are simple and handled via Key' do
|
|
492
|
+
shared_examples_for 'combines conditions with $and' do
|
|
493
|
+
|
|
494
|
+
it "combines conditions with $and" do
|
|
495
|
+
expect(selection.selector).to eq({
|
|
496
|
+
"field" => 3,
|
|
497
|
+
'$and' => ['field' => {'$lt' => 5}],
|
|
498
|
+
})
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it_behaves_like 'returns a cloned query'
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
505
|
+
|
|
506
|
+
it "combines conditions with $eq" do
|
|
507
|
+
expect(selection.selector).to eq({
|
|
508
|
+
"field" => {'$eq' => 3, '$lt' => 5},
|
|
509
|
+
})
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it_behaves_like 'returns a cloned query'
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
516
|
+
|
|
517
|
+
it "combines conditions with $regex" do
|
|
518
|
+
expect(selection.selector).to eq({
|
|
519
|
+
"field" => {'$regex' => /t/, '$lt' => 5},
|
|
520
|
+
})
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
it_behaves_like 'returns a cloned query'
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
context 'criteria are provided in the same hash' do
|
|
527
|
+
context 'non-regexp argument' do
|
|
528
|
+
let(:selection) do
|
|
529
|
+
query.send(tested_method, :field => 3, :field.lt => 5)
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it_behaves_like 'combines conditions with $eq'
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
context 'regexp argument' do
|
|
536
|
+
let(:selection) do
|
|
537
|
+
query.send(tested_method, :field => /t/, :field.lt => 5)
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
it_behaves_like 'combines conditions with $regex'
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
context 'criteria are provided in separate hashes' do
|
|
545
|
+
let(:selection) do
|
|
546
|
+
query.send(tested_method, {:field => 3}, {:field.lt => 5})
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it_behaves_like 'combines conditions with $and'
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
context 'when the criterion is wrapped in an array' do
|
|
553
|
+
let(:selection) do
|
|
554
|
+
query.send(tested_method, [:field => 3], [:field.lt => 5])
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
it_behaves_like 'combines conditions with $and'
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
context 'when criteria are handled via Key and simple' do
|
|
562
|
+
shared_examples_for 'combines conditions with $and' do
|
|
563
|
+
|
|
564
|
+
it "combines conditions with $and" do
|
|
565
|
+
expect(selection.selector).to eq({
|
|
566
|
+
"field" => {'$gt' => 3},
|
|
567
|
+
'$and' => ['field' => 5],
|
|
568
|
+
})
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
it_behaves_like 'returns a cloned query'
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
575
|
+
|
|
576
|
+
it "combines conditions with $eq" do
|
|
577
|
+
expect(selection.selector).to eq({
|
|
578
|
+
"field" => {'$gt' => 3, '$eq' => 5},
|
|
579
|
+
})
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
it_behaves_like 'returns a cloned query'
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
586
|
+
|
|
587
|
+
it "combines conditions with $regex" do
|
|
588
|
+
expect(selection.selector).to eq({
|
|
589
|
+
"field" => {'$gt' => 3, '$regex' => /t/},
|
|
590
|
+
})
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
it_behaves_like 'returns a cloned query'
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
context 'criteria are provided in the same hash' do
|
|
597
|
+
context 'non-regexp argument' do
|
|
598
|
+
let(:selection) do
|
|
599
|
+
query.send(tested_method, :field.gt => 3, :field => 5)
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
it_behaves_like 'combines conditions with $eq'
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
context 'regexp argument' do
|
|
606
|
+
let(:selection) do
|
|
607
|
+
query.send(tested_method, :field.gt => 3, :field => /t/)
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
it_behaves_like 'combines conditions with $regex'
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
context 'criteria are provided in separate hashes' do
|
|
615
|
+
let(:selection) do
|
|
616
|
+
query.send(tested_method, {:field.gt => 3}, {:field => 5})
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it_behaves_like 'combines conditions with $and'
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
context 'when the criterion is wrapped in an array' do
|
|
623
|
+
let(:selection) do
|
|
624
|
+
query.send(tested_method, [:field.gt => 3], [:field => 5])
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
it_behaves_like 'combines conditions with $and'
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
context 'when argument is a Criteria' do
|
|
634
|
+
let(:query) do
|
|
635
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
let(:result) { query.and(other) }
|
|
639
|
+
|
|
640
|
+
context 'different fields' do
|
|
641
|
+
|
|
642
|
+
let(:other) do
|
|
643
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
it 'combines both fields at top level' do
|
|
647
|
+
expect(result.selector).to eq('hello' => 'world', 'foo' => 'bar')
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
context 'same field' do
|
|
652
|
+
|
|
653
|
+
let(:other) do
|
|
654
|
+
Mongoid::Query.new.where(hello: /bar/)
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
it 'combines fields with $and' do
|
|
658
|
+
expect(result.selector).to eq('hello' => 'world', '$and' => [{'hello' => /bar/}])
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
context 'when argument is a mix of Criteria and hashes' do
|
|
664
|
+
let(:query) do
|
|
665
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
let(:other1) do
|
|
669
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
let(:other2) do
|
|
673
|
+
{bar: 42}
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
let(:other3) do
|
|
677
|
+
Mongoid::Query.new.where(a: 2)
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
let(:result) { query.and(other1, other2, other3) }
|
|
681
|
+
|
|
682
|
+
it 'combines' do
|
|
683
|
+
expect(result.selector).to eq('hello' => 'world',
|
|
684
|
+
'foo' => 'bar',
|
|
685
|
+
'bar' => 42,
|
|
686
|
+
'a' => 2,
|
|
687
|
+
)
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
context 'when Key instances are used and types involved have serializers' do
|
|
692
|
+
let(:time) { Time.now }
|
|
693
|
+
|
|
694
|
+
let(:query) do
|
|
695
|
+
Band.all.and(:created_at.gt => time)
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
let(:expected) do
|
|
699
|
+
{'created_at' => {'$gt' => time.utc}}
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
it 'combines and evolves' do
|
|
703
|
+
expect(query.selector).to eq(expected)
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
describe 'query shape' do
|
|
708
|
+
shared_examples_for 'adds most recent criterion as $and' do
|
|
709
|
+
let(:selector) { scope.selector }
|
|
710
|
+
|
|
711
|
+
it 'adds most recent criterion as $and' do
|
|
712
|
+
expect(selector).to eq('foo' => 1, '$and' => [{'foo' => 2}])
|
|
713
|
+
end
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
context 'and/and' do
|
|
717
|
+
let(:scope) do
|
|
718
|
+
Band.and(foo: 1).and(foo: 2)
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
it_behaves_like 'adds most recent criterion as $and'
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
context 'and/and' do
|
|
725
|
+
let(:scope) do
|
|
726
|
+
Band.and(foo: 1).and(foo: 2)
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
it_behaves_like 'adds most recent criterion as $and'
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
context 'and/where' do
|
|
733
|
+
let(:scope) do
|
|
734
|
+
Band.and(foo: 1).where(foo: 2)
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
it_behaves_like 'adds most recent criterion as $and'
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
context 'where/and' do
|
|
741
|
+
let(:scope) do
|
|
742
|
+
Band.where(foo: 1).and(foo: 2)
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
it_behaves_like 'adds most recent criterion as $and'
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
context 'where/where' do
|
|
749
|
+
let(:scope) do
|
|
750
|
+
Band.where(foo: 1).where(foo: 2)
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
it_behaves_like 'adds most recent criterion as $and'
|
|
754
|
+
end
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
context 'when conditions already exist in criteria' do
|
|
758
|
+
let(:base_selection) do
|
|
759
|
+
query.where(foo: 'bar')
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
context 'when hash conditions are given' do
|
|
763
|
+
let(:selection) do
|
|
764
|
+
base_selection.and(hello: 'world')
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
it 'adds new conditions to top level' do
|
|
768
|
+
selection.selector.should == {
|
|
769
|
+
'foo' => 'bar',
|
|
770
|
+
'hello' => 'world',
|
|
771
|
+
}
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
context 'when criteria conditions are given' do
|
|
776
|
+
let(:selection) do
|
|
777
|
+
base_selection.and(query.where(hello: 'world'))
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
it 'adds new conditions to top level' do
|
|
781
|
+
selection.selector.should == {
|
|
782
|
+
'foo' => 'bar',
|
|
783
|
+
'hello' => 'world',
|
|
784
|
+
}
|
|
785
|
+
end
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
context 'when complex criteria conditions are given' do
|
|
789
|
+
let(:selection) do
|
|
790
|
+
base_selection.and(query.or([one: 'one'], [two: 'two']))
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
it 'adds new conditions to top level' do
|
|
794
|
+
selection.selector.should == {
|
|
795
|
+
'foo' => 'bar',
|
|
796
|
+
'$or' => [
|
|
797
|
+
{'one' => 'one'},
|
|
798
|
+
{'two' => 'two'},
|
|
799
|
+
],
|
|
800
|
+
}
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
shared_examples '$or/$nor' do
|
|
807
|
+
|
|
808
|
+
it_behaves_like 'a non-hoisting logical operation'
|
|
809
|
+
|
|
810
|
+
context "when provided no arguments" do
|
|
15
811
|
|
|
16
812
|
let(:selection) do
|
|
17
|
-
query.
|
|
813
|
+
query.send(tested_method)
|
|
18
814
|
end
|
|
19
815
|
|
|
20
|
-
|
|
816
|
+
it_behaves_like 'returns a cloned query'
|
|
817
|
+
|
|
818
|
+
it "does not add any criteria" do
|
|
21
819
|
expect(selection.selector).to eq({})
|
|
22
820
|
end
|
|
23
821
|
|
|
24
822
|
it "returns the query" do
|
|
25
823
|
expect(selection).to eq(query)
|
|
26
824
|
end
|
|
27
|
-
|
|
28
|
-
it "returns a cloned query" do
|
|
29
|
-
expect(selection).to_not equal(query)
|
|
30
|
-
end
|
|
31
825
|
end
|
|
32
826
|
|
|
33
827
|
context "when provided nil" do
|
|
34
828
|
|
|
35
829
|
let(:selection) do
|
|
36
|
-
query.
|
|
830
|
+
query.send(tested_method, nil)
|
|
37
831
|
end
|
|
38
832
|
|
|
39
|
-
|
|
833
|
+
it_behaves_like 'returns a cloned query'
|
|
834
|
+
|
|
835
|
+
it "does not add any criteria" do
|
|
40
836
|
expect(selection.selector).to eq({})
|
|
41
837
|
end
|
|
42
838
|
|
|
43
839
|
it "returns the query" do
|
|
44
840
|
expect(selection).to eq(query)
|
|
45
841
|
end
|
|
46
|
-
|
|
47
|
-
it "returns a cloned query" do
|
|
48
|
-
expect(selection).to_not equal(query)
|
|
49
|
-
end
|
|
50
842
|
end
|
|
51
843
|
|
|
52
844
|
context "when provided a single criterion" do
|
|
53
845
|
|
|
54
846
|
let(:selection) do
|
|
55
|
-
query.
|
|
847
|
+
query.send(tested_method, field: [ 1, 2 ])
|
|
56
848
|
end
|
|
57
849
|
|
|
58
|
-
|
|
850
|
+
it_behaves_like 'returns a cloned query'
|
|
851
|
+
|
|
852
|
+
it "adds the $or/$nor selector" do
|
|
59
853
|
expect(selection.selector).to eq({
|
|
60
|
-
|
|
854
|
+
expected_operator => [{ "field" => [ 1, 2 ] }]
|
|
61
855
|
})
|
|
62
856
|
end
|
|
63
857
|
|
|
64
|
-
|
|
65
|
-
expect(selection).to_not equal(query)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
858
|
+
context 'when the criterion is wrapped in array' do
|
|
68
859
|
|
|
69
|
-
|
|
860
|
+
let(:selection) do
|
|
861
|
+
query.send(tested_method, [{ field: [ 1, 2 ] }])
|
|
862
|
+
end
|
|
70
863
|
|
|
71
|
-
|
|
72
|
-
|
|
864
|
+
it_behaves_like 'returns a cloned query'
|
|
865
|
+
|
|
866
|
+
it "adds the $or/$nor selector" do
|
|
867
|
+
expect(selection.selector).to eq({
|
|
868
|
+
expected_operator => [{ "field" => [ 1, 2 ] }]
|
|
869
|
+
})
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
context 'when the array has nil as one of the elements' do
|
|
873
|
+
|
|
874
|
+
let(:selection) do
|
|
875
|
+
query.send(tested_method, [{ field: [ 1, 2 ] }, nil])
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
it_behaves_like 'returns a cloned query'
|
|
879
|
+
|
|
880
|
+
it "adds the $or/$nor selector ignoring the nil element" do
|
|
881
|
+
expect(selection.selector).to eq({
|
|
882
|
+
expected_operator => [{ "field" => [ 1, 2 ] }]
|
|
883
|
+
})
|
|
884
|
+
end
|
|
885
|
+
end
|
|
73
886
|
end
|
|
74
887
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
888
|
+
context 'when query already has a condition on another field' do
|
|
889
|
+
|
|
890
|
+
let(:selection) do
|
|
891
|
+
query.where(foo: 'bar').send(tested_method, field: [ 1, 2 ])
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
it 'moves original conditions under $or/$nor' do
|
|
895
|
+
expect(selection.selector).to eq({
|
|
896
|
+
expected_operator => [{'foo' => 'bar'}, { "field" => [ 1, 2 ] }]
|
|
897
|
+
})
|
|
898
|
+
end
|
|
79
899
|
end
|
|
80
900
|
|
|
81
|
-
|
|
82
|
-
|
|
901
|
+
context 'when query already has an $or/$nor condition and another condition' do
|
|
902
|
+
|
|
903
|
+
let(:selection) do
|
|
904
|
+
query.send(tested_method, field: [ 1, 2 ]).where(foo: 'bar').send(tested_method, test: 1)
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
it 'unions existing conditions' do
|
|
908
|
+
expect(selection.selector).to eq(
|
|
909
|
+
expected_operator => [
|
|
910
|
+
{
|
|
911
|
+
expected_operator => [{ "field" => [ 1, 2 ] }],
|
|
912
|
+
'foo' => 'bar',
|
|
913
|
+
},
|
|
914
|
+
{'test' => 1},
|
|
915
|
+
]
|
|
916
|
+
)
|
|
917
|
+
end
|
|
83
918
|
end
|
|
84
919
|
end
|
|
85
920
|
|
|
86
|
-
context "when provided multiple
|
|
921
|
+
context "when provided multiple criteria" do
|
|
87
922
|
|
|
88
|
-
context "when the
|
|
923
|
+
context "when the criteria are for different fields" do
|
|
89
924
|
|
|
90
925
|
let(:selection) do
|
|
91
|
-
query.
|
|
926
|
+
query.send(tested_method, { first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
92
927
|
end
|
|
93
928
|
|
|
94
|
-
|
|
929
|
+
it_behaves_like 'returns a cloned query'
|
|
930
|
+
|
|
931
|
+
it "adds the $or/$nor selector" do
|
|
95
932
|
expect(selection.selector).to eq({
|
|
96
|
-
|
|
97
|
-
{ "first" => [ 1, 2 ] }
|
|
933
|
+
expected_operator => [
|
|
934
|
+
{ "first" => [ 1, 2 ] },
|
|
935
|
+
{ "second" => [ 3, 4 ] }
|
|
98
936
|
]
|
|
99
937
|
})
|
|
100
938
|
end
|
|
101
|
-
|
|
102
|
-
it "returns a cloned query" do
|
|
103
|
-
expect(selection).to_not equal(query)
|
|
104
|
-
end
|
|
105
939
|
end
|
|
106
940
|
|
|
107
|
-
context "when the
|
|
941
|
+
context "when the criteria uses a Key instance" do
|
|
108
942
|
|
|
109
943
|
let(:selection) do
|
|
110
|
-
query.
|
|
944
|
+
query.send(tested_method, { first: [ 1, 2 ] }, { :second.gt => 3 })
|
|
111
945
|
end
|
|
112
946
|
|
|
113
|
-
it "adds the $
|
|
947
|
+
it "adds the $or/$nor selector" do
|
|
114
948
|
expect(selection.selector).to eq({
|
|
115
|
-
|
|
949
|
+
expected_operator => [
|
|
116
950
|
{ "first" => [ 1, 2 ] },
|
|
117
|
-
{ "second" =>
|
|
951
|
+
{ "second" => { "$gt" => 3 }}
|
|
118
952
|
]
|
|
119
953
|
})
|
|
120
954
|
end
|
|
121
955
|
|
|
122
|
-
|
|
123
|
-
|
|
956
|
+
it_behaves_like 'returns a cloned query'
|
|
957
|
+
|
|
958
|
+
context 'when the criterion is a time' do
|
|
959
|
+
let(:selection) do
|
|
960
|
+
query.send(tested_method, :field.gte => Time.new(2020, 1, 1))
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
it 'adds the conditions' do
|
|
964
|
+
expect(selection.selector).to eq(expected_operator => [
|
|
965
|
+
"field" => {'$gte' => Time.new(2020, 1, 1)},
|
|
966
|
+
])
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
it 'keeps the type' do
|
|
970
|
+
selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
|
|
971
|
+
end
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
context 'when the criterion is a datetime' do
|
|
975
|
+
let(:selection) do
|
|
976
|
+
query.send(tested_method, :field.gte => DateTime.new(2020, 1, 1))
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
it 'adds the conditions' do
|
|
980
|
+
expect(selection.selector).to eq(expected_operator => [
|
|
981
|
+
"field" => {'$gte' => Time.utc(2020, 1, 1)},
|
|
982
|
+
])
|
|
983
|
+
end
|
|
984
|
+
|
|
985
|
+
it 'converts argument to a time' do
|
|
986
|
+
selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
|
|
987
|
+
end
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
context 'when the criterion is a date' do
|
|
991
|
+
let(:selection) do
|
|
992
|
+
query.send(tested_method, :field.gte => Date.new(2020, 1, 1))
|
|
993
|
+
end
|
|
994
|
+
|
|
995
|
+
it 'adds the conditions' do
|
|
996
|
+
expect(selection.selector).to eq(expected_operator => [
|
|
997
|
+
"field" => {'$gte' => Time.utc(2020, 1, 1)},
|
|
998
|
+
])
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
it 'converts argument to a time' do
|
|
1002
|
+
selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
|
|
1003
|
+
end
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
context "when a criterion has an aliased field" do
|
|
1008
|
+
|
|
1009
|
+
let(:selection) do
|
|
1010
|
+
query.send(tested_method, { id: 1 })
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
it "adds the $or/$nor selector and aliases the field" do
|
|
1014
|
+
expect(selection.selector).to eq({
|
|
1015
|
+
expected_operator => [ { "_id" => 1 } ]
|
|
1016
|
+
})
|
|
124
1017
|
end
|
|
1018
|
+
|
|
1019
|
+
it_behaves_like 'returns a cloned query'
|
|
125
1020
|
end
|
|
126
1021
|
|
|
127
|
-
context "when
|
|
1022
|
+
context "when a criterion is wrapped in an array" do
|
|
128
1023
|
|
|
129
1024
|
let(:selection) do
|
|
130
|
-
query.
|
|
1025
|
+
query.send(tested_method, [{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
|
131
1026
|
end
|
|
132
1027
|
|
|
133
|
-
|
|
1028
|
+
it_behaves_like 'returns a cloned query'
|
|
1029
|
+
|
|
1030
|
+
it "adds the $or/$nor selector" do
|
|
134
1031
|
expect(selection.selector).to eq({
|
|
135
|
-
|
|
1032
|
+
expected_operator => [
|
|
136
1033
|
{ "first" => [ 1, 2 ] },
|
|
137
|
-
{ "
|
|
1034
|
+
{ "second" => { "$gt" => 3 }}
|
|
138
1035
|
]
|
|
139
1036
|
})
|
|
140
1037
|
end
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
context "when the criteria are on the same field" do
|
|
1041
|
+
|
|
1042
|
+
context 'simple criteria' do
|
|
1043
|
+
let(:selection) do
|
|
1044
|
+
query.send(tested_method, { first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
it_behaves_like 'returns a cloned query'
|
|
1048
|
+
|
|
1049
|
+
it "appends both $or/$nor expressions" do
|
|
1050
|
+
expect(selection.selector).to eq({
|
|
1051
|
+
expected_operator => [
|
|
1052
|
+
{ "first" => [ 1, 2 ] },
|
|
1053
|
+
{ "first" => [ 3, 4 ] }
|
|
1054
|
+
]
|
|
1055
|
+
})
|
|
1056
|
+
end
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
context 'Key criteria as one argument' do
|
|
1060
|
+
let(:selection) do
|
|
1061
|
+
query.send(tested_method, :first.gt => 3, :first.lt => 5)
|
|
1062
|
+
end
|
|
1063
|
+
|
|
1064
|
+
it_behaves_like 'returns a cloned query'
|
|
1065
|
+
|
|
1066
|
+
it "adds all criteria" do
|
|
1067
|
+
expect(selection.selector).to eq({
|
|
1068
|
+
expected_operator => [
|
|
1069
|
+
{ "first" => {'$gt' => 3, '$lt' => 5} },
|
|
1070
|
+
]
|
|
1071
|
+
})
|
|
1072
|
+
end
|
|
1073
|
+
end
|
|
1074
|
+
|
|
1075
|
+
context 'Key criteria as multiple arguments' do
|
|
1076
|
+
let(:selection) do
|
|
1077
|
+
query.send(tested_method, {:first.gt => 3}, {:first.lt => 5})
|
|
1078
|
+
end
|
|
141
1079
|
|
|
142
|
-
|
|
143
|
-
|
|
1080
|
+
it_behaves_like 'returns a cloned query'
|
|
1081
|
+
|
|
1082
|
+
it "adds all criteria" do
|
|
1083
|
+
expect(selection.selector).to eq({
|
|
1084
|
+
expected_operator => [
|
|
1085
|
+
{ "first" => {'$gt' => 3} },
|
|
1086
|
+
{ "first" => {'$lt' => 5} },
|
|
1087
|
+
]
|
|
1088
|
+
})
|
|
1089
|
+
end
|
|
144
1090
|
end
|
|
145
1091
|
end
|
|
146
1092
|
end
|
|
@@ -150,385 +1096,564 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
150
1096
|
context "when the criterion are for different fields" do
|
|
151
1097
|
|
|
152
1098
|
let(:selection) do
|
|
153
|
-
query.
|
|
1099
|
+
query.send(tested_method, first: [ 1, 2 ]).send(tested_method, second: [ 3, 4 ])
|
|
154
1100
|
end
|
|
155
1101
|
|
|
156
|
-
|
|
1102
|
+
it_behaves_like 'returns a cloned query'
|
|
1103
|
+
|
|
1104
|
+
it "adds the $or/$nor selectors" do
|
|
157
1105
|
expect(selection.selector).to eq({
|
|
158
|
-
|
|
1106
|
+
expected_operator => [
|
|
159
1107
|
{ "first" => [ 1, 2 ] },
|
|
160
1108
|
{ "second" => [ 3, 4 ] }
|
|
161
1109
|
]
|
|
162
1110
|
})
|
|
163
1111
|
end
|
|
164
|
-
|
|
165
|
-
it "returns a cloned query" do
|
|
166
|
-
expect(selection).to_not equal(query)
|
|
167
|
-
end
|
|
168
1112
|
end
|
|
169
1113
|
|
|
170
1114
|
context "when the criterion are on the same field" do
|
|
171
1115
|
|
|
172
1116
|
let(:selection) do
|
|
173
|
-
query.
|
|
1117
|
+
query.send(tested_method, first: [ 1, 2 ]).send(tested_method, first: [ 3, 4 ])
|
|
174
1118
|
end
|
|
175
1119
|
|
|
176
|
-
|
|
1120
|
+
it_behaves_like 'returns a cloned query'
|
|
1121
|
+
|
|
1122
|
+
it "appends both $or/$nor expressions" do
|
|
177
1123
|
expect(selection.selector).to eq({
|
|
178
|
-
|
|
1124
|
+
expected_operator => [
|
|
179
1125
|
{ "first" => [ 1, 2 ] },
|
|
180
1126
|
{ "first" => [ 3, 4 ] }
|
|
181
1127
|
]
|
|
182
1128
|
})
|
|
183
1129
|
end
|
|
1130
|
+
end
|
|
1131
|
+
end
|
|
1132
|
+
|
|
1133
|
+
context 'when giving multiple conditions in one call on the same key with symbol operator' do
|
|
1134
|
+
|
|
1135
|
+
context 'non-regexp argument' do
|
|
1136
|
+
let(:selection) do
|
|
1137
|
+
query.send(tested_method, field: 1, :field.gt => 0)
|
|
1138
|
+
end
|
|
1139
|
+
|
|
1140
|
+
it 'combines conditions with $eq' do
|
|
1141
|
+
selection.selector.should == {
|
|
1142
|
+
expected_operator => [
|
|
1143
|
+
'field' => {'$eq' => 1, '$gt' => 0},
|
|
1144
|
+
]
|
|
1145
|
+
}
|
|
1146
|
+
end
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
context 'regexp argument' do
|
|
1150
|
+
let(:selection) do
|
|
1151
|
+
query.send(tested_method, field: /t/, :field.gt => 0)
|
|
1152
|
+
end
|
|
184
1153
|
|
|
185
|
-
it
|
|
186
|
-
|
|
1154
|
+
it 'combines conditions with $regex' do
|
|
1155
|
+
selection.selector.should == {
|
|
1156
|
+
expected_operator => [
|
|
1157
|
+
'field' => {'$regex' => /t/, '$gt' => 0},
|
|
1158
|
+
]
|
|
1159
|
+
}
|
|
187
1160
|
end
|
|
188
1161
|
end
|
|
1162
|
+
|
|
189
1163
|
end
|
|
190
1164
|
end
|
|
191
1165
|
|
|
192
1166
|
describe "#or" do
|
|
193
1167
|
|
|
194
|
-
|
|
1168
|
+
let(:tested_method) { :or }
|
|
1169
|
+
let(:expected_operator) { '$or' }
|
|
1170
|
+
|
|
1171
|
+
it_behaves_like '$or/$nor'
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
describe "#nor" do
|
|
1175
|
+
|
|
1176
|
+
let(:tested_method) { :nor }
|
|
1177
|
+
let(:expected_operator) { '$nor' }
|
|
1178
|
+
|
|
1179
|
+
it_behaves_like '$or/$nor'
|
|
1180
|
+
end
|
|
1181
|
+
|
|
1182
|
+
describe "#any_of" do
|
|
1183
|
+
|
|
1184
|
+
let(:tested_method) { :any_of }
|
|
1185
|
+
let(:expected_operator) { '$or' }
|
|
1186
|
+
|
|
1187
|
+
it_behaves_like 'a hoisting logical operation'
|
|
1188
|
+
|
|
1189
|
+
# When multiple arguments are given to any_of, it behaves differently
|
|
1190
|
+
# from and.
|
|
1191
|
+
context 'when argument is a mix of Criteria and hashes' do
|
|
1192
|
+
let(:query) do
|
|
1193
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
1194
|
+
end
|
|
1195
|
+
|
|
1196
|
+
let(:other1) do
|
|
1197
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
let(:other2) do
|
|
1201
|
+
{bar: 42}
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
let(:other3) do
|
|
1205
|
+
Mongoid::Query.new.where(a: 2)
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1208
|
+
let(:result) { query.send(tested_method, other1, other2, other3) }
|
|
1209
|
+
|
|
1210
|
+
it 'combines' do
|
|
1211
|
+
expect(result.selector).to eq(
|
|
1212
|
+
'hello' => 'world',
|
|
1213
|
+
expected_operator => [
|
|
1214
|
+
{'foo' => 'bar'},
|
|
1215
|
+
{'bar' => 42},
|
|
1216
|
+
{'a' => 2},
|
|
1217
|
+
],
|
|
1218
|
+
)
|
|
1219
|
+
end
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
context "when provided no arguments" do
|
|
195
1223
|
|
|
196
1224
|
let(:selection) do
|
|
197
|
-
query.
|
|
1225
|
+
query.any_of
|
|
198
1226
|
end
|
|
199
1227
|
|
|
200
|
-
|
|
1228
|
+
it_behaves_like 'returns a cloned query'
|
|
1229
|
+
|
|
1230
|
+
it "does not add any criteria" do
|
|
201
1231
|
expect(selection.selector).to eq({})
|
|
202
1232
|
end
|
|
203
1233
|
|
|
204
1234
|
it "returns the query" do
|
|
205
1235
|
expect(selection).to eq(query)
|
|
206
1236
|
end
|
|
207
|
-
|
|
208
|
-
it "returns a cloned query" do
|
|
209
|
-
expect(selection).to_not equal(query)
|
|
210
|
-
end
|
|
211
1237
|
end
|
|
212
1238
|
|
|
213
1239
|
context "when provided nil" do
|
|
214
1240
|
|
|
215
1241
|
let(:selection) do
|
|
216
|
-
query.
|
|
1242
|
+
query.any_of(nil)
|
|
217
1243
|
end
|
|
218
1244
|
|
|
219
|
-
|
|
1245
|
+
it_behaves_like 'returns a cloned query'
|
|
1246
|
+
|
|
1247
|
+
it "does not add any criteria" do
|
|
220
1248
|
expect(selection.selector).to eq({})
|
|
221
1249
|
end
|
|
222
1250
|
|
|
223
1251
|
it "returns the query" do
|
|
224
1252
|
expect(selection).to eq(query)
|
|
225
1253
|
end
|
|
226
|
-
|
|
227
|
-
it "returns a cloned query" do
|
|
228
|
-
expect(selection).to_not equal(query)
|
|
229
|
-
end
|
|
230
1254
|
end
|
|
231
1255
|
|
|
232
1256
|
context "when provided a single criterion" do
|
|
233
1257
|
|
|
234
1258
|
let(:selection) do
|
|
235
|
-
query.
|
|
1259
|
+
query.any_of(field: [ 1, 2 ])
|
|
236
1260
|
end
|
|
237
1261
|
|
|
238
|
-
|
|
239
|
-
expect(selection.selector).to eq({
|
|
240
|
-
"$or" => [{ "field" => [ 1, 2 ] }]
|
|
241
|
-
})
|
|
242
|
-
end
|
|
1262
|
+
it_behaves_like 'returns a cloned query'
|
|
243
1263
|
|
|
244
|
-
it "
|
|
245
|
-
expect(selection).
|
|
1264
|
+
it "adds the $or selector" do
|
|
1265
|
+
expect(selection.selector).to eq(
|
|
1266
|
+
"field" => [ 1, 2 ],
|
|
1267
|
+
)
|
|
246
1268
|
end
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
context "when provided multiple criterion" do
|
|
250
1269
|
|
|
251
|
-
context
|
|
1270
|
+
context 'when the criterion is wrapped in array' do
|
|
252
1271
|
|
|
253
1272
|
let(:selection) do
|
|
254
|
-
query.
|
|
1273
|
+
query.any_of([{ field: [ 1, 2 ] }])
|
|
255
1274
|
end
|
|
256
1275
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
})
|
|
1276
|
+
it_behaves_like 'returns a cloned query'
|
|
1277
|
+
|
|
1278
|
+
it "adds the condition" do
|
|
1279
|
+
expect(selection.selector).to eq(
|
|
1280
|
+
"field" => [ 1, 2 ],
|
|
1281
|
+
)
|
|
264
1282
|
end
|
|
265
1283
|
|
|
266
|
-
|
|
267
|
-
|
|
1284
|
+
context 'when the array has nil as one of the elements' do
|
|
1285
|
+
|
|
1286
|
+
let(:selection) do
|
|
1287
|
+
query.any_of([{ field: [ 1, 2 ] }, nil])
|
|
1288
|
+
end
|
|
1289
|
+
|
|
1290
|
+
it_behaves_like 'returns a cloned query'
|
|
1291
|
+
|
|
1292
|
+
it "adds the $or selector ignoring the nil element" do
|
|
1293
|
+
expect(selection.selector).to eq(
|
|
1294
|
+
"field" => [ 1, 2 ],
|
|
1295
|
+
)
|
|
1296
|
+
end
|
|
268
1297
|
end
|
|
269
1298
|
end
|
|
270
1299
|
|
|
271
|
-
context
|
|
1300
|
+
context 'when query already has a condition on another field' do
|
|
272
1301
|
|
|
273
|
-
|
|
274
|
-
query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
|
|
275
|
-
end
|
|
1302
|
+
context 'when there is one argument' do
|
|
276
1303
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
1304
|
+
let(:selection) do
|
|
1305
|
+
query.where(foo: 'bar').any_of(field: [ 1, 2 ])
|
|
1306
|
+
end
|
|
1307
|
+
|
|
1308
|
+
it 'adds the new condition' do
|
|
1309
|
+
expect(selection.selector).to eq(
|
|
1310
|
+
'foo' => 'bar',
|
|
1311
|
+
'field' => [1, 2],
|
|
1312
|
+
)
|
|
1313
|
+
end
|
|
284
1314
|
end
|
|
285
1315
|
|
|
286
|
-
|
|
287
|
-
|
|
1316
|
+
context 'when there are multiple arguments' do
|
|
1317
|
+
|
|
1318
|
+
let(:selection) do
|
|
1319
|
+
query.where(foo: 'bar').any_of({field: [ 1, 2 ]}, {hello: 'world'})
|
|
1320
|
+
end
|
|
1321
|
+
|
|
1322
|
+
it 'adds the new condition' do
|
|
1323
|
+
expect(selection.selector).to eq(
|
|
1324
|
+
'foo' => 'bar',
|
|
1325
|
+
'$or' => [
|
|
1326
|
+
{'field' => [1, 2]},
|
|
1327
|
+
{'hello' => 'world'},
|
|
1328
|
+
],
|
|
1329
|
+
)
|
|
1330
|
+
end
|
|
288
1331
|
end
|
|
289
1332
|
end
|
|
290
1333
|
|
|
291
|
-
context
|
|
1334
|
+
context 'when query already has an $or condition and another condition' do
|
|
292
1335
|
|
|
293
1336
|
let(:selection) do
|
|
294
|
-
query.or(
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
it "adds the $or selector and aliases the field" do
|
|
298
|
-
expect(selection.selector).to eq({
|
|
299
|
-
"$or" => [ { "_id" => 1 } ]
|
|
300
|
-
})
|
|
1337
|
+
query.or(field: [ 1, 2 ]).where(foo: 'bar').any_of(test: 1)
|
|
301
1338
|
end
|
|
302
1339
|
|
|
303
|
-
it
|
|
304
|
-
expect(selection).
|
|
1340
|
+
it 'adds the new condition' do
|
|
1341
|
+
expect(selection.selector).to eq(
|
|
1342
|
+
'$or' => [{'field' => [1, 2]}],
|
|
1343
|
+
'foo' => 'bar',
|
|
1344
|
+
'test' => 1,
|
|
1345
|
+
)
|
|
305
1346
|
end
|
|
306
1347
|
end
|
|
1348
|
+
end
|
|
307
1349
|
|
|
308
|
-
|
|
1350
|
+
context "when provided multiple criteria" do
|
|
1351
|
+
|
|
1352
|
+
context "when the criteria are for different fields" do
|
|
309
1353
|
|
|
310
1354
|
let(:selection) do
|
|
311
|
-
query.
|
|
1355
|
+
query.any_of({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
312
1356
|
end
|
|
313
1357
|
|
|
1358
|
+
it_behaves_like 'returns a cloned query'
|
|
1359
|
+
|
|
314
1360
|
it "adds the $or selector" do
|
|
315
1361
|
expect(selection.selector).to eq({
|
|
316
1362
|
"$or" => [
|
|
317
1363
|
{ "first" => [ 1, 2 ] },
|
|
318
|
-
{ "second" =>
|
|
1364
|
+
{ "second" => [ 3, 4 ] }
|
|
319
1365
|
]
|
|
320
1366
|
})
|
|
321
1367
|
end
|
|
322
|
-
|
|
323
|
-
it "returns a cloned query" do
|
|
324
|
-
expect(selection).to_not equal(query)
|
|
325
|
-
end
|
|
326
1368
|
end
|
|
327
1369
|
|
|
328
|
-
context "when the
|
|
1370
|
+
context "when the criteria uses a Key instance" do
|
|
329
1371
|
|
|
330
1372
|
let(:selection) do
|
|
331
|
-
query.
|
|
1373
|
+
query.any_of({ first: [ 1, 2 ] }, { :second.gt => 3 })
|
|
332
1374
|
end
|
|
333
1375
|
|
|
334
|
-
it "
|
|
1376
|
+
it "adds the $or selector" do
|
|
335
1377
|
expect(selection.selector).to eq({
|
|
336
1378
|
"$or" => [
|
|
337
1379
|
{ "first" => [ 1, 2 ] },
|
|
338
|
-
{ "
|
|
1380
|
+
{ "second" => { "$gt" => 3 }}
|
|
339
1381
|
]
|
|
340
1382
|
})
|
|
341
1383
|
end
|
|
342
1384
|
|
|
343
|
-
|
|
344
|
-
expect(selection).to_not equal(query)
|
|
345
|
-
end
|
|
1385
|
+
it_behaves_like 'returns a cloned query'
|
|
346
1386
|
end
|
|
347
|
-
end
|
|
348
1387
|
|
|
349
|
-
|
|
1388
|
+
context 'when criteria are simple and handled via Key' do
|
|
1389
|
+
shared_examples_for 'adds conditions with $or' do
|
|
350
1390
|
|
|
351
|
-
|
|
1391
|
+
it "adds conditions with $or" do
|
|
1392
|
+
expect(selection.selector).to eq({
|
|
1393
|
+
'$or' => [
|
|
1394
|
+
{'field' => 3},
|
|
1395
|
+
{'field' => {'$lt' => 5}},
|
|
1396
|
+
],
|
|
1397
|
+
})
|
|
1398
|
+
end
|
|
352
1399
|
|
|
353
|
-
|
|
354
|
-
query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
|
|
1400
|
+
it_behaves_like 'returns a cloned query'
|
|
355
1401
|
end
|
|
356
1402
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
1403
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
1404
|
+
|
|
1405
|
+
it "combines conditions with $eq" do
|
|
1406
|
+
expect(selection.selector).to eq({
|
|
1407
|
+
'field' => {
|
|
1408
|
+
'$eq' => 3,
|
|
1409
|
+
'$lt' => 5,
|
|
1410
|
+
},
|
|
1411
|
+
})
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
it_behaves_like 'returns a cloned query'
|
|
364
1415
|
end
|
|
365
1416
|
|
|
366
|
-
|
|
367
|
-
|
|
1417
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
1418
|
+
|
|
1419
|
+
it "combines conditions with $regex" do
|
|
1420
|
+
expect(selection.selector).to eq({
|
|
1421
|
+
'field' => {
|
|
1422
|
+
'$regex' => /t/,
|
|
1423
|
+
'$lt' => 5,
|
|
1424
|
+
},
|
|
1425
|
+
})
|
|
1426
|
+
end
|
|
1427
|
+
|
|
1428
|
+
it_behaves_like 'returns a cloned query'
|
|
368
1429
|
end
|
|
369
|
-
end
|
|
370
1430
|
|
|
371
|
-
|
|
1431
|
+
context 'criteria are provided in the same hash' do
|
|
1432
|
+
context 'non-regexp argument' do
|
|
1433
|
+
let(:selection) do
|
|
1434
|
+
query.send(tested_method, :field => 3, :field.lt => 5)
|
|
1435
|
+
end
|
|
372
1436
|
|
|
373
|
-
|
|
374
|
-
|
|
1437
|
+
it_behaves_like 'combines conditions with $eq'
|
|
1438
|
+
end
|
|
1439
|
+
|
|
1440
|
+
context 'regexp argument' do
|
|
1441
|
+
let(:selection) do
|
|
1442
|
+
query.send(tested_method, :field => /t/, :field.lt => 5)
|
|
1443
|
+
end
|
|
1444
|
+
|
|
1445
|
+
it_behaves_like 'combines conditions with $regex'
|
|
1446
|
+
end
|
|
375
1447
|
end
|
|
376
1448
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
})
|
|
1449
|
+
context 'criteria are provided in separate hashes' do
|
|
1450
|
+
let(:selection) do
|
|
1451
|
+
query.send(tested_method, {:field => 3}, {:field.lt => 5})
|
|
1452
|
+
end
|
|
1453
|
+
|
|
1454
|
+
it_behaves_like 'adds conditions with $or'
|
|
384
1455
|
end
|
|
385
1456
|
|
|
386
|
-
|
|
387
|
-
|
|
1457
|
+
context 'when the criterion is wrapped in an array' do
|
|
1458
|
+
let(:selection) do
|
|
1459
|
+
query.send(tested_method, [:field => 3], [:field.lt => 5])
|
|
1460
|
+
end
|
|
1461
|
+
|
|
1462
|
+
it_behaves_like 'adds conditions with $or'
|
|
388
1463
|
end
|
|
389
1464
|
end
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
1465
|
|
|
393
|
-
|
|
1466
|
+
context 'when criteria are handled via Key and simple' do
|
|
1467
|
+
shared_examples_for 'adds conditions with $or' do
|
|
394
1468
|
|
|
395
|
-
|
|
1469
|
+
it "adds conditions with $or" do
|
|
1470
|
+
expect(selection.selector).to eq({
|
|
1471
|
+
'$or' => [
|
|
1472
|
+
{'field' => {'$gt' => 3}},
|
|
1473
|
+
{'field' => 5},
|
|
1474
|
+
],
|
|
1475
|
+
})
|
|
1476
|
+
end
|
|
396
1477
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
end
|
|
1478
|
+
it_behaves_like 'returns a cloned query'
|
|
1479
|
+
end
|
|
400
1480
|
|
|
401
|
-
|
|
402
|
-
expect(selection.selector).to eq({})
|
|
403
|
-
end
|
|
1481
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
404
1482
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
1483
|
+
it "combines conditions with $eq" do
|
|
1484
|
+
expect(selection.selector).to eq(
|
|
1485
|
+
'field' => {'$gt' => 3, '$eq' => 5},
|
|
1486
|
+
)
|
|
1487
|
+
end
|
|
408
1488
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
end
|
|
412
|
-
end
|
|
1489
|
+
it_behaves_like 'returns a cloned query'
|
|
1490
|
+
end
|
|
413
1491
|
|
|
414
|
-
|
|
1492
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
415
1493
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
1494
|
+
it "combines conditions with $regex" do
|
|
1495
|
+
expect(selection.selector).to eq(
|
|
1496
|
+
'field' => {'$gt' => 3, '$regex' => /t/},
|
|
1497
|
+
)
|
|
1498
|
+
end
|
|
419
1499
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
end
|
|
1500
|
+
it_behaves_like 'returns a cloned query'
|
|
1501
|
+
end
|
|
423
1502
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
1503
|
+
context 'criteria are provided in the same hash' do
|
|
1504
|
+
context 'non-regexp argument' do
|
|
1505
|
+
let(:selection) do
|
|
1506
|
+
query.send(tested_method, :field.gt => 3, :field => 5)
|
|
1507
|
+
end
|
|
427
1508
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
end
|
|
431
|
-
end
|
|
1509
|
+
it_behaves_like 'combines conditions with $eq'
|
|
1510
|
+
end
|
|
432
1511
|
|
|
433
|
-
|
|
1512
|
+
context 'regexp argument' do
|
|
1513
|
+
let(:selection) do
|
|
1514
|
+
query.send(tested_method, :field.gt => 3, :field => /t/)
|
|
1515
|
+
end
|
|
434
1516
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
1517
|
+
it_behaves_like 'combines conditions with $regex'
|
|
1518
|
+
end
|
|
1519
|
+
end
|
|
438
1520
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
end
|
|
1521
|
+
context 'criteria are provided in separate hashes' do
|
|
1522
|
+
let(:selection) do
|
|
1523
|
+
query.send(tested_method, {:field.gt => 3}, {:field => 5})
|
|
1524
|
+
end
|
|
444
1525
|
|
|
445
|
-
|
|
446
|
-
|
|
1526
|
+
it_behaves_like 'adds conditions with $or'
|
|
1527
|
+
end
|
|
1528
|
+
|
|
1529
|
+
context 'when the criterion is wrapped in an array' do
|
|
1530
|
+
let(:selection) do
|
|
1531
|
+
query.send(tested_method, [:field.gt => 3], [:field => 5])
|
|
1532
|
+
end
|
|
1533
|
+
|
|
1534
|
+
it_behaves_like 'adds conditions with $or'
|
|
1535
|
+
end
|
|
447
1536
|
end
|
|
448
|
-
end
|
|
449
1537
|
|
|
450
|
-
|
|
1538
|
+
context "when a criterion has an aliased field" do
|
|
1539
|
+
|
|
1540
|
+
let(:selection) do
|
|
1541
|
+
query.any_of({ id: 1 })
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
it "adds the $or selector and aliases the field" do
|
|
1545
|
+
expect(selection.selector).to eq(
|
|
1546
|
+
"_id" => 1,
|
|
1547
|
+
)
|
|
1548
|
+
end
|
|
1549
|
+
|
|
1550
|
+
it_behaves_like 'returns a cloned query'
|
|
1551
|
+
end
|
|
451
1552
|
|
|
452
|
-
context "when
|
|
1553
|
+
context "when a criterion is wrapped in an array" do
|
|
453
1554
|
|
|
454
1555
|
let(:selection) do
|
|
455
|
-
query.
|
|
1556
|
+
query.any_of([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
|
456
1557
|
end
|
|
457
1558
|
|
|
458
|
-
|
|
1559
|
+
it_behaves_like 'returns a cloned query'
|
|
1560
|
+
|
|
1561
|
+
it "adds the $or selector" do
|
|
459
1562
|
expect(selection.selector).to eq({
|
|
460
|
-
"$
|
|
1563
|
+
"$or" => [
|
|
461
1564
|
{ "first" => [ 1, 2 ] },
|
|
462
|
-
{ "second" =>
|
|
1565
|
+
{ "second" => { "$gt" => 3 }}
|
|
463
1566
|
]
|
|
464
1567
|
})
|
|
465
1568
|
end
|
|
466
|
-
|
|
467
|
-
it "returns a cloned query" do
|
|
468
|
-
expect(selection).to_not equal(query)
|
|
469
|
-
end
|
|
470
1569
|
end
|
|
471
1570
|
|
|
472
|
-
context "when the
|
|
1571
|
+
context "when the criteria are on the same field" do
|
|
473
1572
|
|
|
474
1573
|
let(:selection) do
|
|
475
|
-
query.
|
|
1574
|
+
query.any_of({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
476
1575
|
end
|
|
477
1576
|
|
|
478
|
-
|
|
1577
|
+
it_behaves_like 'returns a cloned query'
|
|
1578
|
+
|
|
1579
|
+
it "appends both $or expressions" do
|
|
479
1580
|
expect(selection.selector).to eq({
|
|
480
|
-
"$
|
|
1581
|
+
"$or" => [
|
|
481
1582
|
{ "first" => [ 1, 2 ] },
|
|
482
1583
|
{ "first" => [ 3, 4 ] }
|
|
483
1584
|
]
|
|
484
1585
|
})
|
|
485
1586
|
end
|
|
486
|
-
|
|
487
|
-
it "returns a cloned query" do
|
|
488
|
-
expect(selection).to_not equal(query)
|
|
489
|
-
end
|
|
490
1587
|
end
|
|
491
1588
|
end
|
|
492
1589
|
|
|
493
|
-
context "when chaining the
|
|
1590
|
+
context "when chaining the criteria" do
|
|
494
1591
|
|
|
495
|
-
context "when the
|
|
1592
|
+
context "when the criteria are for different fields" do
|
|
496
1593
|
|
|
497
1594
|
let(:selection) do
|
|
498
|
-
query.
|
|
1595
|
+
query.any_of(first: [ 1, 2 ]).any_of(second: [ 3, 4 ])
|
|
499
1596
|
end
|
|
500
1597
|
|
|
501
|
-
|
|
502
|
-
expect(selection.selector).to eq({
|
|
503
|
-
"$nor" => [
|
|
504
|
-
{ "first" => [ 1, 2 ] },
|
|
505
|
-
{ "second" => [ 3, 4 ] }
|
|
506
|
-
]
|
|
507
|
-
})
|
|
508
|
-
end
|
|
1598
|
+
it_behaves_like 'returns a cloned query'
|
|
509
1599
|
|
|
510
|
-
it "
|
|
511
|
-
expect(selection).
|
|
1600
|
+
it "adds the conditions separately" do
|
|
1601
|
+
expect(selection.selector).to eq(
|
|
1602
|
+
"first" => [ 1, 2 ],
|
|
1603
|
+
"second" => [ 3, 4 ],
|
|
1604
|
+
)
|
|
512
1605
|
end
|
|
513
1606
|
end
|
|
514
1607
|
|
|
515
|
-
context "when the
|
|
1608
|
+
context "when the criteria are on the same field" do
|
|
516
1609
|
|
|
517
1610
|
let(:selection) do
|
|
518
|
-
query.
|
|
1611
|
+
query.any_of(first: [ 1, 2 ]).any_of(first: [ 3, 4 ])
|
|
519
1612
|
end
|
|
520
1613
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
]
|
|
527
|
-
|
|
1614
|
+
it_behaves_like 'returns a cloned query'
|
|
1615
|
+
|
|
1616
|
+
it "adds the conditions separately" do
|
|
1617
|
+
expect(selection.selector).to eq(
|
|
1618
|
+
"first" => [ 1, 2 ],
|
|
1619
|
+
'$and' => [{"first" => [ 3, 4 ]}],
|
|
1620
|
+
)
|
|
1621
|
+
end
|
|
1622
|
+
end
|
|
1623
|
+
end
|
|
1624
|
+
|
|
1625
|
+
context 'when using multiple criteria and symbol operators' do
|
|
1626
|
+
context 'when using fields that meaningfully evolve values' do
|
|
1627
|
+
|
|
1628
|
+
let(:query) do
|
|
1629
|
+
Dictionary.any_of({a: 1}, :published.gt => Date.new(2020, 2, 3))
|
|
1630
|
+
end
|
|
1631
|
+
|
|
1632
|
+
it 'generates the expected query' do
|
|
1633
|
+
query.selector.should == {'$or' => [
|
|
1634
|
+
{'a' => 1},
|
|
1635
|
+
# Date instance is converted to a Time instance in local time,
|
|
1636
|
+
# because we are querying on a Time field and dates are interpreted
|
|
1637
|
+
# in local time when assigning to Time fields
|
|
1638
|
+
{'published' => {'$gt' => Time.local(2020, 2, 3)}},
|
|
1639
|
+
]}
|
|
1640
|
+
end
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
context 'when using fields that do not meaningfully evolve values' do
|
|
1644
|
+
|
|
1645
|
+
let(:query) do
|
|
1646
|
+
Dictionary.any_of({a: 1}, :submitted_on.gt => Date.new(2020, 2, 3))
|
|
528
1647
|
end
|
|
529
1648
|
|
|
530
|
-
it
|
|
531
|
-
|
|
1649
|
+
it 'generates the expected query' do
|
|
1650
|
+
query.selector.should == {'$or' => [
|
|
1651
|
+
{'a' => 1},
|
|
1652
|
+
# Date instance is converted to a Time instance in UTC,
|
|
1653
|
+
# because we are querying on a Date field and dates are interpreted
|
|
1654
|
+
# in UTC when persisted as dates by Mongoid
|
|
1655
|
+
{'submitted_on' => {'$gt' => Time.utc(2020, 2, 3)}},
|
|
1656
|
+
]}
|
|
532
1657
|
end
|
|
533
1658
|
end
|
|
534
1659
|
end
|
|
@@ -561,27 +1686,45 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
561
1686
|
expect(query.negating).to be nil
|
|
562
1687
|
end
|
|
563
1688
|
|
|
564
|
-
|
|
565
|
-
|
|
1689
|
+
shared_examples_for 'negates the next condition' do
|
|
566
1690
|
let(:selection) do
|
|
567
|
-
query.not.
|
|
1691
|
+
query.not.send(query_method, field: [ 1, 2 ])
|
|
568
1692
|
end
|
|
569
1693
|
|
|
570
|
-
it "negates the
|
|
1694
|
+
it "negates the next condition" do
|
|
571
1695
|
expect(selection.selector).to eq(
|
|
572
|
-
{ "field" => { "$not" => {
|
|
1696
|
+
{ "field" => { "$not" => { operator => [ 1, 2 ] }}}
|
|
573
1697
|
)
|
|
574
1698
|
end
|
|
575
1699
|
|
|
576
|
-
|
|
577
|
-
expect(selection).to_not equal(query)
|
|
578
|
-
end
|
|
1700
|
+
it_behaves_like 'returns a cloned query'
|
|
579
1701
|
|
|
580
1702
|
it "removes the negation on the clone" do
|
|
581
1703
|
expect(selection).to_not be_negating
|
|
582
1704
|
end
|
|
583
1705
|
end
|
|
584
1706
|
|
|
1707
|
+
context "when the next condition is #all" do
|
|
1708
|
+
let(:query_method) { :all }
|
|
1709
|
+
let(:operator) { '$all' }
|
|
1710
|
+
|
|
1711
|
+
it_behaves_like 'negates the next condition'
|
|
1712
|
+
end
|
|
1713
|
+
|
|
1714
|
+
context "when the next condition is #in" do
|
|
1715
|
+
let(:query_method) { :in }
|
|
1716
|
+
let(:operator) { '$in' }
|
|
1717
|
+
|
|
1718
|
+
it_behaves_like 'negates the next condition'
|
|
1719
|
+
end
|
|
1720
|
+
|
|
1721
|
+
context "when the next condition is #nin" do
|
|
1722
|
+
let(:query_method) { :nin }
|
|
1723
|
+
let(:operator) { '$nin' }
|
|
1724
|
+
|
|
1725
|
+
it_behaves_like 'negates the next condition'
|
|
1726
|
+
end
|
|
1727
|
+
|
|
585
1728
|
context "when the following criteria is a gt method" do
|
|
586
1729
|
|
|
587
1730
|
let(:selection) do
|
|
@@ -594,10 +1737,27 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
594
1737
|
)
|
|
595
1738
|
end
|
|
596
1739
|
|
|
597
|
-
|
|
598
|
-
|
|
1740
|
+
it_behaves_like 'returns a cloned query'
|
|
1741
|
+
|
|
1742
|
+
it "removes the negation on the clone" do
|
|
1743
|
+
expect(selection).to_not be_negating
|
|
1744
|
+
end
|
|
1745
|
+
end
|
|
1746
|
+
|
|
1747
|
+
context "when the criteria uses Key" do
|
|
1748
|
+
|
|
1749
|
+
let(:selection) do
|
|
1750
|
+
query.not(:age.gt => 50)
|
|
1751
|
+
end
|
|
1752
|
+
|
|
1753
|
+
it "negates the gt selection" do
|
|
1754
|
+
expect(selection.selector).to eq(
|
|
1755
|
+
'$and' => ['$nor' => ['age' => {'$gt' => 50}]]
|
|
1756
|
+
)
|
|
599
1757
|
end
|
|
600
1758
|
|
|
1759
|
+
it_behaves_like 'returns a cloned query'
|
|
1760
|
+
|
|
601
1761
|
it "removes the negation on the clone" do
|
|
602
1762
|
expect(selection).to_not be_negating
|
|
603
1763
|
end
|
|
@@ -615,9 +1775,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
615
1775
|
)
|
|
616
1776
|
end
|
|
617
1777
|
|
|
618
|
-
|
|
619
|
-
expect(selection).to_not equal(query)
|
|
620
|
-
end
|
|
1778
|
+
it_behaves_like 'returns a cloned query'
|
|
621
1779
|
|
|
622
1780
|
it "removes the negation on the clone" do
|
|
623
1781
|
expect(selection).to_not be_negating
|
|
@@ -636,10 +1794,27 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
636
1794
|
)
|
|
637
1795
|
end
|
|
638
1796
|
|
|
639
|
-
|
|
640
|
-
|
|
1797
|
+
it_behaves_like 'returns a cloned query'
|
|
1798
|
+
|
|
1799
|
+
it "removes the negation on the clone" do
|
|
1800
|
+
expect(selection).to_not be_negating
|
|
1801
|
+
end
|
|
1802
|
+
end
|
|
1803
|
+
|
|
1804
|
+
context 'when the following criteria uses string were form' do
|
|
1805
|
+
|
|
1806
|
+
let(:selection) do
|
|
1807
|
+
query.not.where('hello world')
|
|
1808
|
+
end
|
|
1809
|
+
|
|
1810
|
+
it "negates the selection with an operator" do
|
|
1811
|
+
expect(selection.selector).to eq(
|
|
1812
|
+
'$and' => [{'$nor' => [{'$where' => 'hello world'}]}]
|
|
1813
|
+
)
|
|
641
1814
|
end
|
|
642
1815
|
|
|
1816
|
+
it_behaves_like 'returns a cloned query'
|
|
1817
|
+
|
|
643
1818
|
it "removes the negation on the clone" do
|
|
644
1819
|
expect(selection).to_not be_negating
|
|
645
1820
|
end
|
|
@@ -661,9 +1836,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
661
1836
|
expect(selection).to eq(query)
|
|
662
1837
|
end
|
|
663
1838
|
|
|
664
|
-
|
|
665
|
-
expect(selection).to_not equal(query)
|
|
666
|
-
end
|
|
1839
|
+
it_behaves_like 'returns a cloned query'
|
|
667
1840
|
end
|
|
668
1841
|
|
|
669
1842
|
context "when provided a single criterion" do
|
|
@@ -678,14 +1851,31 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
678
1851
|
})
|
|
679
1852
|
end
|
|
680
1853
|
|
|
681
|
-
|
|
682
|
-
|
|
1854
|
+
it_behaves_like 'returns a cloned query'
|
|
1855
|
+
end
|
|
1856
|
+
|
|
1857
|
+
context "when negating a field in the original selector" do
|
|
1858
|
+
let(:query) do
|
|
1859
|
+
Mongoid::Query.new("id" => "_id").where(field: 'foo')
|
|
1860
|
+
end
|
|
1861
|
+
|
|
1862
|
+
let(:selection) do
|
|
1863
|
+
query.not(field: 'bar')
|
|
1864
|
+
end
|
|
1865
|
+
|
|
1866
|
+
it "combines the conditions" do
|
|
1867
|
+
expect(selection.selector).to eq({
|
|
1868
|
+
"field" => 'foo',
|
|
1869
|
+
'$and' => [{'$nor' => [{ "field" => 'bar' }]}],
|
|
1870
|
+
})
|
|
683
1871
|
end
|
|
1872
|
+
|
|
1873
|
+
it_behaves_like 'returns a cloned query'
|
|
684
1874
|
end
|
|
685
1875
|
|
|
686
|
-
context "when provided multiple
|
|
1876
|
+
context "when provided multiple criteria" do
|
|
687
1877
|
|
|
688
|
-
context "when the
|
|
1878
|
+
context "when the criteria are for different fields" do
|
|
689
1879
|
|
|
690
1880
|
let(:selection) do
|
|
691
1881
|
query.not(first: /1/, second: /2/)
|
|
@@ -698,9 +1888,23 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
698
1888
|
})
|
|
699
1889
|
end
|
|
700
1890
|
|
|
701
|
-
|
|
702
|
-
|
|
1891
|
+
it_behaves_like 'returns a cloned query'
|
|
1892
|
+
end
|
|
1893
|
+
|
|
1894
|
+
context "when the criteria are given in separate arguments" do
|
|
1895
|
+
|
|
1896
|
+
let(:selection) do
|
|
1897
|
+
query.not({first: /1/}, {second: /2/})
|
|
1898
|
+
end
|
|
1899
|
+
|
|
1900
|
+
it "adds the $not selectors" do
|
|
1901
|
+
expect(selection.selector).to eq({
|
|
1902
|
+
"first" => { "$not" => /1/ },
|
|
1903
|
+
"second" => { "$not" => /2/ }
|
|
1904
|
+
})
|
|
703
1905
|
end
|
|
1906
|
+
|
|
1907
|
+
it_behaves_like 'returns a cloned query'
|
|
704
1908
|
end
|
|
705
1909
|
end
|
|
706
1910
|
|
|
@@ -719,9 +1923,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
719
1923
|
})
|
|
720
1924
|
end
|
|
721
1925
|
|
|
722
|
-
|
|
723
|
-
expect(selection).to_not equal(query)
|
|
724
|
-
end
|
|
1926
|
+
it_behaves_like 'returns a cloned query'
|
|
725
1927
|
end
|
|
726
1928
|
|
|
727
1929
|
context "when the criterion are on the same field" do
|
|
@@ -730,15 +1932,14 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
730
1932
|
query.not(first: /1/).not(first: /2/)
|
|
731
1933
|
end
|
|
732
1934
|
|
|
733
|
-
it "
|
|
734
|
-
expect(selection.selector).to eq(
|
|
735
|
-
"first" => { "$not" => /
|
|
736
|
-
|
|
1935
|
+
it "combines conditions" do
|
|
1936
|
+
expect(selection.selector).to eq(
|
|
1937
|
+
"first" => { "$not" => /1/ },
|
|
1938
|
+
'$and' => [{'$nor' => [{'first' => /2/}]}],
|
|
1939
|
+
)
|
|
737
1940
|
end
|
|
738
1941
|
|
|
739
|
-
|
|
740
|
-
expect(selection).to_not equal(query)
|
|
741
|
-
end
|
|
1942
|
+
it_behaves_like 'returns a cloned query'
|
|
742
1943
|
end
|
|
743
1944
|
|
|
744
1945
|
context "when the criterion are a double negative" do
|
|
@@ -753,8 +1954,115 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
753
1954
|
})
|
|
754
1955
|
end
|
|
755
1956
|
|
|
756
|
-
|
|
757
|
-
|
|
1957
|
+
it_behaves_like 'returns a cloned query'
|
|
1958
|
+
end
|
|
1959
|
+
end
|
|
1960
|
+
|
|
1961
|
+
context 'when argument is a Criteria' do
|
|
1962
|
+
let(:query) do
|
|
1963
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
1964
|
+
end
|
|
1965
|
+
|
|
1966
|
+
let(:other) do
|
|
1967
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
1968
|
+
end
|
|
1969
|
+
|
|
1970
|
+
let(:result) { query.not(other) }
|
|
1971
|
+
|
|
1972
|
+
it 'combines' do
|
|
1973
|
+
expect(result.selector).to eq('hello' => 'world', 'foo' => {'$ne' => 'bar'})
|
|
1974
|
+
end
|
|
1975
|
+
end
|
|
1976
|
+
|
|
1977
|
+
context 'when argument is a simple Criteria with multiple fields' do
|
|
1978
|
+
let(:query) do
|
|
1979
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
1980
|
+
end
|
|
1981
|
+
|
|
1982
|
+
let(:other) do
|
|
1983
|
+
Mongoid::Query.new.where(a: 1, b: 2)
|
|
1984
|
+
end
|
|
1985
|
+
|
|
1986
|
+
let(:result) { query.not(other) }
|
|
1987
|
+
|
|
1988
|
+
it 'combines fields into top level criteria' do
|
|
1989
|
+
expect(result.selector).to eq('hello' => 'world',
|
|
1990
|
+
'a' => {'$ne' => 1}, 'b' => {'$ne' => 2})
|
|
1991
|
+
end
|
|
1992
|
+
end
|
|
1993
|
+
|
|
1994
|
+
context 'when argument is a complex Criteria' do
|
|
1995
|
+
let(:query) do
|
|
1996
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
1997
|
+
end
|
|
1998
|
+
|
|
1999
|
+
let(:other) do
|
|
2000
|
+
Mongoid::Query.new.where('$nor' => [{a: 1, b: 2}])
|
|
2001
|
+
end
|
|
2002
|
+
|
|
2003
|
+
let(:result) { query.not(other) }
|
|
2004
|
+
|
|
2005
|
+
it 'combines with $and of $nor' do
|
|
2006
|
+
expect(result.selector).to eq('hello' => 'world', '$and' => [{'$nor' => [{
|
|
2007
|
+
'$nor' => [{'a' => 1, 'b' => 2}]}]}])
|
|
2008
|
+
end
|
|
2009
|
+
end
|
|
2010
|
+
|
|
2011
|
+
context 'when argument is a mix of Criteria and hashes' do
|
|
2012
|
+
let(:query) do
|
|
2013
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
2014
|
+
end
|
|
2015
|
+
|
|
2016
|
+
let(:other1) do
|
|
2017
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
2018
|
+
end
|
|
2019
|
+
|
|
2020
|
+
let(:other2) do
|
|
2021
|
+
{bar: 42}
|
|
2022
|
+
end
|
|
2023
|
+
|
|
2024
|
+
let(:other3) do
|
|
2025
|
+
Mongoid::Query.new.where(a: 2)
|
|
2026
|
+
end
|
|
2027
|
+
|
|
2028
|
+
let(:result) { query.not(other1, other2, other3) }
|
|
2029
|
+
|
|
2030
|
+
it 'combines' do
|
|
2031
|
+
expect(result.selector).to eq('hello' => 'world',
|
|
2032
|
+
'foo' => {'$ne' => 'bar'},
|
|
2033
|
+
'bar' => {'$ne' => 42},
|
|
2034
|
+
'a' => {'$ne' => 2},
|
|
2035
|
+
)
|
|
2036
|
+
end
|
|
2037
|
+
end
|
|
2038
|
+
|
|
2039
|
+
context 'when giving multiple conditions in one call on the same key with symbol operator' do
|
|
2040
|
+
|
|
2041
|
+
context 'non-regexp argument' do
|
|
2042
|
+
let(:selection) do
|
|
2043
|
+
query.not(field: 1, :field.gt => 0)
|
|
2044
|
+
end
|
|
2045
|
+
|
|
2046
|
+
it 'combines conditions with $eq' do
|
|
2047
|
+
selection.selector.should == {
|
|
2048
|
+
'$and' => ['$nor' => [
|
|
2049
|
+
'field' => {'$eq' => 1, '$gt' => 0},
|
|
2050
|
+
]]
|
|
2051
|
+
}
|
|
2052
|
+
end
|
|
2053
|
+
end
|
|
2054
|
+
|
|
2055
|
+
context 'regexp argument' do
|
|
2056
|
+
let(:selection) do
|
|
2057
|
+
query.not(field: /t/, :field.gt => 0)
|
|
2058
|
+
end
|
|
2059
|
+
|
|
2060
|
+
it 'combines conditions with $regex' do
|
|
2061
|
+
selection.selector.should == {
|
|
2062
|
+
'$and' => ['$nor' => [
|
|
2063
|
+
'field' => {'$regex' => /t/, '$gt' => 0},
|
|
2064
|
+
]]
|
|
2065
|
+
}
|
|
758
2066
|
end
|
|
759
2067
|
end
|
|
760
2068
|
end
|