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