mongoid 7.5.3 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -3
- data/README.md +6 -6
- data/Rakefile +25 -0
- data/lib/config/locales/en.yml +92 -43
- data/lib/mongoid/association/accessors.rb +40 -11
- data/lib/mongoid/association/bindable.rb +50 -2
- data/lib/mongoid/association/builders.rb +5 -3
- data/lib/mongoid/association/constrainable.rb +0 -1
- data/lib/mongoid/association/eager_loadable.rb +29 -7
- data/lib/mongoid/association/embedded/batchable.rb +34 -11
- data/lib/mongoid/association/embedded/cyclic.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
- data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +4 -3
- data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
- data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +4 -3
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +69 -45
- data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +19 -5
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +24 -5
- data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
- data/lib/mongoid/association/macros.rb +8 -1
- data/lib/mongoid/association/many.rb +11 -7
- data/lib/mongoid/association/nested/many.rb +5 -4
- data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
- data/lib/mongoid/association/nested/one.rb +45 -7
- data/lib/mongoid/association/one.rb +2 -2
- data/lib/mongoid/association/options.rb +9 -9
- data/lib/mongoid/association/proxy.rb +15 -4
- data/lib/mongoid/association/referenced/auto_save.rb +4 -3
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
- data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
- data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
- data/lib/mongoid/association/referenced/eager.rb +2 -2
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
- data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +22 -30
- data/lib/mongoid/association/referenced/has_many/proxy.rb +29 -19
- data/lib/mongoid/association/referenced/has_many.rb +3 -3
- data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
- data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
- data/lib/mongoid/association/referenced/has_one.rb +3 -3
- data/lib/mongoid/association/referenced/syncable.rb +4 -4
- data/lib/mongoid/association/reflections.rb +4 -4
- data/lib/mongoid/association/relatable.rb +44 -10
- data/lib/mongoid/association.rb +5 -5
- data/lib/mongoid/atomic/modifiers.rb +2 -2
- data/lib/mongoid/atomic.rb +7 -0
- data/lib/mongoid/attributes/dynamic.rb +4 -4
- data/lib/mongoid/attributes/nested.rb +6 -6
- data/lib/mongoid/attributes/processing.rb +37 -6
- data/lib/mongoid/attributes/projector.rb +2 -2
- data/lib/mongoid/attributes/readonly.rb +3 -3
- data/lib/mongoid/attributes.rb +51 -42
- data/lib/mongoid/changeable.rb +147 -14
- data/lib/mongoid/clients/options.rb +5 -1
- data/lib/mongoid/clients/sessions.rb +2 -14
- data/lib/mongoid/clients/storage_options.rb +2 -5
- data/lib/mongoid/clients/validators/storage.rb +3 -15
- data/lib/mongoid/collection_configurable.rb +58 -0
- data/lib/mongoid/composable.rb +2 -0
- data/lib/mongoid/config/defaults.rb +60 -0
- data/lib/mongoid/config/options.rb +3 -0
- data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
- data/lib/mongoid/config/validators/client.rb +6 -6
- data/lib/mongoid/config/validators.rb +1 -0
- data/lib/mongoid/config.rb +140 -18
- data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
- data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
- data/lib/mongoid/contextual/aggregable/none.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +1 -1
- data/lib/mongoid/contextual/geo_near.rb +7 -7
- data/lib/mongoid/contextual/map_reduce.rb +2 -2
- data/lib/mongoid/contextual/memory.rb +285 -58
- data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
- data/lib/mongoid/contextual/mongo.rb +517 -346
- data/lib/mongoid/contextual/none.rb +193 -20
- data/lib/mongoid/contextual/queryable.rb +1 -1
- data/lib/mongoid/contextual.rb +14 -2
- data/lib/mongoid/copyable.rb +32 -8
- data/lib/mongoid/criteria/findable.rb +8 -5
- data/lib/mongoid/criteria/includable.rb +27 -22
- data/lib/mongoid/criteria/marshalable.rb +10 -2
- data/lib/mongoid/criteria/permission.rb +1 -1
- data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -16
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -17
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -9
- data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
- data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
- data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
- data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
- data/lib/mongoid/criteria/queryable/key.rb +4 -4
- data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
- data/lib/mongoid/criteria/queryable/optional.rb +11 -17
- data/lib/mongoid/criteria/queryable/options.rb +2 -2
- data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
- data/lib/mongoid/criteria/queryable/selectable.rb +47 -38
- data/lib/mongoid/criteria/queryable/selector.rb +93 -8
- data/lib/mongoid/criteria/queryable/smash.rb +40 -7
- data/lib/mongoid/criteria/queryable/storable.rb +1 -1
- data/lib/mongoid/criteria/queryable.rb +12 -7
- data/lib/mongoid/criteria/scopable.rb +2 -2
- data/lib/mongoid/criteria/translator.rb +45 -0
- data/lib/mongoid/criteria.rb +20 -40
- data/lib/mongoid/deprecable.rb +36 -0
- data/lib/mongoid/deprecation.rb +25 -0
- data/lib/mongoid/document.rb +127 -35
- data/lib/mongoid/equality.rb +8 -8
- data/lib/mongoid/errors/create_collection_failure.rb +33 -0
- data/lib/mongoid/errors/document_not_found.rb +10 -6
- data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
- data/lib/mongoid/errors/immutable_attribute.rb +26 -0
- data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
- data/lib/mongoid/errors/invalid_config_option.rb +1 -1
- data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
- data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
- data/lib/mongoid/errors/invalid_field.rb +6 -2
- data/lib/mongoid/errors/invalid_field_type.rb +26 -0
- data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
- data/lib/mongoid/errors/invalid_relation.rb +1 -1
- data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
- data/lib/mongoid/errors/invalid_session_use.rb +1 -1
- data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
- data/lib/mongoid/errors/mongoid_error.rb +3 -3
- data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
- data/lib/mongoid/errors/no_client_database.rb +1 -1
- data/lib/mongoid/errors/no_client_hosts.rb +1 -1
- data/lib/mongoid/errors/readonly_attribute.rb +1 -1
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
- data/lib/mongoid/errors/unknown_attribute.rb +1 -1
- data/lib/mongoid/errors.rb +6 -3
- data/lib/mongoid/extensions/array.rb +9 -7
- data/lib/mongoid/extensions/big_decimal.rb +33 -10
- data/lib/mongoid/extensions/binary.rb +42 -0
- data/lib/mongoid/extensions/boolean.rb +8 -2
- data/lib/mongoid/extensions/date.rb +26 -20
- data/lib/mongoid/extensions/date_time.rb +1 -1
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/float.rb +7 -4
- data/lib/mongoid/extensions/hash.rb +19 -8
- data/lib/mongoid/extensions/integer.rb +7 -4
- data/lib/mongoid/extensions/module.rb +1 -1
- data/lib/mongoid/extensions/object.rb +10 -8
- data/lib/mongoid/extensions/range.rb +41 -10
- data/lib/mongoid/extensions/regexp.rb +11 -4
- data/lib/mongoid/extensions/set.rb +11 -4
- data/lib/mongoid/extensions/string.rb +11 -22
- data/lib/mongoid/extensions/symbol.rb +4 -15
- data/lib/mongoid/extensions/time.rb +29 -16
- data/lib/mongoid/extensions/time_with_zone.rb +1 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/factory.rb +55 -7
- data/lib/mongoid/fields/foreign_key.rb +11 -4
- data/lib/mongoid/fields/localized.rb +19 -4
- data/lib/mongoid/fields/standard.rb +17 -7
- data/lib/mongoid/fields/validators/macro.rb +3 -9
- data/lib/mongoid/fields.rb +129 -20
- data/lib/mongoid/findable.rb +54 -24
- data/lib/mongoid/indexable/specification.rb +2 -2
- data/lib/mongoid/indexable/validators/options.rb +6 -2
- data/lib/mongoid/interceptable.rb +76 -15
- data/lib/mongoid/matchable.rb +1 -1
- data/lib/mongoid/matcher/eq_impl.rb +1 -1
- data/lib/mongoid/matcher/type.rb +1 -1
- data/lib/mongoid/matcher.rb +33 -13
- data/lib/mongoid/persistable/creatable.rb +19 -9
- data/lib/mongoid/persistable/deletable.rb +2 -2
- data/lib/mongoid/persistable/destroyable.rb +1 -1
- data/lib/mongoid/persistable/savable.rb +14 -2
- data/lib/mongoid/persistable/unsettable.rb +2 -2
- data/lib/mongoid/persistable/updatable.rb +69 -12
- data/lib/mongoid/persistable/upsertable.rb +21 -2
- data/lib/mongoid/persistable.rb +6 -3
- data/lib/mongoid/persistence_context.rb +6 -4
- data/lib/mongoid/query_cache.rb +13 -261
- data/lib/mongoid/railties/controller_runtime.rb +1 -1
- data/lib/mongoid/railties/database.rake +7 -2
- data/lib/mongoid/reloadable.rb +10 -8
- data/lib/mongoid/scopable.rb +15 -13
- data/lib/mongoid/selectable.rb +1 -2
- data/lib/mongoid/serializable.rb +10 -6
- data/lib/mongoid/stateful.rb +57 -10
- data/lib/mongoid/tasks/database.rake +12 -0
- data/lib/mongoid/tasks/database.rb +20 -2
- data/lib/mongoid/threaded/lifecycle.rb +5 -5
- data/lib/mongoid/threaded.rb +42 -12
- data/lib/mongoid/timestamps/created.rb +1 -1
- data/lib/mongoid/timestamps/updated.rb +2 -2
- data/lib/mongoid/touchable.rb +2 -3
- data/lib/mongoid/traversable.rb +5 -4
- data/lib/mongoid/utils.rb +22 -0
- data/lib/mongoid/validatable/localizable.rb +1 -1
- data/lib/mongoid/validatable/macros.rb +5 -7
- data/lib/mongoid/validatable/presence.rb +2 -2
- data/lib/mongoid/validatable/uniqueness.rb +9 -8
- data/lib/mongoid/validatable.rb +9 -6
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/warnings.rb +19 -4
- data/lib/mongoid.rb +17 -3
- data/spec/config/mongoid.yml +16 -0
- data/spec/integration/app_spec.rb +10 -14
- data/spec/integration/associations/belongs_to_spec.rb +18 -0
- data/spec/integration/associations/embedded_spec.rb +15 -0
- data/spec/integration/associations/embeds_many_spec.rb +15 -2
- data/spec/integration/associations/embeds_one_spec.rb +18 -0
- data/spec/integration/associations/foreign_key_spec.rb +9 -0
- data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
- data/spec/integration/associations/has_one_spec.rb +97 -1
- data/spec/integration/associations/scope_option_spec.rb +1 -1
- data/spec/integration/callbacks_models.rb +132 -1
- data/spec/integration/callbacks_spec.rb +360 -4
- data/spec/integration/criteria/range_spec.rb +95 -1
- data/spec/integration/discriminator_key_spec.rb +118 -80
- data/spec/integration/dots_and_dollars_spec.rb +277 -0
- data/spec/integration/i18n_fallbacks_spec.rb +3 -32
- data/spec/integration/matcher_examples_spec.rb +20 -13
- data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
- data/spec/integration/matcher_operator_spec.rb +3 -5
- data/spec/integration/persistence/range_field_spec.rb +350 -0
- data/spec/mongoid/association/counter_cache_spec.rb +1 -1
- data/spec/mongoid/association/depending_spec.rb +9 -9
- data/spec/mongoid/association/eager_spec.rb +2 -1
- data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
- data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +96 -9
- data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +255 -65
- data/spec/mongoid/association/embedded/embeds_many_models.rb +37 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
- data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
- data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
- data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
- data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
- data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
- data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +4 -20
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +186 -229
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +173 -177
- data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
- data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
- data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
- data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
- data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
- data/spec/mongoid/association/syncable_spec.rb +15 -1
- data/spec/mongoid/atomic/paths_spec.rb +0 -14
- data/spec/mongoid/attributes/nested_spec.rb +80 -11
- data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
- data/spec/mongoid/attributes/projector_spec.rb +1 -5
- data/spec/mongoid/attributes_spec.rb +510 -33
- data/spec/mongoid/changeable_spec.rb +429 -37
- data/spec/mongoid/clients/factory_spec.rb +23 -30
- data/spec/mongoid/clients/sessions_spec.rb +0 -38
- data/spec/mongoid/clients_spec.rb +149 -15
- data/spec/mongoid/collection_configurable_spec.rb +158 -0
- data/spec/mongoid/config/defaults_spec.rb +160 -0
- data/spec/mongoid/config_spec.rb +214 -31
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
- data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
- data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
- data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
- data/spec/mongoid/contextual/memory_spec.rb +850 -88
- data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
- data/spec/mongoid/contextual/mongo_spec.rb +1572 -435
- data/spec/mongoid/contextual/none_spec.rb +60 -21
- data/spec/mongoid/copyable_spec.rb +453 -11
- data/spec/mongoid/criteria/findable_spec.rb +86 -210
- data/spec/mongoid/criteria/includable_spec.rb +1492 -0
- data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
- data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
- data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
- data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +469 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +78 -86
- data/spec/mongoid/criteria/queryable/selector_spec.rb +90 -5
- data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
- data/spec/mongoid/criteria/translator_spec.rb +132 -0
- data/spec/mongoid/criteria_projection_spec.rb +1 -5
- data/spec/mongoid/criteria_spec.rb +469 -1205
- data/spec/mongoid/document_fields_spec.rb +173 -24
- data/spec/mongoid/document_spec.rb +32 -41
- data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
- data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
- data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
- data/spec/mongoid/errors/no_environment_spec.rb +3 -3
- data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
- data/spec/mongoid/extensions/array_spec.rb +16 -2
- data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
- data/spec/mongoid/extensions/binary_spec.rb +44 -9
- data/spec/mongoid/extensions/boolean_spec.rb +68 -82
- data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
- data/spec/mongoid/extensions/date_spec.rb +71 -1
- data/spec/mongoid/extensions/date_time_spec.rb +15 -9
- data/spec/mongoid/extensions/float_spec.rb +53 -74
- data/spec/mongoid/extensions/hash_spec.rb +33 -3
- data/spec/mongoid/extensions/integer_spec.rb +50 -64
- data/spec/mongoid/extensions/range_spec.rb +255 -54
- data/spec/mongoid/extensions/regexp_spec.rb +58 -33
- data/spec/mongoid/extensions/set_spec.rb +106 -0
- data/spec/mongoid/extensions/string_spec.rb +53 -25
- data/spec/mongoid/extensions/symbol_spec.rb +18 -25
- data/spec/mongoid/extensions/time_spec.rb +639 -106
- data/spec/mongoid/extensions/time_with_zone_spec.rb +24 -83
- data/spec/mongoid/factory_spec.rb +61 -1
- data/spec/mongoid/fields/localized_spec.rb +80 -37
- data/spec/mongoid/fields_spec.rb +500 -84
- data/spec/mongoid/findable_spec.rb +450 -58
- data/spec/mongoid/indexable/specification_spec.rb +2 -2
- data/spec/mongoid/indexable_spec.rb +55 -30
- data/spec/mongoid/interceptable_spec.rb +599 -8
- data/spec/mongoid/interceptable_spec_models.rb +235 -4
- data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
- data/spec/mongoid/mongoizable_spec.rb +285 -0
- data/spec/mongoid/persistable/creatable_spec.rb +2 -2
- data/spec/mongoid/persistable/deletable_spec.rb +28 -8
- data/spec/mongoid/persistable/destroyable_spec.rb +28 -8
- data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
- data/spec/mongoid/persistable/logical_spec.rb +37 -0
- data/spec/mongoid/persistable/poppable_spec.rb +36 -0
- data/spec/mongoid/persistable/pullable_spec.rb +72 -0
- data/spec/mongoid/persistable/pushable_spec.rb +72 -0
- data/spec/mongoid/persistable/renamable_spec.rb +36 -0
- data/spec/mongoid/persistable/savable_spec.rb +96 -0
- data/spec/mongoid/persistable/settable_spec.rb +37 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
- data/spec/mongoid/persistable/updatable_spec.rb +20 -28
- data/spec/mongoid/persistable/upsertable_spec.rb +89 -1
- data/spec/mongoid/persistence_context_spec.rb +31 -57
- data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
- data/spec/mongoid/query_cache_spec.rb +56 -215
- data/spec/mongoid/reloadable_spec.rb +83 -6
- data/spec/mongoid/scopable_spec.rb +91 -1
- data/spec/mongoid/serializable_spec.rb +9 -30
- data/spec/mongoid/shardable_spec.rb +4 -4
- data/spec/mongoid/stateful_spec.rb +150 -8
- data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
- data/spec/mongoid/tasks/database_spec.rb +127 -0
- data/spec/mongoid/timestamps_spec.rb +392 -4
- data/spec/mongoid/timestamps_spec_models.rb +67 -0
- data/spec/mongoid/touchable_spec.rb +390 -2
- data/spec/mongoid/touchable_spec_models.rb +14 -8
- data/spec/mongoid/traversable_spec.rb +13 -35
- data/spec/mongoid/validatable/presence_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +58 -31
- data/spec/mongoid/warnings_spec.rb +35 -0
- data/spec/mongoid_spec.rb +34 -16
- data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
- data/spec/rails/mongoid_spec.rb +4 -16
- data/spec/spec_helper.rb +5 -0
- data/spec/support/constraints.rb +24 -0
- data/spec/support/immutable_ids.rb +118 -0
- data/spec/support/macros.rb +78 -0
- data/spec/support/models/artist.rb +0 -1
- data/spec/support/models/augmentation.rb +12 -0
- data/spec/support/models/band.rb +4 -0
- data/spec/support/models/book.rb +1 -0
- data/spec/support/models/building.rb +2 -0
- data/spec/support/models/catalog.rb +24 -0
- data/spec/support/models/circus.rb +3 -0
- data/spec/support/models/cover.rb +10 -0
- data/spec/support/models/fanatic.rb +8 -0
- data/spec/support/models/implant.rb +9 -0
- data/spec/support/models/label.rb +2 -0
- data/spec/support/models/passport.rb +9 -0
- data/spec/support/models/person.rb +2 -0
- data/spec/support/models/player.rb +2 -0
- data/spec/support/models/powerup.rb +12 -0
- data/spec/support/models/product.rb +1 -0
- data/spec/support/models/purse.rb +9 -0
- data/spec/support/models/registry.rb +1 -0
- data/spec/support/models/school.rb +14 -0
- data/spec/support/models/shield.rb +18 -0
- data/spec/support/models/student.rb +14 -0
- data/spec/support/models/weapon.rb +12 -0
- data.tar.gz.sig +0 -0
- metadata +718 -641
- metadata.gz.sig +0 -0
- data/lib/mongoid/errors/eager_load.rb +0 -23
- data/lib/mongoid/errors/invalid_value.rb +0 -17
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
- data/spec/mongoid/errors/eager_load_spec.rb +0 -31
|
@@ -27,7 +27,7 @@ module Mongoid
|
|
|
27
27
|
:before_save,
|
|
28
28
|
:before_update,
|
|
29
29
|
:before_upsert,
|
|
30
|
-
:before_validation
|
|
30
|
+
:before_validation,
|
|
31
31
|
].freeze
|
|
32
32
|
|
|
33
33
|
included do
|
|
@@ -37,6 +37,12 @@ module Mongoid
|
|
|
37
37
|
define_model_callbacks :build, :find, :initialize, :touch, only: :after
|
|
38
38
|
define_model_callbacks :create, :destroy, :save, :update, :upsert
|
|
39
39
|
|
|
40
|
+
# This callback is used internally by Mongoid to save association
|
|
41
|
+
# targets for referenced associations after the parent model is persisted.
|
|
42
|
+
#
|
|
43
|
+
# @api private
|
|
44
|
+
define_model_callbacks :persist_parent
|
|
45
|
+
|
|
40
46
|
attr_accessor :before_callback_halted
|
|
41
47
|
end
|
|
42
48
|
|
|
@@ -47,7 +53,7 @@ module Mongoid
|
|
|
47
53
|
#
|
|
48
54
|
# @param [ Symbol ] kind The type of callback.
|
|
49
55
|
#
|
|
50
|
-
# @return [ true
|
|
56
|
+
# @return [ true | false ] If the callback can be executed.
|
|
51
57
|
def callback_executable?(kind)
|
|
52
58
|
respond_to?("_#{kind}_callbacks")
|
|
53
59
|
end
|
|
@@ -60,7 +66,7 @@ module Mongoid
|
|
|
60
66
|
#
|
|
61
67
|
# @param [ Symbol ] kind The callback kind.
|
|
62
68
|
#
|
|
63
|
-
# @return [ true
|
|
69
|
+
# @return [ true | false ] If the document is in a callback state.
|
|
64
70
|
def in_callback_state?(kind)
|
|
65
71
|
[ :create, :destroy ].include?(kind) || new_record? || flagged_for_destroy? || changed?
|
|
66
72
|
end
|
|
@@ -73,7 +79,7 @@ module Mongoid
|
|
|
73
79
|
# @example Run only the after save callbacks.
|
|
74
80
|
# model.run_after_callbacks(:save)
|
|
75
81
|
#
|
|
76
|
-
# @param [
|
|
82
|
+
# @param [ Symbol... ] *kinds The events that are occurring.
|
|
77
83
|
#
|
|
78
84
|
# @return [ Object ] The result of the chain executing.
|
|
79
85
|
def run_after_callbacks(*kinds)
|
|
@@ -90,7 +96,7 @@ module Mongoid
|
|
|
90
96
|
# @example Run only the before save callbacks.
|
|
91
97
|
# model.run_before_callbacks(:save, :create)
|
|
92
98
|
#
|
|
93
|
-
# @param [
|
|
99
|
+
# @param [ Symbol... ] *kinds The events that are occurring.
|
|
94
100
|
#
|
|
95
101
|
# @return [ Object ] The result of the chain executing.
|
|
96
102
|
def run_before_callbacks(*kinds)
|
|
@@ -109,22 +115,77 @@ module Mongoid
|
|
|
109
115
|
# end
|
|
110
116
|
#
|
|
111
117
|
# @param [ Symbol ] kind The type of callback to execute.
|
|
112
|
-
# @param [
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
# @param [ true | false ] with_children Flag specifies whether callbacks of embedded document should be run.
|
|
119
|
+
def run_callbacks(kind, with_children: true, &block)
|
|
120
|
+
if with_children
|
|
121
|
+
cascadable_children(kind).each do |child|
|
|
122
|
+
if child.run_callbacks(child_callback_type(kind, child), with_children: with_children) == false
|
|
123
|
+
return false
|
|
124
|
+
end
|
|
119
125
|
end
|
|
120
126
|
end
|
|
121
127
|
if callback_executable?(kind)
|
|
122
|
-
super(kind,
|
|
128
|
+
super(kind, &block)
|
|
123
129
|
else
|
|
124
130
|
true
|
|
125
131
|
end
|
|
126
132
|
end
|
|
127
133
|
|
|
134
|
+
# Run the callbacks for embedded documents.
|
|
135
|
+
#
|
|
136
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
|
137
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
|
138
|
+
# nil, callbacks will be executed on all cascadable children of
|
|
139
|
+
# the document.
|
|
140
|
+
#
|
|
141
|
+
# @api private
|
|
142
|
+
def _mongoid_run_child_callbacks(kind, children: nil, &block)
|
|
143
|
+
child, *tail = (children || cascadable_children(kind))
|
|
144
|
+
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
|
145
|
+
if child.nil?
|
|
146
|
+
block&.call
|
|
147
|
+
elsif tail.empty?
|
|
148
|
+
child.run_callbacks(child_callback_type(kind, child), with_children: with_children, &block)
|
|
149
|
+
else
|
|
150
|
+
child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
|
|
151
|
+
_mongoid_run_child_callbacks(kind, children: tail, &block)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# This is used to store callbacks to be executed later. A good use case for
|
|
157
|
+
# this is delaying the after_find and after_initialize callbacks until the
|
|
158
|
+
# associations are set on the document. This can also be used to delay
|
|
159
|
+
# applying the defaults on a document.
|
|
160
|
+
#
|
|
161
|
+
# @return [ Array<Symbol> ] an array of symbols that represent the pending callbacks.
|
|
162
|
+
#
|
|
163
|
+
# @api private
|
|
164
|
+
def pending_callbacks
|
|
165
|
+
@pending_callbacks ||= [].to_set
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# @api private
|
|
169
|
+
def pending_callbacks=(value)
|
|
170
|
+
@pending_callbacks = value
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Run the pending callbacks. If the callback is :apply_defaults, we will apply
|
|
174
|
+
# the defaults for this document. Otherwise, the callback is passed to the
|
|
175
|
+
# run_callbacks function.
|
|
176
|
+
#
|
|
177
|
+
# @api private
|
|
178
|
+
def run_pending_callbacks
|
|
179
|
+
pending_callbacks.each do |cb|
|
|
180
|
+
if [:apply_defaults, :apply_post_processed_defaults].include?(cb)
|
|
181
|
+
send(cb)
|
|
182
|
+
else
|
|
183
|
+
self.run_callbacks(cb, with_children: false)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
pending_callbacks.clear
|
|
187
|
+
end
|
|
188
|
+
|
|
128
189
|
private
|
|
129
190
|
|
|
130
191
|
# We need to hook into this for autosave, since we don't want it firing if
|
|
@@ -135,7 +196,7 @@ module Mongoid
|
|
|
135
196
|
# @example Was a before callback halted?
|
|
136
197
|
# document.before_callback_halted?
|
|
137
198
|
#
|
|
138
|
-
# @return [ true
|
|
199
|
+
# @return [ true | false ] If a before callback was halted.
|
|
139
200
|
def before_callback_halted?
|
|
140
201
|
!!@before_callback_halted
|
|
141
202
|
end
|
|
@@ -175,7 +236,7 @@ module Mongoid
|
|
|
175
236
|
# @param [ Symbol ] kind The type of callback.
|
|
176
237
|
# @param [ Document ] child The child document.
|
|
177
238
|
#
|
|
178
|
-
# @return [ true
|
|
239
|
+
# @return [ true | false ] If the child should fire the callback.
|
|
179
240
|
def cascadable_child?(kind, child, association)
|
|
180
241
|
return false if kind == :initialize || kind == :find || kind == :touch
|
|
181
242
|
return false if kind == :validate && association.validate?
|
data/lib/mongoid/matchable.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Mongoid
|
|
|
15
15
|
#
|
|
16
16
|
# @param [ Hash ] selector The MongoDB selector.
|
|
17
17
|
#
|
|
18
|
-
# @return [ true
|
|
18
|
+
# @return [ true | false ] True if matches, false if not.
|
|
19
19
|
def _matches?(selector)
|
|
20
20
|
Matcher::Expression.matches?(self, selector)
|
|
21
21
|
end
|
|
@@ -46,7 +46,7 @@ module Mongoid
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
# Per https://
|
|
49
|
+
# Per https://www.mongodb.com/docs/ruby-driver/current/tutorials/bson-v4/#time-instances,
|
|
50
50
|
# > Times in BSON (and MongoDB) can only have millisecond precision. When Ruby Time instances
|
|
51
51
|
# are serialized to BSON or Extended JSON, the times are floored to the nearest millisecond.
|
|
52
52
|
#
|
data/lib/mongoid/matcher/type.rb
CHANGED
data/lib/mongoid/matcher.rb
CHANGED
|
@@ -2,7 +2,6 @@ module Mongoid
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
module Matcher
|
|
5
|
-
|
|
6
5
|
# Extracts field values in the document at the specified key.
|
|
7
6
|
#
|
|
8
7
|
# The document can be a Hash or a model instance.
|
|
@@ -24,23 +23,28 @@ module Mongoid
|
|
|
24
23
|
# an array of values of the `bar` field in each of the hashes in the
|
|
25
24
|
# `foo` array.
|
|
26
25
|
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
26
|
+
# This method can return an individual field value in some document
|
|
27
|
+
# or an array of values from multiple documents. The array can be returned
|
|
28
|
+
# because a field value in the specified path is an array of primitive
|
|
29
|
+
# values (e.g. integers) or because a field value in the specified path
|
|
30
|
+
# is an array of documents (e.g. a one-to-many embedded association),
|
|
31
|
+
# in which case the leaf value may be a scalar for each individual document.
|
|
32
|
+
# If the leaf value is an array and a one-to-many association was traversed,
|
|
33
|
+
# the return value will be an array of arrays. Note that an individual
|
|
34
|
+
# field value can also be an array and this case is indistinguishable
|
|
35
|
+
# from and behaves identically to association traversal for the purposes
|
|
36
|
+
# of, for example, subsequent array element retrieval.
|
|
31
37
|
#
|
|
32
38
|
# @param [ Document | Hash ] document The document to extract from.
|
|
33
39
|
# @param [ String ] key The key path to extract.
|
|
34
40
|
#
|
|
35
|
-
# @return [
|
|
36
|
-
# Whether the value existed in the document, the extracted value
|
|
37
|
-
# and the array expansion flag.
|
|
41
|
+
# @return [ Object | Array ] Field value or values.
|
|
38
42
|
module_function def extract_attribute(document, key)
|
|
39
43
|
if document.respond_to?(:as_attributes, true)
|
|
40
44
|
# If a document has hash fields, as_attributes would keep those fields
|
|
41
45
|
# as Hash instances which do not offer indifferent access.
|
|
42
46
|
# Convert to BSON::Document to get indifferent access on hash fields.
|
|
43
|
-
document =
|
|
47
|
+
document = document.send(:as_attributes)
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
current = [document]
|
|
@@ -50,8 +54,9 @@ module Mongoid
|
|
|
50
54
|
current.each do |doc|
|
|
51
55
|
case doc
|
|
52
56
|
when Hash
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
actual_key = find_exact_key(doc, field)
|
|
58
|
+
if !actual_key.nil?
|
|
59
|
+
new << doc[actual_key]
|
|
55
60
|
end
|
|
56
61
|
when Array
|
|
57
62
|
if (index = field.to_i).to_s == field
|
|
@@ -61,8 +66,9 @@ module Mongoid
|
|
|
61
66
|
end
|
|
62
67
|
doc.each do |subdoc|
|
|
63
68
|
if Hash === subdoc
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
actual_key = find_exact_key(subdoc, field)
|
|
70
|
+
if !actual_key.nil?
|
|
71
|
+
new << subdoc[actual_key]
|
|
66
72
|
end
|
|
67
73
|
end
|
|
68
74
|
end
|
|
@@ -74,6 +80,20 @@ module Mongoid
|
|
|
74
80
|
|
|
75
81
|
current
|
|
76
82
|
end
|
|
83
|
+
|
|
84
|
+
# Indifferent string or symbol key lookup, returning the exact key.
|
|
85
|
+
#
|
|
86
|
+
# @param [ Hash ] hash The input hash.
|
|
87
|
+
# @param [ String | Symbol ] key The key to perform indifferent lookups with.
|
|
88
|
+
#
|
|
89
|
+
# @return [ String | Symbol | nil ] The exact key (with the correct type) that exists in the hash, or nil if the key does not exist.
|
|
90
|
+
module_function def find_exact_key(hash, key)
|
|
91
|
+
key_s = key.to_s
|
|
92
|
+
return key_s if hash.key?(key_s)
|
|
93
|
+
|
|
94
|
+
key_sym = key.to_sym
|
|
95
|
+
hash.key?(key_sym) ? key_sym : nil
|
|
96
|
+
end
|
|
77
97
|
end
|
|
78
98
|
end
|
|
79
99
|
|
|
@@ -100,15 +100,25 @@ module Mongoid
|
|
|
100
100
|
#
|
|
101
101
|
# @return [ Document ] The document.
|
|
102
102
|
def prepare_insert(options = {})
|
|
103
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
|
103
104
|
return self if performing_validations?(options) &&
|
|
104
105
|
invalid?(options[:context] || :create)
|
|
105
|
-
|
|
106
|
-
run_callbacks(:create) do
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
run_callbacks(:save, with_children: false) do
|
|
107
|
+
run_callbacks(:create, with_children: false) do
|
|
108
|
+
run_callbacks(:persist_parent, with_children: false) do
|
|
109
|
+
_mongoid_run_child_callbacks(:save) do
|
|
110
|
+
_mongoid_run_child_callbacks(:create) do
|
|
111
|
+
result = yield(self)
|
|
112
|
+
if !result.is_a?(Document) || result.errors.empty?
|
|
113
|
+
post_process_insert
|
|
114
|
+
post_process_persist(result, options)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
109
119
|
end
|
|
110
120
|
end
|
|
111
|
-
|
|
121
|
+
self
|
|
112
122
|
end
|
|
113
123
|
|
|
114
124
|
module ClassMethods
|
|
@@ -123,10 +133,10 @@ module Mongoid
|
|
|
123
133
|
# @example Create multiple new documents.
|
|
124
134
|
# Person.create({ title: "Mr" }, { title: "Mrs" })
|
|
125
135
|
#
|
|
126
|
-
# @param [ Hash
|
|
136
|
+
# @param [ Hash | Array ] attributes The attributes to create with, or an
|
|
127
137
|
# Array of multiple attributes for multiple documents.
|
|
128
138
|
#
|
|
129
|
-
# @return [ Document
|
|
139
|
+
# @return [ Document | Array<Document> ] The newly created document(s).
|
|
130
140
|
def create(attributes = nil, &block)
|
|
131
141
|
_creating do
|
|
132
142
|
if attributes.is_a?(::Array)
|
|
@@ -150,10 +160,10 @@ module Mongoid
|
|
|
150
160
|
# @example Create multiple new documents.
|
|
151
161
|
# Person.create!({ title: "Mr" }, { title: "Mrs" })
|
|
152
162
|
#
|
|
153
|
-
# @param [ Hash
|
|
163
|
+
# @param [ Hash | Array ] attributes The attributes to create with, or an
|
|
154
164
|
# Array of multiple attributes for multiple documents.
|
|
155
165
|
#
|
|
156
|
-
# @return [ Document
|
|
166
|
+
# @return [ Document | Array<Document> ] The newly created document(s).
|
|
157
167
|
def create!(attributes = nil, &block)
|
|
158
168
|
_creating do
|
|
159
169
|
if attributes.is_a?(::Array)
|
|
@@ -16,7 +16,6 @@ module Mongoid
|
|
|
16
16
|
#
|
|
17
17
|
# @return [ TrueClass ] True.
|
|
18
18
|
def delete(options = {})
|
|
19
|
-
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
|
20
19
|
prepare_delete do
|
|
21
20
|
unless options[:persist] == false
|
|
22
21
|
if embedded?
|
|
@@ -86,7 +85,7 @@ module Mongoid
|
|
|
86
85
|
#
|
|
87
86
|
# @param [ Hash ] options The delete options.
|
|
88
87
|
#
|
|
89
|
-
# @return [ true
|
|
88
|
+
# @return [ true | false ] If the parent should be notified.
|
|
90
89
|
def notifying_parent?(options = {})
|
|
91
90
|
!options.delete(:suppress)
|
|
92
91
|
end
|
|
@@ -102,6 +101,7 @@ module Mongoid
|
|
|
102
101
|
#
|
|
103
102
|
# @return [ Object ] The result of the block.
|
|
104
103
|
def prepare_delete
|
|
104
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
|
105
105
|
yield(self)
|
|
106
106
|
freeze
|
|
107
107
|
self.destroyed = true
|
|
@@ -14,7 +14,7 @@ module Mongoid
|
|
|
14
14
|
#
|
|
15
15
|
# @param [ Hash ] options Options to pass to destroy.
|
|
16
16
|
#
|
|
17
|
-
# @return [ true
|
|
17
|
+
# @return [ true | false ] True if successful, false if not.
|
|
18
18
|
def destroy(options = nil)
|
|
19
19
|
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
|
20
20
|
self.flagged_for_destroy = true
|
|
@@ -14,7 +14,13 @@ module Mongoid
|
|
|
14
14
|
#
|
|
15
15
|
# @param [ Hash ] options Options to pass to the save.
|
|
16
16
|
#
|
|
17
|
-
# @
|
|
17
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
|
18
|
+
# attribute will be updated with the current time. When this option is
|
|
19
|
+
# false, none of the embedded documents will be touched. This option is
|
|
20
|
+
# ignored when saving a new document, and the created_at and updated_at
|
|
21
|
+
# will be set to the current time.
|
|
22
|
+
#
|
|
23
|
+
# @return [ true | false ] True if success, false if not.
|
|
18
24
|
def save(options = {})
|
|
19
25
|
if new_record?
|
|
20
26
|
!insert(options).new_record?
|
|
@@ -31,10 +37,16 @@ module Mongoid
|
|
|
31
37
|
#
|
|
32
38
|
# @param [ Hash ] options Options to pass to the save.
|
|
33
39
|
#
|
|
40
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
|
41
|
+
# attribute will be updated with the current time. When this option is
|
|
42
|
+
# false, none of the embedded documents will be touched.This option is
|
|
43
|
+
# ignored when saving a new document, and the created_at and updated_at
|
|
44
|
+
# will be set to the current time.
|
|
45
|
+
#
|
|
34
46
|
# @raise [ Errors::Validations ] If validation failed.
|
|
35
47
|
# @raise [ Errors::Callback ] If a callback returns false.
|
|
36
48
|
#
|
|
37
|
-
# @return [ true
|
|
49
|
+
# @return [ true | false ] True if validation passed.
|
|
38
50
|
def save!(options = {})
|
|
39
51
|
unless save(options)
|
|
40
52
|
fail_due_to_validation! unless errors.empty?
|
|
@@ -13,8 +13,8 @@ module Mongoid
|
|
|
13
13
|
# @example Unset the values.
|
|
14
14
|
# document.unset(:first_name, :last_name, :middle)
|
|
15
15
|
#
|
|
16
|
-
# @param [ Array<String
|
|
17
|
-
# unset.
|
|
16
|
+
# @param [ [ String | Symbol | Array<String | Symbol>]... ] *fields
|
|
17
|
+
# The names of the field(s) to unset.
|
|
18
18
|
#
|
|
19
19
|
# @return [ Document ] The document.
|
|
20
20
|
def unset(*fields)
|
|
@@ -13,13 +13,13 @@ module Mongoid
|
|
|
13
13
|
# @example Update the attribute.
|
|
14
14
|
# person.update_attribute(:title, "Sir")
|
|
15
15
|
#
|
|
16
|
-
# @param [ Symbol
|
|
16
|
+
# @param [ Symbol | String ] name The name of the attribute.
|
|
17
17
|
# @param [ Object ] value The new value of the attribute.a
|
|
18
18
|
#
|
|
19
19
|
# @raise [ Errors::ReadonlyAttribute ] If the field cannot be changed due
|
|
20
20
|
# to being flagged as read-only.
|
|
21
21
|
#
|
|
22
|
-
# @return [ true
|
|
22
|
+
# @return [ true | false ] True if save was successful, false if not.
|
|
23
23
|
def update_attribute(name, value)
|
|
24
24
|
as_writable_attribute!(name, value) do |access|
|
|
25
25
|
normalized = name.to_s
|
|
@@ -35,7 +35,7 @@ module Mongoid
|
|
|
35
35
|
#
|
|
36
36
|
# @param [ Hash ] attributes The attributes to update.
|
|
37
37
|
#
|
|
38
|
-
# @return [ true
|
|
38
|
+
# @return [ true | false ] True if validation passed, false if not.
|
|
39
39
|
def update(attributes = {})
|
|
40
40
|
assign_attributes(attributes)
|
|
41
41
|
save
|
|
@@ -53,7 +53,7 @@ module Mongoid
|
|
|
53
53
|
# @raise [ Errors::Validations ] If validation failed.
|
|
54
54
|
# @raise [ Errors::Callbacks ] If a callback returns false.
|
|
55
55
|
#
|
|
56
|
-
# @return [ true
|
|
56
|
+
# @return [ true | false ] True if validation passed.
|
|
57
57
|
def update!(attributes = {})
|
|
58
58
|
result = update_attributes(attributes)
|
|
59
59
|
unless result
|
|
@@ -91,18 +91,32 @@ module Mongoid
|
|
|
91
91
|
#
|
|
92
92
|
# @param [ Hash ] options The options.
|
|
93
93
|
#
|
|
94
|
-
# @
|
|
94
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
|
95
|
+
# attribute will be updated with the current time.
|
|
96
|
+
#
|
|
97
|
+
# @return [ true | false ] The result of the update.
|
|
95
98
|
def prepare_update(options = {})
|
|
99
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
|
100
|
+
enforce_immutability_of_id_field!
|
|
96
101
|
return false if performing_validations?(options) &&
|
|
97
102
|
invalid?(options[:context] || :update)
|
|
98
103
|
process_flagged_destroys
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
update_children = cascadable_children(:update)
|
|
105
|
+
process_touch_option(options, update_children)
|
|
106
|
+
run_callbacks(:save, with_children: false) do
|
|
107
|
+
run_callbacks(:update, with_children: false) do
|
|
108
|
+
run_callbacks(:persist_parent, with_children: false) do
|
|
109
|
+
_mongoid_run_child_callbacks(:save) do
|
|
110
|
+
_mongoid_run_child_callbacks(:update, children: update_children) do
|
|
111
|
+
result = yield(self)
|
|
112
|
+
self.previously_new_record = false
|
|
113
|
+
post_process_persist(result, options)
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
103
118
|
end
|
|
104
119
|
end
|
|
105
|
-
post_process_persist(result, options) and result
|
|
106
120
|
end
|
|
107
121
|
|
|
108
122
|
# Update the document in the database.
|
|
@@ -112,9 +126,9 @@ module Mongoid
|
|
|
112
126
|
#
|
|
113
127
|
# @param [ Hash ] options Options to pass to update.
|
|
114
128
|
#
|
|
115
|
-
# @option options [ true
|
|
129
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
|
116
130
|
#
|
|
117
|
-
# @return [ true
|
|
131
|
+
# @return [ true | false ] True if succeeded, false if not.
|
|
118
132
|
def update_document(options = {})
|
|
119
133
|
prepare_update(options) do
|
|
120
134
|
updates, conflicts = init_atomic_updates
|
|
@@ -153,6 +167,49 @@ module Mongoid
|
|
|
153
167
|
end
|
|
154
168
|
end
|
|
155
169
|
end
|
|
170
|
+
|
|
171
|
+
# If there is a touch option and it is false, this method will call the
|
|
172
|
+
# timeless method so that the updated_at attribute is not updated. It
|
|
173
|
+
# will call the timeless method on all of the cascadable children as
|
|
174
|
+
# well. Note that timeless is cleared in the before_update callback.
|
|
175
|
+
#
|
|
176
|
+
# @param [ Hash ] options The options.
|
|
177
|
+
# @param [ Array<Document> ] children The children that the :update
|
|
178
|
+
# callbacks will be executed on.
|
|
179
|
+
#
|
|
180
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
|
181
|
+
# attribute will be updated with the current time.
|
|
182
|
+
def process_touch_option(options, children)
|
|
183
|
+
unless options.fetch(:touch, true)
|
|
184
|
+
timeless
|
|
185
|
+
children.each(&:timeless)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Checks to see if the _id field has been modified. If it has, and if
|
|
190
|
+
# the document has already been persisted, this is an error. Otherwise,
|
|
191
|
+
# returns without side-effects.
|
|
192
|
+
#
|
|
193
|
+
# Note that if `Mongoid::Config.immutable_ids` is false, this will do
|
|
194
|
+
# nothing.
|
|
195
|
+
#
|
|
196
|
+
# @raise [ Errors::ImmutableAttribute ] if _id has changed, and document
|
|
197
|
+
# has been persisted.
|
|
198
|
+
def enforce_immutability_of_id_field!
|
|
199
|
+
# special case here: we *do* allow the _id to be mutated if it was
|
|
200
|
+
# previously nil. This addresses an odd case exposed in
|
|
201
|
+
# has_one/proxy_spec.rb where `person.create_address` would
|
|
202
|
+
# (somehow?) create the address with a nil _id first, before then
|
|
203
|
+
# saving it *again* with the correct _id.
|
|
204
|
+
|
|
205
|
+
if _id_changed? && !_id_was.nil? && persisted?
|
|
206
|
+
if Mongoid::Config.immutable_ids
|
|
207
|
+
raise Errors::ImmutableAttribute.new(:_id, _id)
|
|
208
|
+
else
|
|
209
|
+
Mongoid::Warnings.warn_mutable_ids
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
156
213
|
end
|
|
157
214
|
end
|
|
158
215
|
end
|
|
@@ -10,16 +10,32 @@ module Mongoid
|
|
|
10
10
|
# database, then Mongo will insert a new one, otherwise the fields will get
|
|
11
11
|
# overwritten with new values on the existing document.
|
|
12
12
|
#
|
|
13
|
+
# If the replace option is true, unspecified attributes will be dropped,
|
|
14
|
+
# and if it is false, unspecified attributes will be maintained. The
|
|
15
|
+
# replace option defaults to true in Mongoid 8.1 and earlier. The default
|
|
16
|
+
# will be flipped to false in Mongoid 9.
|
|
17
|
+
#
|
|
13
18
|
# @example Upsert the document.
|
|
14
19
|
# document.upsert
|
|
15
20
|
#
|
|
21
|
+
# @example Upsert the document without replace.
|
|
22
|
+
# document.upsert(replace: false)
|
|
23
|
+
#
|
|
16
24
|
# @param [ Hash ] options The validation options.
|
|
17
25
|
#
|
|
26
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
|
27
|
+
# @option options [ true | false ] :replace Whether or not to replace the document on upsert.
|
|
28
|
+
#
|
|
18
29
|
# @return [ true ] True.
|
|
19
30
|
def upsert(options = {})
|
|
20
31
|
prepare_upsert(options) do
|
|
21
|
-
|
|
32
|
+
if options.fetch(:replace, true)
|
|
33
|
+
collection.find(atomic_selector).replace_one(
|
|
22
34
|
as_attributes, upsert: true, session: _session)
|
|
35
|
+
else
|
|
36
|
+
collection.find(atomic_selector).update_one(
|
|
37
|
+
{ "$set" => as_attributes }, upsert: true, session: _session)
|
|
38
|
+
end
|
|
23
39
|
end
|
|
24
40
|
end
|
|
25
41
|
|
|
@@ -36,8 +52,11 @@ module Mongoid
|
|
|
36
52
|
#
|
|
37
53
|
# @param [ Hash ] options The options hash.
|
|
38
54
|
#
|
|
39
|
-
# @
|
|
55
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
|
56
|
+
#
|
|
57
|
+
# @return [ true | false ] If the operation succeeded.
|
|
40
58
|
def prepare_upsert(options = {})
|
|
59
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
|
41
60
|
return false if performing_validations?(options) && invalid?(:upsert)
|
|
42
61
|
result = run_callbacks(:upsert) do
|
|
43
62
|
yield(self)
|
data/lib/mongoid/persistable.rb
CHANGED
|
@@ -79,11 +79,11 @@ module Mongoid
|
|
|
79
79
|
# document.set name: "Tool"
|
|
80
80
|
# end
|
|
81
81
|
#
|
|
82
|
-
# @param [ true
|
|
82
|
+
# @param [ true | false ] join_context Join the context (i.e. merge
|
|
83
83
|
# declared atomic operations) of the atomically block wrapping this one
|
|
84
84
|
# for the same document, if one exists.
|
|
85
85
|
#
|
|
86
|
-
# @return [ true
|
|
86
|
+
# @return [ true | false ] If the operation succeeded.
|
|
87
87
|
def atomically(join_context: nil)
|
|
88
88
|
join_context = Mongoid.join_contexts if join_context.nil?
|
|
89
89
|
call_depth = @atomic_depth ||= 0
|
|
@@ -146,7 +146,7 @@ module Mongoid
|
|
|
146
146
|
# @example Are we executing atomically?
|
|
147
147
|
# document.executing_atomically?
|
|
148
148
|
#
|
|
149
|
-
# @return [ true
|
|
149
|
+
# @return [ true | false ] If we are current executing atomically.
|
|
150
150
|
def executing_atomically?
|
|
151
151
|
!@atomic_updates_to_execute_stack.nil?
|
|
152
152
|
end
|
|
@@ -161,6 +161,8 @@ module Mongoid
|
|
|
161
161
|
# @param [ Object ] result The result of the operation.
|
|
162
162
|
# @param [ Hash ] options The options.
|
|
163
163
|
#
|
|
164
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
|
165
|
+
#
|
|
164
166
|
# @return [ true ] true.
|
|
165
167
|
def post_process_persist(result, options = {})
|
|
166
168
|
post_persist unless result == false
|
|
@@ -180,6 +182,7 @@ module Mongoid
|
|
|
180
182
|
#
|
|
181
183
|
# @return [ Object ] The result of the operation.
|
|
182
184
|
def prepare_atomic_operation
|
|
185
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
|
183
186
|
operations = yield({})
|
|
184
187
|
persist_or_delay_atomic_operation(operations)
|
|
185
188
|
self
|