mongoid 7.0.13 → 8.0.8
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 +43 -0
- data/lib/config/locales/en.yml +178 -95
- data/lib/mongoid/association/accessors.rb +175 -83
- data/lib/mongoid/association/bindable.rb +57 -28
- data/lib/mongoid/association/builders.rb +8 -14
- data/lib/mongoid/association/constrainable.rb +5 -7
- data/lib/mongoid/association/depending.rb +9 -18
- data/lib/mongoid/association/eager_loadable.rb +31 -10
- data/lib/mongoid/association/embedded/batchable.rb +67 -53
- data/lib/mongoid/association/embedded/cyclic.rb +10 -17
- data/lib/mongoid/association/embedded/embedded_in/binding.rb +27 -9
- 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 +9 -28
- data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -8
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +8 -5
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +143 -122
- data/lib/mongoid/association/embedded/embeds_many.rb +8 -36
- data/lib/mongoid/association/embedded/embeds_one/binding.rb +4 -8
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +26 -9
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +63 -29
- data/lib/mongoid/association/embedded/embeds_one.rb +9 -33
- data/lib/mongoid/association/embedded.rb +2 -0
- data/lib/mongoid/association/macros.rb +71 -41
- data/lib/mongoid/association/many.rb +25 -35
- data/lib/mongoid/association/marshalable.rb +3 -6
- data/lib/mongoid/association/nested/many.rb +22 -30
- data/lib/mongoid/association/nested/nested_buildable.rb +9 -15
- data/lib/mongoid/association/nested/one.rb +19 -30
- data/lib/mongoid/association/nested.rb +3 -3
- data/lib/mongoid/association/one.rb +5 -12
- data/lib/mongoid/association/options.rb +16 -46
- data/lib/mongoid/association/proxy.rb +37 -38
- data/lib/mongoid/association/referenced/auto_save.rb +9 -14
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +5 -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 +19 -31
- data/lib/mongoid/association/referenced/belongs_to.rb +16 -38
- data/lib/mongoid/association/referenced/counter_cache.rb +14 -25
- data/lib/mongoid/association/referenced/eager.rb +41 -40
- 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 +105 -68
- data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +29 -46
- 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 +440 -456
- data/lib/mongoid/association/referenced/has_many/proxy.rb +101 -124
- data/lib/mongoid/association/referenced/has_many.rb +21 -45
- 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 +16 -29
- data/lib/mongoid/association/referenced/has_one/proxy.rb +25 -30
- data/lib/mongoid/association/referenced/has_one.rb +16 -36
- data/lib/mongoid/association/referenced/syncable.rb +11 -26
- data/lib/mongoid/association/referenced.rb +2 -0
- data/lib/mongoid/association/reflections.rb +7 -6
- data/lib/mongoid/association/relatable.rb +62 -84
- data/lib/mongoid/association.rb +13 -27
- data/lib/mongoid/atomic/modifiers.rb +29 -53
- data/lib/mongoid/atomic/paths/embedded/many.rb +23 -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 +45 -51
- data/lib/mongoid/attributes/dynamic.rb +6 -21
- data/lib/mongoid/attributes/nested.rb +11 -14
- data/lib/mongoid/attributes/processing.rb +46 -30
- data/lib/mongoid/attributes/projector.rb +119 -0
- data/lib/mongoid/attributes/readonly.rb +5 -8
- data/lib/mongoid/attributes.rb +80 -98
- data/lib/mongoid/cacheable.rb +7 -10
- data/lib/mongoid/changeable.rb +49 -70
- data/lib/mongoid/clients/factory.rb +42 -17
- data/lib/mongoid/clients/options.rb +15 -14
- data/lib/mongoid/clients/sessions.rb +4 -20
- data/lib/mongoid/clients/storage_options.rb +7 -12
- data/lib/mongoid/clients/validators/storage.rb +5 -12
- 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 +30 -5
- data/lib/mongoid/config/options.rb +23 -23
- data/lib/mongoid/config/validators/client.rb +8 -23
- data/lib/mongoid/config/validators/option.rb +2 -3
- data/lib/mongoid/config/validators.rb +2 -1
- data/lib/mongoid/config.rb +164 -48
- data/lib/mongoid/contextual/aggregable/memory.rb +40 -27
- data/lib/mongoid/contextual/aggregable/mongo.rb +32 -33
- 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 +13 -44
- data/lib/mongoid/contextual/map_reduce.rb +7 -35
- data/lib/mongoid/contextual/memory.rb +187 -81
- data/lib/mongoid/contextual/mongo.rb +360 -239
- data/lib/mongoid/contextual/none.rb +109 -31
- data/lib/mongoid/contextual/queryable.rb +3 -4
- data/lib/mongoid/contextual.rb +9 -11
- data/lib/mongoid/copyable.rb +42 -17
- data/lib/mongoid/criteria/findable.rb +19 -19
- data/lib/mongoid/criteria/includable.rb +30 -33
- data/lib/mongoid/criteria/inspectable.rb +2 -3
- data/lib/mongoid/criteria/marshalable.rb +12 -7
- data/lib/mongoid/criteria/modifiable.rb +2 -19
- data/lib/mongoid/criteria/options.rb +2 -3
- data/lib/mongoid/criteria/permission.rb +3 -2
- data/lib/mongoid/criteria/queryable/aggregable.rb +4 -15
- data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
- data/lib/mongoid/criteria/queryable/extensions/array.rb +7 -41
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +28 -8
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +5 -6
- data/lib/mongoid/criteria/queryable/extensions/date.rb +9 -9
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +11 -12
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +4 -41
- data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -14
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -21
- data/lib/mongoid/criteria/queryable/extensions/object.rb +6 -30
- data/lib/mongoid/criteria/queryable/extensions/range.rb +49 -17
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +9 -16
- data/lib/mongoid/criteria/queryable/extensions/set.rb +4 -5
- data/lib/mongoid/criteria/queryable/extensions/string.rb +7 -32
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +7 -22
- data/lib/mongoid/criteria/queryable/extensions/time.rb +9 -9
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +9 -9
- data/lib/mongoid/criteria/queryable/extensions.rb +1 -4
- data/lib/mongoid/criteria/queryable/key.rb +39 -24
- data/lib/mongoid/criteria/queryable/macroable.rb +3 -4
- data/lib/mongoid/criteria/queryable/mergeable.rb +200 -40
- data/lib/mongoid/criteria/queryable/optional.rb +10 -59
- data/lib/mongoid/criteria/queryable/options.rb +4 -21
- data/lib/mongoid/criteria/queryable/pipeline.rb +5 -15
- data/lib/mongoid/criteria/queryable/selectable.rb +417 -171
- data/lib/mongoid/criteria/queryable/selector.rb +127 -30
- data/lib/mongoid/criteria/queryable/smash.rb +42 -18
- data/lib/mongoid/criteria/queryable/storable.rb +237 -0
- data/lib/mongoid/criteria/queryable.rb +18 -15
- data/lib/mongoid/criteria/scopable.rb +29 -21
- data/lib/mongoid/criteria/translator.rb +45 -0
- data/lib/mongoid/criteria.rb +95 -107
- data/lib/mongoid/deprecable.rb +37 -0
- data/lib/mongoid/deprecation.rb +25 -0
- data/lib/mongoid/document.rb +148 -97
- data/lib/mongoid/equality.rb +35 -18
- 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 +35 -21
- 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 +3 -4
- data/lib/mongoid/errors/invalid_dependent_strategy.rb +3 -4
- data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
- data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -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 +8 -7
- 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_field_type.rb +26 -0
- 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 +5 -10
- 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 +3 -4
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -3
- data/lib/mongoid/errors/invalid_time.rb +2 -3
- 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 +6 -13
- 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 +3 -4
- data/lib/mongoid/errors/no_client_hosts.rb +3 -4
- 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 +3 -4
- 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 +3 -1
- data/lib/mongoid/errors/unknown_attribute.rb +3 -4
- 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 +14 -3
- data/lib/mongoid/evolvable.rb +4 -5
- data/lib/mongoid/extensions/array.rb +37 -44
- data/lib/mongoid/extensions/big_decimal.rb +35 -21
- data/lib/mongoid/extensions/binary.rb +42 -0
- data/lib/mongoid/extensions/boolean.rb +10 -6
- data/lib/mongoid/extensions/date.rb +32 -25
- data/lib/mongoid/extensions/date_time.rb +5 -13
- data/lib/mongoid/extensions/decimal128.rb +2 -5
- data/lib/mongoid/extensions/false_class.rb +5 -8
- data/lib/mongoid/extensions/float.rb +12 -14
- data/lib/mongoid/extensions/hash.rb +87 -45
- data/lib/mongoid/extensions/integer.rb +12 -16
- data/lib/mongoid/extensions/module.rb +3 -4
- data/lib/mongoid/extensions/nil_class.rb +2 -5
- data/lib/mongoid/extensions/object.rb +25 -50
- data/lib/mongoid/extensions/object_id.rb +2 -7
- data/lib/mongoid/extensions/range.rb +42 -20
- data/lib/mongoid/extensions/regexp.rb +13 -7
- data/lib/mongoid/extensions/set.rb +13 -11
- data/lib/mongoid/extensions/string.rb +30 -61
- data/lib/mongoid/extensions/symbol.rb +6 -22
- data/lib/mongoid/extensions/time.rb +37 -23
- data/lib/mongoid/extensions/time_with_zone.rb +26 -9
- data/lib/mongoid/extensions/true_class.rb +5 -8
- data/lib/mongoid/extensions.rb +19 -3
- data/lib/mongoid/factory.rb +104 -17
- data/lib/mongoid/fields/foreign_key.rb +14 -26
- data/lib/mongoid/fields/localized.rb +11 -15
- data/lib/mongoid/fields/standard.rb +13 -43
- data/lib/mongoid/fields/validators/macro.rb +32 -20
- data/lib/mongoid/fields/validators.rb +2 -1
- data/lib/mongoid/fields.rb +328 -85
- data/lib/mongoid/findable.rb +90 -33
- data/lib/mongoid/indexable/specification.rb +5 -18
- data/lib/mongoid/indexable/validators/options.rb +8 -9
- data/lib/mongoid/indexable.rb +6 -21
- data/lib/mongoid/inspectable.rb +4 -11
- data/lib/mongoid/interceptable.rb +191 -41
- data/lib/mongoid/loggable.rb +13 -16
- data/lib/mongoid/matchable.rb +3 -154
- 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 +130 -0
- data/lib/mongoid/persistable/creatable.rb +22 -30
- data/lib/mongoid/persistable/deletable.rb +6 -22
- data/lib/mongoid/persistable/destroyable.rb +12 -11
- 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 +5 -10
- data/lib/mongoid/persistable/settable.rb +3 -6
- data/lib/mongoid/persistable/unsettable.rb +9 -9
- data/lib/mongoid/persistable/updatable.rb +50 -31
- data/lib/mongoid/persistable/upsertable.rb +5 -10
- data/lib/mongoid/persistable.rb +135 -40
- data/lib/mongoid/persistence_context.rb +85 -45
- data/lib/mongoid/positional.rb +2 -5
- data/lib/mongoid/query_cache.rb +13 -280
- data/lib/mongoid/railtie.rb +3 -16
- data/lib/mongoid/railties/controller_runtime.rb +4 -2
- data/lib/mongoid/railties/database.rake +9 -0
- data/lib/mongoid/reloadable.rb +19 -22
- data/lib/mongoid/scopable.rb +34 -57
- data/lib/mongoid/selectable.rb +8 -18
- data/lib/mongoid/serializable.rb +33 -34
- data/lib/mongoid/shardable.rb +108 -21
- data/lib/mongoid/stateful.rb +38 -19
- data/lib/mongoid/stringified_symbol.rb +52 -0
- data/lib/mongoid/tasks/database.rake +12 -5
- data/lib/mongoid/tasks/database.rb +85 -7
- data/lib/mongoid/threaded/lifecycle.rb +7 -26
- data/lib/mongoid/threaded.rb +44 -67
- data/lib/mongoid/timestamps/created/short.rb +2 -1
- data/lib/mongoid/timestamps/created.rb +4 -3
- 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 +5 -6
- data/lib/mongoid/timestamps.rb +3 -2
- data/lib/mongoid/touchable.rb +54 -25
- data/lib/mongoid/traversable.rb +185 -61
- data/lib/mongoid/validatable/associated.rb +99 -22
- data/lib/mongoid/validatable/format.rb +2 -1
- data/lib/mongoid/validatable/length.rb +2 -1
- data/lib/mongoid/validatable/localizable.rb +3 -4
- data/lib/mongoid/validatable/macros.rb +2 -9
- data/lib/mongoid/validatable/presence.rb +10 -15
- data/lib/mongoid/validatable/queryable.rb +2 -3
- data/lib/mongoid/validatable/uniqueness.rb +29 -41
- data/lib/mongoid/validatable.rb +22 -33
- data/lib/mongoid/version.rb +2 -2
- data/lib/mongoid/warnings.rb +28 -0
- data/lib/mongoid.rb +34 -15
- data/lib/rails/generators/mongoid/config/config_generator.rb +2 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +53 -32
- 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 +17 -0
- data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
- data/spec/integration/app_spec.rb +31 -27
- data/spec/integration/associations/belongs_to_spec.rb +20 -0
- data/spec/integration/associations/embedded_dirty_spec.rb +57 -0
- data/spec/integration/associations/embedded_spec.rb +162 -55
- data/spec/integration/associations/embeds_many_spec.rb +219 -0
- data/spec/integration/associations/embeds_one_spec.rb +41 -0
- data/spec/integration/associations/foreign_key_spec.rb +107 -0
- data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
- data/spec/integration/associations/has_and_belongs_to_many_spec.rb +61 -0
- data/spec/integration/associations/has_many_spec.rb +128 -0
- data/spec/integration/associations/has_one_spec.rb +272 -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 +107 -1
- data/spec/integration/callbacks_spec.rb +262 -8
- 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 +359 -0
- data/spec/integration/criteria/time_with_zone_spec.rb +125 -15
- data/spec/integration/discriminator_key_spec.rb +392 -0
- data/spec/integration/discriminator_value_spec.rb +206 -0
- data/spec/integration/document_spec.rb +30 -1
- data/spec/integration/dots_and_dollars_spec.rb +277 -0
- data/spec/integration/i18n_fallbacks_spec.rb +73 -0
- data/spec/integration/{matchable_spec.rb → matcher_examples_spec.rb} +130 -45
- 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 +41 -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 +122 -0
- data/spec/integration/matcher_spec.rb +283 -0
- data/spec/integration/persistence/range_field_spec.rb +350 -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 +18 -6
- 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 +35 -33
- data/spec/mongoid/association/depending_spec.rb +431 -338
- data/spec/mongoid/association/eager_spec.rb +8 -5
- 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 +4 -1
- data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +56 -0
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +84 -22
- 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 +114 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +687 -173
- data/spec/mongoid/association/embedded/embeds_many_models.rb +174 -1
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +63 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +71 -1
- data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +2 -0
- data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +27 -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 +22 -0
- data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +31 -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 +4 -1
- data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +111 -16
- data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +242 -12
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +114 -58
- data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
- data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +26 -3
- 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 +418 -361
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +68 -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 +81 -4
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +3 -1
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +132 -0
- data/spec/mongoid/association/referenced/has_many/eager_spec.rb +40 -9
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +314 -133
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +848 -451
- data/spec/mongoid/association/referenced/has_many_models.rb +61 -1
- data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
- data/spec/mongoid/association/referenced/has_many_spec.rb +48 -0
- data/spec/mongoid/association/referenced/has_one/binding_spec.rb +2 -0
- data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +55 -9
- data/spec/mongoid/association/referenced/has_one/eager_spec.rb +34 -4
- data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +135 -27
- data/spec/mongoid/association/referenced/has_one_models.rb +65 -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 +47 -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 +66 -26
- data/spec/mongoid/atomic_spec.rb +53 -6
- data/spec/mongoid/attributes/dynamic_spec.rb +0 -1
- data/spec/mongoid/attributes/nested_spec.rb +149 -78
- data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
- 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 +40 -0
- data/spec/mongoid/attributes/readonly_spec.rb +24 -22
- data/spec/mongoid/attributes_spec.rb +683 -65
- data/spec/mongoid/cacheable_spec.rb +6 -4
- data/spec/mongoid/changeable_spec.rb +185 -43
- data/spec/mongoid/clients/factory_spec.rb +128 -28
- data/spec/mongoid/clients/options_spec.rb +45 -26
- data/spec/mongoid/clients/sessions_spec.rb +25 -66
- data/spec/mongoid/clients/transactions_spec.rb +54 -29
- data/spec/mongoid/clients_spec.rb +65 -8
- data/spec/mongoid/composable_spec.rb +2 -0
- data/spec/mongoid/config/environment_spec.rb +126 -8
- data/spec/mongoid/config/options_spec.rb +22 -3
- data/spec/mongoid/config_spec.rb +377 -1
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +433 -153
- data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
- data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
- data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
- data/spec/mongoid/contextual/atomic_spec.rb +205 -67
- data/spec/mongoid/contextual/geo_near_spec.rb +20 -18
- data/spec/mongoid/contextual/map_reduce_spec.rb +6 -18
- data/spec/mongoid/contextual/memory_spec.rb +1360 -91
- data/spec/mongoid/contextual/mongo_spec.rb +1871 -544
- data/spec/mongoid/contextual/none_spec.rb +39 -73
- data/spec/mongoid/copyable_spec.rb +657 -26
- data/spec/mongoid/copyable_spec_models.rb +30 -0
- data/spec/mongoid/criteria/findable_spec.rb +161 -228
- data/spec/mongoid/criteria/includable_spec.rb +1492 -0
- data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
- data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +20 -1
- 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 +9 -19
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +136 -26
- 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 +13 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +46 -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 -15
- 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 +73 -8
- 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 -59
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -59
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +34 -16
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +13 -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 +18 -485
- 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 +1643 -286
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1191 -2752
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
- data/spec/mongoid/criteria/queryable/selector_spec.rb +91 -4
- data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
- data/spec/mongoid/criteria/queryable/storable_spec.rb +298 -0
- data/spec/mongoid/criteria/scopable_spec.rb +129 -0
- data/spec/mongoid/criteria/translator_spec.rb +132 -0
- data/spec/mongoid/criteria_projection_spec.rb +409 -0
- data/spec/mongoid/criteria_spec.rb +1322 -1723
- data/spec/mongoid/document_fields_spec.rb +179 -5
- 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 +153 -87
- 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 +78 -0
- data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
- data/spec/mongoid/errors/{eager_load_spec.rb → invalid_config_file_spec.rb} +7 -5
- 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 +3 -1
- data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -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 +24 -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 +5 -3
- 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 +3 -1
- 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 +41 -45
- data/spec/mongoid/extensions/big_decimal_spec.rb +714 -212
- data/spec/mongoid/extensions/binary_spec.rb +46 -9
- data/spec/mongoid/extensions/boolean_spec.rb +70 -82
- data/spec/mongoid/extensions/date_class_mongoize_spec.rb +339 -0
- data/spec/mongoid/extensions/date_spec.rb +58 -140
- data/spec/mongoid/extensions/date_time_spec.rb +32 -69
- 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 +66 -73
- data/spec/mongoid/extensions/hash_spec.rb +138 -3
- data/spec/mongoid/extensions/integer_spec.rb +61 -63
- 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 +257 -54
- data/spec/mongoid/extensions/regexp_spec.rb +60 -33
- data/spec/mongoid/extensions/set_spec.rb +108 -0
- data/spec/mongoid/extensions/string_spec.rb +111 -50
- data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
- data/spec/mongoid/extensions/symbol_spec.rb +20 -25
- data/spec/mongoid/extensions/time_spec.rb +663 -66
- data/spec/mongoid/extensions/time_with_zone_spec.rb +50 -31
- data/spec/mongoid/extensions/true_class_spec.rb +3 -1
- data/spec/mongoid/extensions_spec.rb +16 -2
- data/spec/mongoid/factory_spec.rb +347 -27
- data/spec/mongoid/fields/foreign_key_spec.rb +2 -0
- data/spec/mongoid/fields/localized_spec.rb +43 -16
- data/spec/mongoid/fields/standard_spec.rb +2 -0
- data/spec/mongoid/fields_spec.rb +776 -80
- data/spec/mongoid/findable_spec.rb +133 -34
- data/spec/mongoid/indexable/specification_spec.rb +4 -2
- data/spec/mongoid/indexable_spec.rb +65 -18
- data/spec/mongoid/inspectable_spec.rb +39 -2
- data/spec/mongoid/interceptable_spec.rb +955 -103
- data/spec/mongoid/interceptable_spec_models.rb +307 -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 +36 -0
- data/spec/mongoid/mongoizable_spec.rb +285 -0
- data/spec/mongoid/persistable/creatable_spec.rb +114 -29
- data/spec/mongoid/persistable/deletable_spec.rb +274 -12
- data/spec/mongoid/persistable/destroyable_spec.rb +202 -12
- 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 +24 -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 +18 -2
- data/spec/mongoid/persistable_spec.rb +85 -9
- data/spec/mongoid/persistence_context_spec.rb +52 -1
- data/spec/mongoid/positional_spec.rb +2 -0
- data/spec/mongoid/query_cache_middleware_spec.rb +50 -0
- data/spec/mongoid/query_cache_spec.rb +339 -87
- data/spec/mongoid/relations/proxy_spec.rb +8 -6
- data/spec/mongoid/reloadable_spec.rb +357 -22
- data/spec/mongoid/scopable_spec.rb +121 -37
- data/spec/mongoid/selectable_spec.rb +8 -6
- data/spec/mongoid/serializable_spec.rb +160 -29
- data/spec/mongoid/shardable_models.rb +75 -0
- data/spec/mongoid/shardable_spec.rb +239 -34
- data/spec/mongoid/stateful_spec.rb +31 -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 +398 -6
- data/spec/mongoid/timestamps_spec_models.rb +67 -0
- data/spec/mongoid/touchable_spec.rb +296 -33
- data/spec/mongoid/touchable_spec_models.rb +57 -0
- data/spec/mongoid/traversable_spec.rb +1160 -1
- data/spec/mongoid/validatable/associated_spec.rb +15 -30
- 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 +128 -98
- data/spec/mongoid/validatable_spec.rb +5 -3
- data/spec/mongoid/warnings_spec.rb +35 -0
- data/spec/mongoid_spec.rb +3 -1
- data/spec/rails/controller_extension/controller_runtime_spec.rb +5 -3
- data/spec/rails/mongoid_spec.rb +8 -18
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/cluster_config.rb +14 -4
- data/spec/shared/lib/mrss/constraints.rb +51 -27
- data/spec/shared/lib/mrss/docker_runner.rb +37 -4
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +48 -1
- data/spec/shared/lib/mrss/server_version_registry.rb +16 -18
- 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 +18 -1
- data/spec/shared/lib/mrss/utils.rb +28 -6
- data/spec/shared/share/Dockerfile.erb +156 -66
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/config.sh +27 -0
- data/spec/shared/shlib/distro.sh +2 -1
- data/spec/shared/shlib/server.sh +171 -45
- data/spec/shared/shlib/set_env.sh +47 -6
- data/spec/spec_helper.rb +38 -36
- data/spec/support/authorization.rb +2 -0
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/constraints.rb +39 -8
- data/spec/support/expectations.rb +5 -1
- data/spec/support/helpers.rb +11 -0
- data/spec/support/macros.rb +77 -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/support/models/augmentation.rb +25 -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 +9 -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/support/models/catalog.rb +24 -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/support/models/circus.rb +12 -0
- data/spec/{app → support}/models/code.rb +4 -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/{app → support}/models/customer.rb +0 -1
- data/spec/{app → support}/models/customer_address.rb +0 -1
- 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/support/models/fanatic.rb +8 -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 +11 -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 +6 -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 +3 -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 +12 -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 +22 -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 +23 -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 +4 -0
- data/spec/{app → support}/models/post.rb +2 -0
- data/spec/{app → support}/models/post_genre.rb +2 -0
- data/spec/support/models/powerup.rb +25 -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/support/models/purse.rb +9 -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 +3 -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/school.rb +14 -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/support/models/shield.rb +18 -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/support/models/student.rb +14 -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/support/models/weapon.rb +25 -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/schema_maps/schema_map_aws.json +17 -0
- data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
- data/spec/support/schema_maps/schema_map_azure.json +17 -0
- data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
- data/spec/support/schema_maps/schema_map_gcp.json +17 -0
- data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
- data/spec/support/schema_maps/schema_map_kmip.json +17 -0
- data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
- data/spec/support/schema_maps/schema_map_local.json +18 -0
- data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
- data/spec/support/shared/time.rb +53 -0
- data/spec/support/spec_config.rb +12 -3
- data.tar.gz.sig +0 -0
- metadata +1162 -764
- metadata.gz.sig +0 -0
- data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
- data/lib/mongoid/errors/eager_load.rb +0 -22
- data/lib/mongoid/errors/invalid_value.rb +0 -16
- 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/augmentation.rb +0 -11
- data/spec/app/models/bed.rb +0 -1
- data/spec/app/models/car.rb +0 -1
- data/spec/app/models/circus.rb +0 -7
- 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/powerup.rb +0 -11
- 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/app/models/weapon.rb +0 -11
- 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/cluster_config.rb +0 -158
- data/spec/support/session_registry.rb +0 -50
- /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
|
|
124
1003
|
end
|
|
125
1004
|
end
|
|
126
1005
|
|
|
127
|
-
context "when
|
|
1006
|
+
context "when a criterion has an aliased field" do
|
|
128
1007
|
|
|
129
1008
|
let(:selection) do
|
|
130
|
-
query.
|
|
1009
|
+
query.send(tested_method, { id: 1 })
|
|
131
1010
|
end
|
|
132
1011
|
|
|
133
|
-
it "
|
|
1012
|
+
it "adds the $or/$nor selector and aliases the field" do
|
|
134
1013
|
expect(selection.selector).to eq({
|
|
135
|
-
"
|
|
1014
|
+
expected_operator => [ { "_id" => 1 } ]
|
|
1015
|
+
})
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
it_behaves_like 'returns a cloned query'
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
context "when a criterion is wrapped in an array" do
|
|
1022
|
+
|
|
1023
|
+
let(:selection) do
|
|
1024
|
+
query.send(tested_method, [{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
|
1025
|
+
end
|
|
1026
|
+
|
|
1027
|
+
it_behaves_like 'returns a cloned query'
|
|
1028
|
+
|
|
1029
|
+
it "adds the $or/$nor selector" do
|
|
1030
|
+
expect(selection.selector).to eq({
|
|
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
|
|
141
1073
|
|
|
142
|
-
|
|
143
|
-
|
|
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
|
|
1078
|
+
|
|
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,211 +1095,296 @@ 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
1268
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
context "when the criterion are for different fields" do
|
|
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
|
-
expect(selection.selector).to eq({
|
|
259
|
-
"$or" => [
|
|
260
|
-
{ "first" => [ 1, 2 ] },
|
|
261
|
-
{ "second" => [ 3, 4 ] }
|
|
262
|
-
]
|
|
263
|
-
})
|
|
264
|
-
end
|
|
1275
|
+
it_behaves_like 'returns a cloned query'
|
|
265
1276
|
|
|
266
|
-
it "
|
|
267
|
-
expect(selection).
|
|
1277
|
+
it "adds the condition" do
|
|
1278
|
+
expect(selection.selector).to eq(
|
|
1279
|
+
"field" => [ 1, 2 ],
|
|
1280
|
+
)
|
|
268
1281
|
end
|
|
269
|
-
end
|
|
270
1282
|
|
|
271
|
-
|
|
1283
|
+
context 'when the array has nil as one of the elements' do
|
|
272
1284
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
1285
|
+
let(:selection) do
|
|
1286
|
+
query.any_of([{ field: [ 1, 2 ] }, nil])
|
|
1287
|
+
end
|
|
276
1288
|
|
|
277
|
-
|
|
278
|
-
expect(selection.selector).to eq({
|
|
279
|
-
"$or" => [
|
|
280
|
-
{ "first" => [ 1, 2 ] },
|
|
281
|
-
{ "second" => { "$gt" => 3 }}
|
|
282
|
-
]
|
|
283
|
-
})
|
|
284
|
-
end
|
|
1289
|
+
it_behaves_like 'returns a cloned query'
|
|
285
1290
|
|
|
286
|
-
|
|
287
|
-
|
|
1291
|
+
it "adds the $or selector ignoring the nil element" do
|
|
1292
|
+
expect(selection.selector).to eq(
|
|
1293
|
+
"field" => [ 1, 2 ],
|
|
1294
|
+
)
|
|
1295
|
+
end
|
|
288
1296
|
end
|
|
289
1297
|
end
|
|
290
1298
|
|
|
291
|
-
context
|
|
1299
|
+
context 'when query already has a condition on another field' do
|
|
292
1300
|
|
|
293
|
-
|
|
294
|
-
query.or({ id: 1 })
|
|
295
|
-
end
|
|
1301
|
+
context 'when there is one argument' do
|
|
296
1302
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
|
301
1313
|
end
|
|
302
1314
|
|
|
303
|
-
|
|
304
|
-
|
|
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
|
|
305
1330
|
end
|
|
306
1331
|
end
|
|
307
1332
|
|
|
308
|
-
context
|
|
1333
|
+
context 'when query already has an $or condition and another condition' do
|
|
309
1334
|
|
|
310
1335
|
let(:selection) do
|
|
311
|
-
query.or(
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
it "adds the $or selector" do
|
|
315
|
-
expect(selection.selector).to eq({
|
|
316
|
-
"$or" => [
|
|
317
|
-
{ "first" => [ 1, 2 ] },
|
|
318
|
-
{ "second" => { "$gt" => 3 }}
|
|
319
|
-
]
|
|
320
|
-
})
|
|
1336
|
+
query.or(field: [ 1, 2 ]).where(foo: 'bar').any_of(test: 1)
|
|
321
1337
|
end
|
|
322
1338
|
|
|
323
|
-
it
|
|
324
|
-
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
|
+
)
|
|
325
1345
|
end
|
|
326
1346
|
end
|
|
327
1347
|
|
|
328
|
-
context
|
|
1348
|
+
context 'when any_of has multiple arguments' do
|
|
329
1349
|
|
|
330
1350
|
let(:selection) do
|
|
331
|
-
query.or(
|
|
1351
|
+
query.or(field: [ 1, 2 ]).where(foo: 'bar').any_of({a: 1}, {b: 2})
|
|
332
1352
|
end
|
|
333
1353
|
|
|
334
|
-
it
|
|
335
|
-
expect(selection.selector).to eq(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
})
|
|
1354
|
+
it 'adds the new condition to top level' do
|
|
1355
|
+
expect(selection.selector).to eq(
|
|
1356
|
+
'$or' => [{'field' => [1, 2]}],
|
|
1357
|
+
'foo' => 'bar',
|
|
1358
|
+
'$and' => [{'$or' => [{'a' => 1}, {'b' => 2}]}],
|
|
1359
|
+
)
|
|
341
1360
|
end
|
|
342
1361
|
|
|
343
|
-
|
|
344
|
-
|
|
1362
|
+
context 'when query already has a top-level $and' do
|
|
1363
|
+
let(:selection) do
|
|
1364
|
+
query.or(field: [ 1, 2 ]).where('$and' => [foo: 'bar']).any_of({a: 1}, {b: 2})
|
|
1365
|
+
end
|
|
1366
|
+
|
|
1367
|
+
it 'adds the new condition to top level $and' do
|
|
1368
|
+
expect(selection.selector).to eq(
|
|
1369
|
+
'$or' => [{'field' => [1, 2]}],
|
|
1370
|
+
'$and' => [{'foo' => 'bar'}, {'$or' => [{'a' => 1}, {'b' => 2}]}],
|
|
1371
|
+
)
|
|
1372
|
+
end
|
|
345
1373
|
end
|
|
346
1374
|
end
|
|
347
1375
|
end
|
|
348
1376
|
|
|
349
|
-
context "when
|
|
1377
|
+
context "when provided multiple criteria" do
|
|
350
1378
|
|
|
351
|
-
context "when the
|
|
1379
|
+
context "when the criteria are for different fields" do
|
|
352
1380
|
|
|
353
1381
|
let(:selection) do
|
|
354
|
-
query.
|
|
1382
|
+
query.any_of({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
355
1383
|
end
|
|
356
1384
|
|
|
357
|
-
|
|
1385
|
+
it_behaves_like 'returns a cloned query'
|
|
1386
|
+
|
|
1387
|
+
it "adds the $or selector" do
|
|
358
1388
|
expect(selection.selector).to eq({
|
|
359
1389
|
"$or" => [
|
|
360
1390
|
{ "first" => [ 1, 2 ] },
|
|
@@ -362,173 +1392,295 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
362
1392
|
]
|
|
363
1393
|
})
|
|
364
1394
|
end
|
|
365
|
-
|
|
366
|
-
it "returns a cloned query" do
|
|
367
|
-
expect(selection).to_not equal(query)
|
|
368
|
-
end
|
|
369
1395
|
end
|
|
370
1396
|
|
|
371
|
-
context "when the
|
|
1397
|
+
context "when the criteria uses a Key instance" do
|
|
372
1398
|
|
|
373
1399
|
let(:selection) do
|
|
374
|
-
query.
|
|
1400
|
+
query.any_of({ first: [ 1, 2 ] }, { :second.gt => 3 })
|
|
375
1401
|
end
|
|
376
1402
|
|
|
377
|
-
it "
|
|
1403
|
+
it "adds the $or selector" do
|
|
378
1404
|
expect(selection.selector).to eq({
|
|
379
1405
|
"$or" => [
|
|
380
1406
|
{ "first" => [ 1, 2 ] },
|
|
381
|
-
{ "
|
|
1407
|
+
{ "second" => { "$gt" => 3 }}
|
|
382
1408
|
]
|
|
383
1409
|
})
|
|
384
1410
|
end
|
|
385
1411
|
|
|
386
|
-
|
|
387
|
-
expect(selection).to_not equal(query)
|
|
388
|
-
end
|
|
1412
|
+
it_behaves_like 'returns a cloned query'
|
|
389
1413
|
end
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
1414
|
|
|
393
|
-
|
|
1415
|
+
context 'when criteria are simple and handled via Key' do
|
|
1416
|
+
shared_examples_for 'adds conditions with $or' do
|
|
394
1417
|
|
|
395
|
-
|
|
1418
|
+
it "adds conditions with $or" do
|
|
1419
|
+
expect(selection.selector).to eq({
|
|
1420
|
+
'$or' => [
|
|
1421
|
+
{'field' => 3},
|
|
1422
|
+
{'field' => {'$lt' => 5}},
|
|
1423
|
+
],
|
|
1424
|
+
})
|
|
1425
|
+
end
|
|
396
1426
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
end
|
|
1427
|
+
it_behaves_like 'returns a cloned query'
|
|
1428
|
+
end
|
|
400
1429
|
|
|
401
|
-
|
|
402
|
-
expect(selection.selector).to eq({})
|
|
403
|
-
end
|
|
1430
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
404
1431
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
1432
|
+
it "combines conditions with $eq" do
|
|
1433
|
+
expect(selection.selector).to eq({
|
|
1434
|
+
'field' => {
|
|
1435
|
+
'$eq' => 3,
|
|
1436
|
+
'$lt' => 5,
|
|
1437
|
+
},
|
|
1438
|
+
})
|
|
1439
|
+
end
|
|
408
1440
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
end
|
|
412
|
-
end
|
|
1441
|
+
it_behaves_like 'returns a cloned query'
|
|
1442
|
+
end
|
|
413
1443
|
|
|
414
|
-
|
|
1444
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
415
1445
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
1446
|
+
it "combines conditions with $regex" do
|
|
1447
|
+
expect(selection.selector).to eq({
|
|
1448
|
+
'field' => {
|
|
1449
|
+
'$regex' => /t/,
|
|
1450
|
+
'$lt' => 5,
|
|
1451
|
+
},
|
|
1452
|
+
})
|
|
1453
|
+
end
|
|
419
1454
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
end
|
|
1455
|
+
it_behaves_like 'returns a cloned query'
|
|
1456
|
+
end
|
|
423
1457
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
1458
|
+
context 'criteria are provided in the same hash' do
|
|
1459
|
+
context 'non-regexp argument' do
|
|
1460
|
+
let(:selection) do
|
|
1461
|
+
query.send(tested_method, :field => 3, :field.lt => 5)
|
|
1462
|
+
end
|
|
427
1463
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
end
|
|
431
|
-
end
|
|
1464
|
+
it_behaves_like 'combines conditions with $eq'
|
|
1465
|
+
end
|
|
432
1466
|
|
|
433
|
-
|
|
1467
|
+
context 'regexp argument' do
|
|
1468
|
+
let(:selection) do
|
|
1469
|
+
query.send(tested_method, :field => /t/, :field.lt => 5)
|
|
1470
|
+
end
|
|
434
1471
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
1472
|
+
it_behaves_like 'combines conditions with $regex'
|
|
1473
|
+
end
|
|
1474
|
+
end
|
|
438
1475
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
1476
|
+
context 'criteria are provided in separate hashes' do
|
|
1477
|
+
let(:selection) do
|
|
1478
|
+
query.send(tested_method, {:field => 3}, {:field.lt => 5})
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
it_behaves_like 'adds conditions with $or'
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
context 'when the criterion is wrapped in an array' do
|
|
1485
|
+
let(:selection) do
|
|
1486
|
+
query.send(tested_method, [:field => 3], [:field.lt => 5])
|
|
1487
|
+
end
|
|
1488
|
+
|
|
1489
|
+
it_behaves_like 'adds conditions with $or'
|
|
1490
|
+
end
|
|
443
1491
|
end
|
|
444
1492
|
|
|
445
|
-
|
|
446
|
-
|
|
1493
|
+
context 'when criteria are handled via Key and simple' do
|
|
1494
|
+
shared_examples_for 'adds conditions with $or' do
|
|
1495
|
+
|
|
1496
|
+
it "adds conditions with $or" do
|
|
1497
|
+
expect(selection.selector).to eq({
|
|
1498
|
+
'$or' => [
|
|
1499
|
+
{'field' => {'$gt' => 3}},
|
|
1500
|
+
{'field' => 5},
|
|
1501
|
+
],
|
|
1502
|
+
})
|
|
1503
|
+
end
|
|
1504
|
+
|
|
1505
|
+
it_behaves_like 'returns a cloned query'
|
|
1506
|
+
end
|
|
1507
|
+
|
|
1508
|
+
shared_examples_for 'combines conditions with $eq' do
|
|
1509
|
+
|
|
1510
|
+
it "combines conditions with $eq" do
|
|
1511
|
+
expect(selection.selector).to eq(
|
|
1512
|
+
'field' => {'$gt' => 3, '$eq' => 5},
|
|
1513
|
+
)
|
|
1514
|
+
end
|
|
1515
|
+
|
|
1516
|
+
it_behaves_like 'returns a cloned query'
|
|
1517
|
+
end
|
|
1518
|
+
|
|
1519
|
+
shared_examples_for 'combines conditions with $regex' do
|
|
1520
|
+
|
|
1521
|
+
it "combines conditions with $regex" do
|
|
1522
|
+
expect(selection.selector).to eq(
|
|
1523
|
+
'field' => {'$gt' => 3, '$regex' => /t/},
|
|
1524
|
+
)
|
|
1525
|
+
end
|
|
1526
|
+
|
|
1527
|
+
it_behaves_like 'returns a cloned query'
|
|
1528
|
+
end
|
|
1529
|
+
|
|
1530
|
+
context 'criteria are provided in the same hash' do
|
|
1531
|
+
context 'non-regexp argument' do
|
|
1532
|
+
let(:selection) do
|
|
1533
|
+
query.send(tested_method, :field.gt => 3, :field => 5)
|
|
1534
|
+
end
|
|
1535
|
+
|
|
1536
|
+
it_behaves_like 'combines conditions with $eq'
|
|
1537
|
+
end
|
|
1538
|
+
|
|
1539
|
+
context 'regexp argument' do
|
|
1540
|
+
let(:selection) do
|
|
1541
|
+
query.send(tested_method, :field.gt => 3, :field => /t/)
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
it_behaves_like 'combines conditions with $regex'
|
|
1545
|
+
end
|
|
1546
|
+
end
|
|
1547
|
+
|
|
1548
|
+
context 'criteria are provided in separate hashes' do
|
|
1549
|
+
let(:selection) do
|
|
1550
|
+
query.send(tested_method, {:field.gt => 3}, {:field => 5})
|
|
1551
|
+
end
|
|
1552
|
+
|
|
1553
|
+
it_behaves_like 'adds conditions with $or'
|
|
1554
|
+
end
|
|
1555
|
+
|
|
1556
|
+
context 'when the criterion is wrapped in an array' do
|
|
1557
|
+
let(:selection) do
|
|
1558
|
+
query.send(tested_method, [:field.gt => 3], [:field => 5])
|
|
1559
|
+
end
|
|
1560
|
+
|
|
1561
|
+
it_behaves_like 'adds conditions with $or'
|
|
1562
|
+
end
|
|
447
1563
|
end
|
|
448
|
-
end
|
|
449
1564
|
|
|
450
|
-
|
|
1565
|
+
context "when a criterion has an aliased field" do
|
|
1566
|
+
|
|
1567
|
+
let(:selection) do
|
|
1568
|
+
query.any_of({ id: 1 })
|
|
1569
|
+
end
|
|
1570
|
+
|
|
1571
|
+
it "adds the $or selector and aliases the field" do
|
|
1572
|
+
expect(selection.selector).to eq(
|
|
1573
|
+
"_id" => 1,
|
|
1574
|
+
)
|
|
1575
|
+
end
|
|
1576
|
+
|
|
1577
|
+
it_behaves_like 'returns a cloned query'
|
|
1578
|
+
end
|
|
451
1579
|
|
|
452
|
-
context "when
|
|
1580
|
+
context "when a criterion is wrapped in an array" do
|
|
453
1581
|
|
|
454
1582
|
let(:selection) do
|
|
455
|
-
query.
|
|
1583
|
+
query.any_of([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
|
456
1584
|
end
|
|
457
1585
|
|
|
458
|
-
|
|
1586
|
+
it_behaves_like 'returns a cloned query'
|
|
1587
|
+
|
|
1588
|
+
it "adds the $or selector" do
|
|
459
1589
|
expect(selection.selector).to eq({
|
|
460
|
-
"$
|
|
1590
|
+
"$or" => [
|
|
461
1591
|
{ "first" => [ 1, 2 ] },
|
|
462
|
-
{ "second" =>
|
|
1592
|
+
{ "second" => { "$gt" => 3 }}
|
|
463
1593
|
]
|
|
464
1594
|
})
|
|
465
1595
|
end
|
|
466
|
-
|
|
467
|
-
it "returns a cloned query" do
|
|
468
|
-
expect(selection).to_not equal(query)
|
|
469
|
-
end
|
|
470
1596
|
end
|
|
471
1597
|
|
|
472
|
-
context "when the
|
|
1598
|
+
context "when the criteria are on the same field" do
|
|
473
1599
|
|
|
474
1600
|
let(:selection) do
|
|
475
|
-
query.
|
|
1601
|
+
query.any_of({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
476
1602
|
end
|
|
477
1603
|
|
|
478
|
-
|
|
1604
|
+
it_behaves_like 'returns a cloned query'
|
|
1605
|
+
|
|
1606
|
+
it "appends both $or expressions" do
|
|
479
1607
|
expect(selection.selector).to eq({
|
|
480
|
-
"$
|
|
1608
|
+
"$or" => [
|
|
481
1609
|
{ "first" => [ 1, 2 ] },
|
|
482
1610
|
{ "first" => [ 3, 4 ] }
|
|
483
1611
|
]
|
|
484
1612
|
})
|
|
485
1613
|
end
|
|
486
|
-
|
|
487
|
-
it "returns a cloned query" do
|
|
488
|
-
expect(selection).to_not equal(query)
|
|
489
|
-
end
|
|
490
1614
|
end
|
|
491
1615
|
end
|
|
492
1616
|
|
|
493
|
-
context "when chaining the
|
|
1617
|
+
context "when chaining the criteria" do
|
|
494
1618
|
|
|
495
|
-
context "when the
|
|
1619
|
+
context "when the criteria are for different fields" do
|
|
496
1620
|
|
|
497
1621
|
let(:selection) do
|
|
498
|
-
query.
|
|
1622
|
+
query.any_of(first: [ 1, 2 ]).any_of(second: [ 3, 4 ])
|
|
499
1623
|
end
|
|
500
1624
|
|
|
501
|
-
|
|
502
|
-
expect(selection.selector).to eq({
|
|
503
|
-
"$nor" => [
|
|
504
|
-
{ "first" => [ 1, 2 ] },
|
|
505
|
-
{ "second" => [ 3, 4 ] }
|
|
506
|
-
]
|
|
507
|
-
})
|
|
508
|
-
end
|
|
1625
|
+
it_behaves_like 'returns a cloned query'
|
|
509
1626
|
|
|
510
|
-
it "
|
|
511
|
-
expect(selection).
|
|
1627
|
+
it "adds the conditions separately" do
|
|
1628
|
+
expect(selection.selector).to eq(
|
|
1629
|
+
"first" => [ 1, 2 ],
|
|
1630
|
+
"second" => [ 3, 4 ],
|
|
1631
|
+
)
|
|
512
1632
|
end
|
|
513
1633
|
end
|
|
514
1634
|
|
|
515
|
-
context "when the
|
|
1635
|
+
context "when the criteria are on the same field" do
|
|
516
1636
|
|
|
517
1637
|
let(:selection) do
|
|
518
|
-
query.
|
|
1638
|
+
query.any_of(first: [ 1, 2 ]).any_of(first: [ 3, 4 ])
|
|
519
1639
|
end
|
|
520
1640
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
]
|
|
527
|
-
|
|
1641
|
+
it_behaves_like 'returns a cloned query'
|
|
1642
|
+
|
|
1643
|
+
it "adds the conditions separately" do
|
|
1644
|
+
expect(selection.selector).to eq(
|
|
1645
|
+
"first" => [ 1, 2 ],
|
|
1646
|
+
'$and' => [{"first" => [ 3, 4 ]}],
|
|
1647
|
+
)
|
|
1648
|
+
end
|
|
1649
|
+
end
|
|
1650
|
+
end
|
|
1651
|
+
|
|
1652
|
+
context 'when using multiple criteria and symbol operators' do
|
|
1653
|
+
context 'when using fields that meaningfully evolve values' do
|
|
1654
|
+
|
|
1655
|
+
let(:query) do
|
|
1656
|
+
Dictionary.any_of({a: 1}, :published.gt => Date.new(2020, 2, 3))
|
|
1657
|
+
end
|
|
1658
|
+
|
|
1659
|
+
it 'generates the expected query' do
|
|
1660
|
+
query.selector.should == {'$or' => [
|
|
1661
|
+
{'a' => 1},
|
|
1662
|
+
# Date instance is converted to a Time instance in local time,
|
|
1663
|
+
# because we are querying on a Time field and dates are interpreted
|
|
1664
|
+
# in local time when assigning to Time fields
|
|
1665
|
+
{'published' => {'$gt' => Time.local(2020, 2, 3)}},
|
|
1666
|
+
]}
|
|
1667
|
+
end
|
|
1668
|
+
end
|
|
1669
|
+
|
|
1670
|
+
context 'when using fields that do not meaningfully evolve values' do
|
|
1671
|
+
|
|
1672
|
+
let(:query) do
|
|
1673
|
+
Dictionary.any_of({a: 1}, :submitted_on.gt => Date.new(2020, 2, 3))
|
|
528
1674
|
end
|
|
529
1675
|
|
|
530
|
-
it
|
|
531
|
-
|
|
1676
|
+
it 'generates the expected query' do
|
|
1677
|
+
query.selector.should == {'$or' => [
|
|
1678
|
+
{'a' => 1},
|
|
1679
|
+
# Date instance is converted to a Time instance in UTC,
|
|
1680
|
+
# because we are querying on a Date field and dates are interpreted
|
|
1681
|
+
# in UTC when persisted as dates by Mongoid
|
|
1682
|
+
{'submitted_on' => {'$gt' => Time.utc(2020, 2, 3)}},
|
|
1683
|
+
]}
|
|
532
1684
|
end
|
|
533
1685
|
end
|
|
534
1686
|
end
|
|
@@ -561,27 +1713,45 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
561
1713
|
expect(query.negating).to be nil
|
|
562
1714
|
end
|
|
563
1715
|
|
|
564
|
-
|
|
565
|
-
|
|
1716
|
+
shared_examples_for 'negates the next condition' do
|
|
566
1717
|
let(:selection) do
|
|
567
|
-
query.not.
|
|
1718
|
+
query.not.send(query_method, field: [ 1, 2 ])
|
|
568
1719
|
end
|
|
569
1720
|
|
|
570
|
-
it "negates the
|
|
1721
|
+
it "negates the next condition" do
|
|
571
1722
|
expect(selection.selector).to eq(
|
|
572
|
-
{ "field" => { "$not" => {
|
|
1723
|
+
{ "field" => { "$not" => { operator => [ 1, 2 ] }}}
|
|
573
1724
|
)
|
|
574
1725
|
end
|
|
575
1726
|
|
|
576
|
-
|
|
577
|
-
expect(selection).to_not equal(query)
|
|
578
|
-
end
|
|
1727
|
+
it_behaves_like 'returns a cloned query'
|
|
579
1728
|
|
|
580
1729
|
it "removes the negation on the clone" do
|
|
581
1730
|
expect(selection).to_not be_negating
|
|
582
1731
|
end
|
|
583
1732
|
end
|
|
584
1733
|
|
|
1734
|
+
context "when the next condition is #all" do
|
|
1735
|
+
let(:query_method) { :all }
|
|
1736
|
+
let(:operator) { '$all' }
|
|
1737
|
+
|
|
1738
|
+
it_behaves_like 'negates the next condition'
|
|
1739
|
+
end
|
|
1740
|
+
|
|
1741
|
+
context "when the next condition is #in" do
|
|
1742
|
+
let(:query_method) { :in }
|
|
1743
|
+
let(:operator) { '$in' }
|
|
1744
|
+
|
|
1745
|
+
it_behaves_like 'negates the next condition'
|
|
1746
|
+
end
|
|
1747
|
+
|
|
1748
|
+
context "when the next condition is #nin" do
|
|
1749
|
+
let(:query_method) { :nin }
|
|
1750
|
+
let(:operator) { '$nin' }
|
|
1751
|
+
|
|
1752
|
+
it_behaves_like 'negates the next condition'
|
|
1753
|
+
end
|
|
1754
|
+
|
|
585
1755
|
context "when the following criteria is a gt method" do
|
|
586
1756
|
|
|
587
1757
|
let(:selection) do
|
|
@@ -594,10 +1764,27 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
594
1764
|
)
|
|
595
1765
|
end
|
|
596
1766
|
|
|
597
|
-
|
|
598
|
-
|
|
1767
|
+
it_behaves_like 'returns a cloned query'
|
|
1768
|
+
|
|
1769
|
+
it "removes the negation on the clone" do
|
|
1770
|
+
expect(selection).to_not be_negating
|
|
1771
|
+
end
|
|
1772
|
+
end
|
|
1773
|
+
|
|
1774
|
+
context "when the criteria uses Key" do
|
|
1775
|
+
|
|
1776
|
+
let(:selection) do
|
|
1777
|
+
query.not(:age.gt => 50)
|
|
1778
|
+
end
|
|
1779
|
+
|
|
1780
|
+
it "negates the gt selection" do
|
|
1781
|
+
expect(selection.selector).to eq(
|
|
1782
|
+
'$and' => ['$nor' => ['age' => {'$gt' => 50}]]
|
|
1783
|
+
)
|
|
599
1784
|
end
|
|
600
1785
|
|
|
1786
|
+
it_behaves_like 'returns a cloned query'
|
|
1787
|
+
|
|
601
1788
|
it "removes the negation on the clone" do
|
|
602
1789
|
expect(selection).to_not be_negating
|
|
603
1790
|
end
|
|
@@ -615,9 +1802,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
615
1802
|
)
|
|
616
1803
|
end
|
|
617
1804
|
|
|
618
|
-
|
|
619
|
-
expect(selection).to_not equal(query)
|
|
620
|
-
end
|
|
1805
|
+
it_behaves_like 'returns a cloned query'
|
|
621
1806
|
|
|
622
1807
|
it "removes the negation on the clone" do
|
|
623
1808
|
expect(selection).to_not be_negating
|
|
@@ -636,10 +1821,27 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
636
1821
|
)
|
|
637
1822
|
end
|
|
638
1823
|
|
|
639
|
-
|
|
640
|
-
|
|
1824
|
+
it_behaves_like 'returns a cloned query'
|
|
1825
|
+
|
|
1826
|
+
it "removes the negation on the clone" do
|
|
1827
|
+
expect(selection).to_not be_negating
|
|
1828
|
+
end
|
|
1829
|
+
end
|
|
1830
|
+
|
|
1831
|
+
context 'when the following criteria uses string were form' do
|
|
1832
|
+
|
|
1833
|
+
let(:selection) do
|
|
1834
|
+
query.not.where('hello world')
|
|
1835
|
+
end
|
|
1836
|
+
|
|
1837
|
+
it "negates the selection with an operator" do
|
|
1838
|
+
expect(selection.selector).to eq(
|
|
1839
|
+
'$and' => [{'$nor' => [{'$where' => 'hello world'}]}]
|
|
1840
|
+
)
|
|
641
1841
|
end
|
|
642
1842
|
|
|
1843
|
+
it_behaves_like 'returns a cloned query'
|
|
1844
|
+
|
|
643
1845
|
it "removes the negation on the clone" do
|
|
644
1846
|
expect(selection).to_not be_negating
|
|
645
1847
|
end
|
|
@@ -661,9 +1863,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
661
1863
|
expect(selection).to eq(query)
|
|
662
1864
|
end
|
|
663
1865
|
|
|
664
|
-
|
|
665
|
-
expect(selection).to_not equal(query)
|
|
666
|
-
end
|
|
1866
|
+
it_behaves_like 'returns a cloned query'
|
|
667
1867
|
end
|
|
668
1868
|
|
|
669
1869
|
context "when provided a single criterion" do
|
|
@@ -678,14 +1878,31 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
678
1878
|
})
|
|
679
1879
|
end
|
|
680
1880
|
|
|
681
|
-
|
|
682
|
-
|
|
1881
|
+
it_behaves_like 'returns a cloned query'
|
|
1882
|
+
end
|
|
1883
|
+
|
|
1884
|
+
context "when negating a field in the original selector" do
|
|
1885
|
+
let(:query) do
|
|
1886
|
+
Mongoid::Query.new("id" => "_id").where(field: 'foo')
|
|
1887
|
+
end
|
|
1888
|
+
|
|
1889
|
+
let(:selection) do
|
|
1890
|
+
query.not(field: 'bar')
|
|
683
1891
|
end
|
|
1892
|
+
|
|
1893
|
+
it "combines the conditions" do
|
|
1894
|
+
expect(selection.selector).to eq({
|
|
1895
|
+
"field" => 'foo',
|
|
1896
|
+
'$and' => [{'$nor' => [{ "field" => 'bar' }]}],
|
|
1897
|
+
})
|
|
1898
|
+
end
|
|
1899
|
+
|
|
1900
|
+
it_behaves_like 'returns a cloned query'
|
|
684
1901
|
end
|
|
685
1902
|
|
|
686
|
-
context "when provided multiple
|
|
1903
|
+
context "when provided multiple criteria" do
|
|
687
1904
|
|
|
688
|
-
context "when the
|
|
1905
|
+
context "when the criteria are for different fields" do
|
|
689
1906
|
|
|
690
1907
|
let(:selection) do
|
|
691
1908
|
query.not(first: /1/, second: /2/)
|
|
@@ -698,9 +1915,23 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
698
1915
|
})
|
|
699
1916
|
end
|
|
700
1917
|
|
|
701
|
-
|
|
702
|
-
|
|
1918
|
+
it_behaves_like 'returns a cloned query'
|
|
1919
|
+
end
|
|
1920
|
+
|
|
1921
|
+
context "when the criteria are given in separate arguments" do
|
|
1922
|
+
|
|
1923
|
+
let(:selection) do
|
|
1924
|
+
query.not({first: /1/}, {second: /2/})
|
|
1925
|
+
end
|
|
1926
|
+
|
|
1927
|
+
it "adds the $not selectors" do
|
|
1928
|
+
expect(selection.selector).to eq({
|
|
1929
|
+
"first" => { "$not" => /1/ },
|
|
1930
|
+
"second" => { "$not" => /2/ }
|
|
1931
|
+
})
|
|
703
1932
|
end
|
|
1933
|
+
|
|
1934
|
+
it_behaves_like 'returns a cloned query'
|
|
704
1935
|
end
|
|
705
1936
|
end
|
|
706
1937
|
|
|
@@ -719,9 +1950,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
719
1950
|
})
|
|
720
1951
|
end
|
|
721
1952
|
|
|
722
|
-
|
|
723
|
-
expect(selection).to_not equal(query)
|
|
724
|
-
end
|
|
1953
|
+
it_behaves_like 'returns a cloned query'
|
|
725
1954
|
end
|
|
726
1955
|
|
|
727
1956
|
context "when the criterion are on the same field" do
|
|
@@ -730,15 +1959,14 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
730
1959
|
query.not(first: /1/).not(first: /2/)
|
|
731
1960
|
end
|
|
732
1961
|
|
|
733
|
-
it "
|
|
734
|
-
expect(selection.selector).to eq(
|
|
735
|
-
"first" => { "$not" => /
|
|
736
|
-
|
|
1962
|
+
it "combines conditions" do
|
|
1963
|
+
expect(selection.selector).to eq(
|
|
1964
|
+
"first" => { "$not" => /1/ },
|
|
1965
|
+
'$and' => [{'$nor' => [{'first' => /2/}]}],
|
|
1966
|
+
)
|
|
737
1967
|
end
|
|
738
1968
|
|
|
739
|
-
|
|
740
|
-
expect(selection).to_not equal(query)
|
|
741
|
-
end
|
|
1969
|
+
it_behaves_like 'returns a cloned query'
|
|
742
1970
|
end
|
|
743
1971
|
|
|
744
1972
|
context "when the criterion are a double negative" do
|
|
@@ -753,10 +1981,139 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
|
753
1981
|
})
|
|
754
1982
|
end
|
|
755
1983
|
|
|
756
|
-
|
|
757
|
-
|
|
1984
|
+
it_behaves_like 'returns a cloned query'
|
|
1985
|
+
end
|
|
1986
|
+
end
|
|
1987
|
+
|
|
1988
|
+
context 'when argument is a Criteria' do
|
|
1989
|
+
let(:query) do
|
|
1990
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
1991
|
+
end
|
|
1992
|
+
|
|
1993
|
+
let(:other) do
|
|
1994
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
1995
|
+
end
|
|
1996
|
+
|
|
1997
|
+
let(:result) { query.not(other) }
|
|
1998
|
+
|
|
1999
|
+
it 'combines' do
|
|
2000
|
+
expect(result.selector).to eq('hello' => 'world', 'foo' => {'$ne' => 'bar'})
|
|
2001
|
+
end
|
|
2002
|
+
end
|
|
2003
|
+
|
|
2004
|
+
context 'when argument is a simple Criteria with multiple fields' do
|
|
2005
|
+
let(:query) do
|
|
2006
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
2007
|
+
end
|
|
2008
|
+
|
|
2009
|
+
let(:other) do
|
|
2010
|
+
Mongoid::Query.new.where(a: 1, b: 2)
|
|
2011
|
+
end
|
|
2012
|
+
|
|
2013
|
+
let(:result) { query.not(other) }
|
|
2014
|
+
|
|
2015
|
+
it 'combines fields into top level criteria' do
|
|
2016
|
+
expect(result.selector).to eq('hello' => 'world',
|
|
2017
|
+
'a' => {'$ne' => 1}, 'b' => {'$ne' => 2})
|
|
2018
|
+
end
|
|
2019
|
+
end
|
|
2020
|
+
|
|
2021
|
+
context 'when argument is a complex Criteria' do
|
|
2022
|
+
let(:query) do
|
|
2023
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
2024
|
+
end
|
|
2025
|
+
|
|
2026
|
+
let(:other) do
|
|
2027
|
+
Mongoid::Query.new.where('$nor' => [{a: 1, b: 2}])
|
|
2028
|
+
end
|
|
2029
|
+
|
|
2030
|
+
let(:result) { query.not(other) }
|
|
2031
|
+
|
|
2032
|
+
it 'combines with $and of $nor' do
|
|
2033
|
+
expect(result.selector).to eq('hello' => 'world', '$and' => [{'$nor' => [{
|
|
2034
|
+
'$nor' => [{'a' => 1, 'b' => 2}]}]}])
|
|
2035
|
+
end
|
|
2036
|
+
end
|
|
2037
|
+
|
|
2038
|
+
context 'when argument is a mix of Criteria and hashes' do
|
|
2039
|
+
let(:query) do
|
|
2040
|
+
Mongoid::Query.new.where(hello: 'world')
|
|
2041
|
+
end
|
|
2042
|
+
|
|
2043
|
+
let(:other1) do
|
|
2044
|
+
Mongoid::Query.new.where(foo: 'bar')
|
|
2045
|
+
end
|
|
2046
|
+
|
|
2047
|
+
let(:other2) do
|
|
2048
|
+
{bar: 42}
|
|
2049
|
+
end
|
|
2050
|
+
|
|
2051
|
+
let(:other3) do
|
|
2052
|
+
Mongoid::Query.new.where(a: 2)
|
|
2053
|
+
end
|
|
2054
|
+
|
|
2055
|
+
let(:result) { query.not(other1, other2, other3) }
|
|
2056
|
+
|
|
2057
|
+
it 'combines' do
|
|
2058
|
+
expect(result.selector).to eq('hello' => 'world',
|
|
2059
|
+
'foo' => {'$ne' => 'bar'},
|
|
2060
|
+
'bar' => {'$ne' => 42},
|
|
2061
|
+
'a' => {'$ne' => 2},
|
|
2062
|
+
)
|
|
2063
|
+
end
|
|
2064
|
+
end
|
|
2065
|
+
|
|
2066
|
+
context 'when giving multiple conditions in one call on the same key with symbol operator' do
|
|
2067
|
+
|
|
2068
|
+
context 'non-regexp argument' do
|
|
2069
|
+
let(:selection) do
|
|
2070
|
+
query.not(field: 1, :field.gt => 0)
|
|
2071
|
+
end
|
|
2072
|
+
|
|
2073
|
+
it 'combines conditions with $eq' do
|
|
2074
|
+
selection.selector.should == {
|
|
2075
|
+
'$and' => ['$nor' => [
|
|
2076
|
+
'field' => {'$eq' => 1, '$gt' => 0},
|
|
2077
|
+
]]
|
|
2078
|
+
}
|
|
2079
|
+
end
|
|
2080
|
+
end
|
|
2081
|
+
|
|
2082
|
+
context 'regexp argument' do
|
|
2083
|
+
let(:selection) do
|
|
2084
|
+
query.not(field: /t/, :field.gt => 0)
|
|
2085
|
+
end
|
|
2086
|
+
|
|
2087
|
+
it 'combines conditions with $regex' do
|
|
2088
|
+
selection.selector.should == {
|
|
2089
|
+
'$and' => ['$nor' => [
|
|
2090
|
+
'field' => {'$regex' => /t/, '$gt' => 0},
|
|
2091
|
+
]]
|
|
2092
|
+
}
|
|
758
2093
|
end
|
|
759
2094
|
end
|
|
760
2095
|
end
|
|
2096
|
+
|
|
2097
|
+
# This test confirms that MONGOID-5097 has been repaired.
|
|
2098
|
+
context "when using exists on a field of type Time" do
|
|
2099
|
+
let(:criteria) do
|
|
2100
|
+
Dictionary.any_of({:published.exists => true}, published: nil)
|
|
2101
|
+
end
|
|
2102
|
+
|
|
2103
|
+
it "doesn't raise an error" do
|
|
2104
|
+
expect do
|
|
2105
|
+
criteria
|
|
2106
|
+
end.to_not raise_error
|
|
2107
|
+
end
|
|
2108
|
+
|
|
2109
|
+
it "generates the correct selector" do
|
|
2110
|
+
expect(criteria.selector).to eq({
|
|
2111
|
+
"$or" => [ {
|
|
2112
|
+
"published" => { "$exists" => true }
|
|
2113
|
+
}, {
|
|
2114
|
+
"published" => nil
|
|
2115
|
+
} ] } )
|
|
2116
|
+
end
|
|
2117
|
+
end
|
|
761
2118
|
end
|
|
762
2119
|
end
|