mongoid 8.0.5 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -3
- data/README.md +3 -3
- data/Rakefile +0 -25
- data/lib/config/locales/en.yml +46 -14
- data/lib/mongoid/association/accessors.rb +2 -2
- data/lib/mongoid/association/builders.rb +1 -1
- data/lib/mongoid/association/embedded/batchable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +6 -6
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +40 -2
- data/lib/mongoid/association/proxy.rb +1 -1
- data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
- data/lib/mongoid/association/reflections.rb +2 -2
- data/lib/mongoid/atomic.rb +0 -7
- data/lib/mongoid/attributes/dynamic.rb +1 -1
- data/lib/mongoid/attributes/nested.rb +2 -2
- data/lib/mongoid/attributes/projector.rb +1 -1
- data/lib/mongoid/attributes/readonly.rb +1 -1
- data/lib/mongoid/attributes.rb +8 -2
- data/lib/mongoid/changeable.rb +107 -5
- data/lib/mongoid/clients/storage_options.rb +2 -5
- data/lib/mongoid/clients/validators/storage.rb +1 -13
- 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/validators/async_query_executor.rb +24 -0
- data/lib/mongoid/config/validators.rb +1 -0
- data/lib/mongoid/config.rb +101 -0
- data/lib/mongoid/contextual/atomic.rb +1 -1
- data/lib/mongoid/contextual/memory.rb +233 -33
- data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
- data/lib/mongoid/contextual/mongo.rb +373 -113
- data/lib/mongoid/contextual/none.rb +162 -7
- data/lib/mongoid/contextual.rb +12 -0
- data/lib/mongoid/criteria/findable.rb +2 -2
- data/lib/mongoid/criteria/includable.rb +4 -3
- data/lib/mongoid/criteria/queryable/key.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
- data/lib/mongoid/criteria/queryable/optional.rb +8 -8
- data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
- data/lib/mongoid/criteria.rb +6 -5
- data/lib/mongoid/deprecable.rb +1 -1
- data/lib/mongoid/errors/create_collection_failure.rb +33 -0
- 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_global_executor_concurrency.rb +22 -0
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
- data/lib/mongoid/errors.rb +4 -1
- data/lib/mongoid/extensions/object.rb +2 -2
- data/lib/mongoid/extensions/time.rb +2 -0
- data/lib/mongoid/fields/localized.rb +10 -0
- data/lib/mongoid/fields/standard.rb +10 -0
- data/lib/mongoid/fields.rb +69 -13
- data/lib/mongoid/findable.rb +27 -3
- data/lib/mongoid/interceptable.rb +7 -6
- data/lib/mongoid/matcher/eq_impl.rb +1 -1
- data/lib/mongoid/matcher/type.rb +1 -1
- data/lib/mongoid/persistable/creatable.rb +1 -0
- data/lib/mongoid/persistable/deletable.rb +1 -1
- data/lib/mongoid/persistable/savable.rb +13 -1
- data/lib/mongoid/persistable/unsettable.rb +2 -2
- data/lib/mongoid/persistable/updatable.rb +51 -1
- data/lib/mongoid/persistable/upsertable.rb +20 -1
- data/lib/mongoid/persistable.rb +3 -0
- data/lib/mongoid/query_cache.rb +5 -1
- data/lib/mongoid/railties/database.rake +7 -2
- data/lib/mongoid/reloadable.rb +5 -3
- data/lib/mongoid/stateful.rb +22 -1
- data/lib/mongoid/tasks/database.rake +12 -0
- data/lib/mongoid/tasks/database.rb +20 -0
- data/lib/mongoid/utils.rb +22 -0
- data/lib/mongoid/validatable/macros.rb +5 -5
- data/lib/mongoid/validatable.rb +4 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/warnings.rb +17 -1
- data/lib/mongoid.rb +16 -3
- data/spec/integration/app_spec.rb +2 -2
- data/spec/integration/callbacks_models.rb +37 -0
- data/spec/integration/callbacks_spec.rb +134 -0
- data/spec/integration/discriminator_key_spec.rb +4 -5
- data/spec/integration/i18n_fallbacks_spec.rb +3 -2
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
- data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
- data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +5 -27
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
- data/spec/mongoid/association/syncable_spec.rb +1 -1
- data/spec/mongoid/attributes_spec.rb +3 -6
- data/spec/mongoid/changeable_spec.rb +299 -24
- data/spec/mongoid/clients_spec.rb +122 -13
- data/spec/mongoid/collection_configurable_spec.rb +158 -0
- data/spec/mongoid/config/defaults_spec.rb +160 -0
- data/spec/mongoid/config_spec.rb +154 -18
- data/spec/mongoid/contextual/memory_spec.rb +332 -76
- data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
- data/spec/mongoid/contextual/mongo_spec.rb +995 -36
- data/spec/mongoid/contextual/none_spec.rb +49 -2
- data/spec/mongoid/copyable_spec.rb +3 -11
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
- data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selector_spec.rb +1 -1
- data/spec/mongoid/criteria_projection_spec.rb +1 -4
- data/spec/mongoid/criteria_spec.rb +5 -9
- data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
- data/spec/mongoid/extensions/time_spec.rb +8 -43
- data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
- data/spec/mongoid/fields/localized_spec.rb +46 -28
- data/spec/mongoid/fields_spec.rb +136 -34
- data/spec/mongoid/findable_spec.rb +391 -34
- data/spec/mongoid/indexable_spec.rb +16 -10
- data/spec/mongoid/interceptable_spec.rb +15 -3
- data/spec/mongoid/persistable/deletable_spec.rb +26 -6
- data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
- 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 +80 -6
- data/spec/mongoid/persistence_context_spec.rb +7 -57
- data/spec/mongoid/query_cache_spec.rb +56 -61
- data/spec/mongoid/reloadable_spec.rb +24 -28
- data/spec/mongoid/scopable_spec.rb +70 -0
- data/spec/mongoid/serializable_spec.rb +9 -30
- data/spec/mongoid/stateful_spec.rb +122 -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 +9 -11
- data/spec/mongoid/touchable_spec.rb +277 -5
- data/spec/mongoid/touchable_spec_models.rb +3 -1
- data/spec/mongoid/traversable_spec.rb +9 -24
- data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
- data/spec/mongoid_spec.rb +36 -10
- data/spec/shared/lib/mrss/docker_runner.rb +7 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
- data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
- data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
- data/spec/shared/lib/mrss/utils.rb +28 -6
- data/spec/shared/share/Dockerfile.erb +36 -40
- data/spec/shared/shlib/server.sh +32 -8
- data/spec/shared/shlib/set_env.sh +4 -4
- data/spec/spec_helper.rb +5 -0
- data/spec/support/immutable_ids.rb +118 -0
- data/spec/support/macros.rb +47 -15
- data/spec/support/models/artist.rb +0 -1
- data/spec/support/models/band.rb +1 -0
- data/spec/support/models/book.rb +1 -0
- data/spec/support/models/building.rb +2 -0
- data/spec/support/models/cover.rb +10 -0
- data/spec/support/models/product.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +686 -650
- metadata.gz.sig +0 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Errors
|
5
|
+
|
6
|
+
# This error is raised when a bad global executor concurrency option is attempted
|
7
|
+
# to be set.
|
8
|
+
class InvalidGlobalExecutorConcurrency < MongoidError
|
9
|
+
|
10
|
+
# Create the new error.
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def initialize
|
14
|
+
super(
|
15
|
+
compose_message(
|
16
|
+
"invalid_global_executor_concurrency"
|
17
|
+
)
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/mongoid/errors.rb
CHANGED
@@ -3,11 +3,14 @@
|
|
3
3
|
require "mongoid/errors/mongoid_error"
|
4
4
|
require "mongoid/errors/ambiguous_relationship"
|
5
5
|
require "mongoid/errors/callback"
|
6
|
+
require "mongoid/errors/create_collection_failure"
|
6
7
|
require "mongoid/errors/criteria_argument_required"
|
7
8
|
require "mongoid/errors/document_not_destroyed"
|
8
9
|
require "mongoid/errors/document_not_found"
|
9
10
|
require "mongoid/errors/empty_config_file"
|
11
|
+
require "mongoid/errors/immutable_attribute"
|
10
12
|
require "mongoid/errors/in_memory_collation_not_supported"
|
13
|
+
require "mongoid/errors/invalid_async_query_executor"
|
11
14
|
require "mongoid/errors/invalid_collection"
|
12
15
|
require "mongoid/errors/invalid_config_file"
|
13
16
|
require "mongoid/errors/invalid_config_option"
|
@@ -16,6 +19,7 @@ require "mongoid/errors/invalid_field"
|
|
16
19
|
require "mongoid/errors/invalid_field_option"
|
17
20
|
require "mongoid/errors/invalid_field_type"
|
18
21
|
require "mongoid/errors/invalid_find"
|
22
|
+
require "mongoid/errors/invalid_global_executor_concurrency"
|
19
23
|
require "mongoid/errors/invalid_includes"
|
20
24
|
require "mongoid/errors/invalid_index"
|
21
25
|
require "mongoid/errors/invalid_options"
|
@@ -35,7 +39,6 @@ require "mongoid/errors/invalid_scope"
|
|
35
39
|
require "mongoid/errors/invalid_session_use"
|
36
40
|
require "mongoid/errors/invalid_set_polymorphic_relation"
|
37
41
|
require "mongoid/errors/invalid_storage_options"
|
38
|
-
require "mongoid/errors/invalid_storage_parent"
|
39
42
|
require "mongoid/errors/invalid_time"
|
40
43
|
require "mongoid/errors/inverse_not_found"
|
41
44
|
require "mongoid/errors/mixed_relations"
|
@@ -91,7 +91,7 @@ module Mongoid
|
|
91
91
|
# object.do_or_do_not(:use, "The Force")
|
92
92
|
#
|
93
93
|
# @param [ String | Symbol ] name The method name.
|
94
|
-
# @param [
|
94
|
+
# @param [ Object... ] *args The arguments.
|
95
95
|
#
|
96
96
|
# @return [ Object | nil ] The result of the method call or nil if the
|
97
97
|
# method does not exist.
|
@@ -190,7 +190,7 @@ module Mongoid
|
|
190
190
|
# object.you_must(:use, "The Force")
|
191
191
|
#
|
192
192
|
# @param [ String | Symbol ] name The method name.
|
193
|
-
# @param [
|
193
|
+
# @param [ Object... ] *args The arguments.
|
194
194
|
#
|
195
195
|
# @return [ Object | nil ] The result of the method call or nil if the
|
196
196
|
# method does not exist. Nil if the object is frozen.
|
@@ -31,6 +31,16 @@ module Mongoid
|
|
31
31
|
true
|
32
32
|
end
|
33
33
|
|
34
|
+
# Is the localized field enforcing values to be present?
|
35
|
+
#
|
36
|
+
# @example Is the localized field enforcing values to be present?
|
37
|
+
# field.localize_present?
|
38
|
+
#
|
39
|
+
# @return [ true | false ] If the field enforces present.
|
40
|
+
def localize_present?
|
41
|
+
options[:localize] == :present
|
42
|
+
end
|
43
|
+
|
34
44
|
# Convert the provided string into a hash for the locale.
|
35
45
|
#
|
36
46
|
# @example Serialize the value.
|
@@ -97,6 +97,16 @@ module Mongoid
|
|
97
97
|
false
|
98
98
|
end
|
99
99
|
|
100
|
+
# Is the localized field enforcing values to be present?
|
101
|
+
#
|
102
|
+
# @example Is the localized field enforcing values to be present?
|
103
|
+
# field.localize_present?
|
104
|
+
#
|
105
|
+
# @return [ true | false ] If the field enforces present.
|
106
|
+
def localize_present?
|
107
|
+
false
|
108
|
+
end
|
109
|
+
|
100
110
|
# Get the metadata for the field if its a foreign key.
|
101
111
|
#
|
102
112
|
# @example Get the metadata.
|
data/lib/mongoid/fields.rb
CHANGED
@@ -538,6 +538,8 @@ module Mongoid
|
|
538
538
|
# Model.add_defaults(field)
|
539
539
|
#
|
540
540
|
# @param [ Field ] field The field to add for.
|
541
|
+
#
|
542
|
+
# @api private
|
541
543
|
def add_defaults(field)
|
542
544
|
default, name = field.default_val, field.name.to_s
|
543
545
|
remove_defaults(name)
|
@@ -557,6 +559,8 @@ module Mongoid
|
|
557
559
|
#
|
558
560
|
# @param [ Symbol ] name The name of the field.
|
559
561
|
# @param [ Hash ] options The hash of options.
|
562
|
+
#
|
563
|
+
# @api private
|
560
564
|
def add_field(name, options = {})
|
561
565
|
aliased = options[:as]
|
562
566
|
aliased_fields[aliased.to_s] = name if aliased
|
@@ -584,6 +588,8 @@ module Mongoid
|
|
584
588
|
# # => "called"
|
585
589
|
#
|
586
590
|
# @param [ Field ] field the field to process
|
591
|
+
#
|
592
|
+
# @api private
|
587
593
|
def process_options(field)
|
588
594
|
field_options = field.options
|
589
595
|
|
@@ -606,6 +612,8 @@ module Mongoid
|
|
606
612
|
# @param [ Symbol ] name The name of the field.
|
607
613
|
# @param [ Symbol ] meth The name of the accessor.
|
608
614
|
# @param [ Hash ] options The options.
|
615
|
+
#
|
616
|
+
# @api private
|
609
617
|
def create_accessors(name, meth, options = {})
|
610
618
|
field = fields[name]
|
611
619
|
|
@@ -629,6 +637,8 @@ module Mongoid
|
|
629
637
|
# @param [ String ] name The name of the attribute.
|
630
638
|
# @param [ String ] meth The name of the method.
|
631
639
|
# @param [ Field ] field The field.
|
640
|
+
#
|
641
|
+
# @api private
|
632
642
|
def create_field_getter(name, meth, field)
|
633
643
|
generated_methods.module_eval do
|
634
644
|
re_define_method(meth) do
|
@@ -651,6 +661,8 @@ module Mongoid
|
|
651
661
|
#
|
652
662
|
# @param [ String ] name The name of the attribute.
|
653
663
|
# @param [ String ] meth The name of the method.
|
664
|
+
#
|
665
|
+
# @api private
|
654
666
|
def create_field_getter_before_type_cast(name, meth)
|
655
667
|
generated_methods.module_eval do
|
656
668
|
re_define_method("#{meth}_before_type_cast") do
|
@@ -671,6 +683,8 @@ module Mongoid
|
|
671
683
|
# @param [ String ] name The name of the attribute.
|
672
684
|
# @param [ String ] meth The name of the method.
|
673
685
|
# @param [ Field ] field The field.
|
686
|
+
#
|
687
|
+
# @api private
|
674
688
|
def create_field_setter(name, meth, field)
|
675
689
|
generated_methods.module_eval do
|
676
690
|
re_define_method("#{meth}=") do |value|
|
@@ -690,6 +704,8 @@ module Mongoid
|
|
690
704
|
#
|
691
705
|
# @param [ String ] name The name of the attribute.
|
692
706
|
# @param [ String ] meth The name of the method.
|
707
|
+
#
|
708
|
+
# @api private
|
693
709
|
def create_field_check(name, meth)
|
694
710
|
generated_methods.module_eval do
|
695
711
|
re_define_method("#{meth}?") do
|
@@ -706,6 +722,8 @@ module Mongoid
|
|
706
722
|
#
|
707
723
|
# @param [ String ] name The name of the attribute.
|
708
724
|
# @param [ String ] meth The name of the method.
|
725
|
+
#
|
726
|
+
# @api private
|
709
727
|
def create_translations_getter(name, meth)
|
710
728
|
generated_methods.module_eval do
|
711
729
|
re_define_method("#{meth}_translations") do
|
@@ -724,6 +742,8 @@ module Mongoid
|
|
724
742
|
# @param [ String ] name The name of the attribute.
|
725
743
|
# @param [ String ] meth The name of the method.
|
726
744
|
# @param [ Field ] field The field.
|
745
|
+
#
|
746
|
+
# @api private
|
727
747
|
def create_translations_setter(name, meth, field)
|
728
748
|
generated_methods.module_eval do
|
729
749
|
re_define_method("#{meth}_translations=") do |value|
|
@@ -743,6 +763,8 @@ module Mongoid
|
|
743
763
|
# Person.generated_methods
|
744
764
|
#
|
745
765
|
# @return [ Module ] The module of generated methods.
|
766
|
+
#
|
767
|
+
# @api private
|
746
768
|
def generated_methods
|
747
769
|
@generated_methods ||= begin
|
748
770
|
mod = Module.new
|
@@ -757,21 +779,49 @@ module Mongoid
|
|
757
779
|
# Model.remove_defaults(name)
|
758
780
|
#
|
759
781
|
# @param [ String ] name The field name.
|
782
|
+
#
|
783
|
+
# @api private
|
760
784
|
def remove_defaults(name)
|
761
785
|
pre_processed_defaults.delete_one(name)
|
762
786
|
post_processed_defaults.delete_one(name)
|
763
787
|
end
|
764
788
|
|
789
|
+
# Create a field for the given name and options.
|
790
|
+
#
|
791
|
+
# @param [ Symbol ] name The name of the field.
|
792
|
+
# @param [ Hash ] options The hash of options.
|
793
|
+
#
|
794
|
+
# @return [ Field ] The created field.
|
795
|
+
#
|
796
|
+
# @api private
|
765
797
|
def field_for(name, options)
|
766
798
|
opts = options.merge(klass: self)
|
767
|
-
|
768
|
-
|
769
|
-
if
|
770
|
-
|
799
|
+
opts[:type] = retrieve_and_validate_type(name, options[:type])
|
800
|
+
return Fields::Localized.new(name, opts) if options[:localize]
|
801
|
+
return Fields::ForeignKey.new(name, opts) if options[:identity]
|
802
|
+
Fields::Standard.new(name, opts)
|
803
|
+
end
|
804
|
+
|
805
|
+
# Get the class for the given type.
|
806
|
+
#
|
807
|
+
# @param [ Symbol ] name The name of the field.
|
808
|
+
# @param [ Symbol | Class ] type The type of the field.
|
809
|
+
#
|
810
|
+
# @return [ Class ] The type of the field.
|
811
|
+
#
|
812
|
+
# @raises [ Mongoid::Errors::InvalidFieldType ] if given an invalid field
|
813
|
+
# type.
|
814
|
+
#
|
815
|
+
# @api private
|
816
|
+
def retrieve_and_validate_type(name, type)
|
817
|
+
type_mapping = TYPE_MAPPINGS[type]
|
818
|
+
result = type_mapping || unmapped_type(type)
|
819
|
+
if !result.is_a?(Class)
|
820
|
+
raise Errors::InvalidFieldType.new(self, name, type)
|
771
821
|
else
|
772
|
-
if INVALID_BSON_CLASSES.include?(
|
773
|
-
warn_message = "Using #{
|
774
|
-
if
|
822
|
+
if INVALID_BSON_CLASSES.include?(result)
|
823
|
+
warn_message = "Using #{result} as the field type is not supported. "
|
824
|
+
if result == BSON::Decimal128
|
775
825
|
warn_message += "In BSON <= 4, the BSON::Decimal128 type will work as expected for both storing and querying, but will return a BigDecimal on query in BSON 5+."
|
776
826
|
else
|
777
827
|
warn_message += "Saving values of this type to the database will work as expected, however, querying them will return a value of the native Ruby Integer type."
|
@@ -779,16 +829,22 @@ module Mongoid
|
|
779
829
|
Mongoid.logger.warn(warn_message)
|
780
830
|
end
|
781
831
|
end
|
782
|
-
|
783
|
-
return Fields::ForeignKey.new(name, opts) if options[:identity]
|
784
|
-
Fields::Standard.new(name, opts)
|
832
|
+
result
|
785
833
|
end
|
786
834
|
|
787
|
-
|
788
|
-
|
835
|
+
# Returns the type of the field if the type was not in the TYPE_MAPPINGS
|
836
|
+
# hash.
|
837
|
+
#
|
838
|
+
# @param [ Symbol | Class ] type The type of the field.
|
839
|
+
#
|
840
|
+
# @return [ Class ] The type of the field.
|
841
|
+
#
|
842
|
+
# @api private
|
843
|
+
def unmapped_type(type)
|
844
|
+
if "Boolean" == type.to_s
|
789
845
|
Mongoid::Boolean
|
790
846
|
else
|
791
|
-
|
847
|
+
type || Object
|
792
848
|
end
|
793
849
|
end
|
794
850
|
end
|
data/lib/mongoid/findable.rb
CHANGED
@@ -22,18 +22,24 @@ module Mongoid
|
|
22
22
|
:each,
|
23
23
|
:each_with_index,
|
24
24
|
:extras,
|
25
|
+
:fifth,
|
26
|
+
:fifth!,
|
25
27
|
:find_one_and_delete,
|
26
28
|
:find_one_and_replace,
|
27
29
|
:find_one_and_update,
|
28
30
|
:find_or_create_by,
|
29
31
|
:find_or_create_by!,
|
30
32
|
:find_or_initialize_by,
|
33
|
+
:first!,
|
31
34
|
:first_or_create,
|
32
35
|
:first_or_create!,
|
33
36
|
:first_or_initialize,
|
34
37
|
:for_js,
|
38
|
+
:fourth,
|
39
|
+
:fourth!,
|
35
40
|
:geo_near,
|
36
41
|
:includes,
|
42
|
+
:last!,
|
37
43
|
:map_reduce,
|
38
44
|
:max,
|
39
45
|
:min,
|
@@ -41,11 +47,19 @@ module Mongoid
|
|
41
47
|
:pick,
|
42
48
|
:pluck,
|
43
49
|
:read,
|
50
|
+
:second,
|
51
|
+
:second!,
|
52
|
+
:second_to_last,
|
53
|
+
:second_to_last!,
|
44
54
|
:sum,
|
45
55
|
:take,
|
46
56
|
:take!,
|
47
57
|
:tally,
|
48
58
|
:text_search,
|
59
|
+
:third,
|
60
|
+
:third!,
|
61
|
+
:third_to_last,
|
62
|
+
:third_to_last!,
|
49
63
|
:update,
|
50
64
|
:update_all,
|
51
65
|
|
@@ -87,9 +101,19 @@ module Mongoid
|
|
87
101
|
# @example Do any documents exist for the conditions?
|
88
102
|
# Person.exists?
|
89
103
|
#
|
104
|
+
# @example Do any documents exist for given _id.
|
105
|
+
# Person.exists?(BSON::ObjectId(...))
|
106
|
+
#
|
107
|
+
# @example Do any documents exist for given conditions.
|
108
|
+
# Person.exists?(name: "...")
|
109
|
+
#
|
110
|
+
# @param [ Hash | Object | false ] id_or_conditions an _id to
|
111
|
+
# search for, a hash of conditions, nil or false.
|
112
|
+
#
|
90
113
|
# @return [ true | false ] If any documents exist for the conditions.
|
91
|
-
|
92
|
-
|
114
|
+
# Always false if passed nil or false.
|
115
|
+
def exists?(id_or_conditions = :none)
|
116
|
+
with_default_scope.exists?(id_or_conditions)
|
93
117
|
end
|
94
118
|
|
95
119
|
# Finds a +Document+ or multiple documents by their _id values.
|
@@ -135,7 +159,7 @@ module Mongoid
|
|
135
159
|
# @note Each argument can be an individual id, an array of ids or
|
136
160
|
# a nested array. Each array will be flattened.
|
137
161
|
#
|
138
|
-
# @param [ Object | Array<Object> ] *args The
|
162
|
+
# @param [ [ Object | Array<Object> ]... ] *args The id(s) to find.
|
139
163
|
#
|
140
164
|
# @return [ Document | Array<Document> | nil ] A document or matching documents.
|
141
165
|
#
|
@@ -79,7 +79,7 @@ module Mongoid
|
|
79
79
|
# @example Run only the after save callbacks.
|
80
80
|
# model.run_after_callbacks(:save)
|
81
81
|
#
|
82
|
-
# @param [
|
82
|
+
# @param [ Symbol... ] *kinds The events that are occurring.
|
83
83
|
#
|
84
84
|
# @return [ Object ] The result of the chain executing.
|
85
85
|
def run_after_callbacks(*kinds)
|
@@ -96,7 +96,7 @@ module Mongoid
|
|
96
96
|
# @example Run only the before save callbacks.
|
97
97
|
# model.run_before_callbacks(:save, :create)
|
98
98
|
#
|
99
|
-
# @param [
|
99
|
+
# @param [ Symbol... ] *kinds The events that are occurring.
|
100
100
|
#
|
101
101
|
# @return [ Object ] The result of the chain executing.
|
102
102
|
def run_before_callbacks(*kinds)
|
@@ -134,19 +134,20 @@ module Mongoid
|
|
134
134
|
# Run the callbacks for embedded documents.
|
135
135
|
#
|
136
136
|
# @param [ Symbol ] kind The type of callback to execute.
|
137
|
-
# @param [ Array<Document> ] children Children to
|
137
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
138
138
|
# nil, callbacks will be executed on all cascadable children of
|
139
139
|
# the document.
|
140
140
|
#
|
141
141
|
# @api private
|
142
142
|
def _mongoid_run_child_callbacks(kind, children: nil, &block)
|
143
143
|
child, *tail = (children || cascadable_children(kind))
|
144
|
+
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
144
145
|
if child.nil?
|
145
|
-
|
146
|
+
block&.call
|
146
147
|
elsif tail.empty?
|
147
|
-
|
148
|
+
child.run_callbacks(child_callback_type(kind, child), with_children: with_children, &block)
|
148
149
|
else
|
149
|
-
|
150
|
+
child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
|
150
151
|
_mongoid_run_child_callbacks(kind, children: tail, &block)
|
151
152
|
end
|
152
153
|
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
@@ -100,6 +100,7 @@ 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(:save, with_children: false) do
|
@@ -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?
|
@@ -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,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,6 +37,12 @@ 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
|
#
|
@@ -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 | Symbol> ] fields
|
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)
|
@@ -91,16 +91,23 @@ module Mongoid
|
|
91
91
|
#
|
92
92
|
# @param [ Hash ] options The options.
|
93
93
|
#
|
94
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
95
|
+
# attribute will be updated with the current time.
|
96
|
+
#
|
94
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
|
104
|
+
update_children = cascadable_children(:update)
|
105
|
+
process_touch_option(options, update_children)
|
99
106
|
run_callbacks(:save, with_children: false) do
|
100
107
|
run_callbacks(:update, with_children: false) do
|
101
108
|
run_callbacks(:persist_parent, with_children: false) do
|
102
109
|
_mongoid_run_child_callbacks(:save) do
|
103
|
-
_mongoid_run_child_callbacks(:update) do
|
110
|
+
_mongoid_run_child_callbacks(:update, children: update_children) do
|
104
111
|
result = yield(self)
|
105
112
|
self.previously_new_record = false
|
106
113
|
post_process_persist(result, options)
|
@@ -160,6 +167,49 @@ module Mongoid
|
|
160
167
|
end
|
161
168
|
end
|
162
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
|
163
213
|
end
|
164
214
|
end
|
165
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
|
#
|
55
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
56
|
+
#
|
39
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
@@ -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
|