mongoid 8.0.8 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +3 -3
  4. data/README.md +3 -3
  5. data/Rakefile +0 -25
  6. data/lib/config/locales/en.yml +46 -14
  7. data/lib/mongoid/association/accessors.rb +2 -2
  8. data/lib/mongoid/association/builders.rb +1 -1
  9. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  10. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  11. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  12. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  13. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +6 -6
  14. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  15. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  16. data/lib/mongoid/association/macros.rb +0 -6
  17. data/lib/mongoid/association/nested/one.rb +40 -2
  18. data/lib/mongoid/association/proxy.rb +1 -1
  19. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  21. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  22. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
  23. data/lib/mongoid/association/reflections.rb +2 -2
  24. data/lib/mongoid/atomic.rb +7 -16
  25. data/lib/mongoid/attributes/dynamic.rb +1 -1
  26. data/lib/mongoid/attributes/nested.rb +2 -2
  27. data/lib/mongoid/attributes/processing.rb +5 -29
  28. data/lib/mongoid/attributes/projector.rb +1 -1
  29. data/lib/mongoid/attributes/readonly.rb +1 -1
  30. data/lib/mongoid/attributes.rb +8 -2
  31. data/lib/mongoid/changeable.rb +107 -5
  32. data/lib/mongoid/clients/storage_options.rb +2 -5
  33. data/lib/mongoid/clients/validators/storage.rb +1 -13
  34. data/lib/mongoid/collection_configurable.rb +58 -0
  35. data/lib/mongoid/composable.rb +2 -0
  36. data/lib/mongoid/config/defaults.rb +60 -0
  37. data/lib/mongoid/config/options.rb +0 -3
  38. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  39. data/lib/mongoid/config/validators.rb +1 -0
  40. data/lib/mongoid/config.rb +99 -28
  41. data/lib/mongoid/contextual/atomic.rb +1 -1
  42. data/lib/mongoid/contextual/memory.rb +233 -33
  43. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  44. data/lib/mongoid/contextual/mongo.rb +370 -133
  45. data/lib/mongoid/contextual/none.rb +162 -7
  46. data/lib/mongoid/contextual.rb +12 -0
  47. data/lib/mongoid/criteria/findable.rb +2 -2
  48. data/lib/mongoid/criteria/includable.rb +4 -3
  49. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  50. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  51. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  52. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  53. data/lib/mongoid/criteria/queryable/selector.rb +1 -1
  54. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  55. data/lib/mongoid/criteria.rb +6 -5
  56. data/lib/mongoid/deprecable.rb +1 -2
  57. data/lib/mongoid/deprecation.rb +3 -3
  58. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  59. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  60. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  61. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  62. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  63. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  64. data/lib/mongoid/errors.rb +4 -1
  65. data/lib/mongoid/extensions/hash.rb +2 -24
  66. data/lib/mongoid/extensions/object.rb +2 -2
  67. data/lib/mongoid/extensions/time.rb +2 -0
  68. data/lib/mongoid/fields/localized.rb +10 -0
  69. data/lib/mongoid/fields/standard.rb +10 -0
  70. data/lib/mongoid/fields.rb +53 -24
  71. data/lib/mongoid/findable.rb +27 -3
  72. data/lib/mongoid/interceptable.rb +10 -118
  73. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  74. data/lib/mongoid/matcher/type.rb +1 -1
  75. data/lib/mongoid/persistable/creatable.rb +1 -0
  76. data/lib/mongoid/persistable/deletable.rb +1 -1
  77. data/lib/mongoid/persistable/savable.rb +13 -1
  78. data/lib/mongoid/persistable/unsettable.rb +2 -2
  79. data/lib/mongoid/persistable/updatable.rb +51 -1
  80. data/lib/mongoid/persistable/upsertable.rb +20 -1
  81. data/lib/mongoid/persistable.rb +3 -0
  82. data/lib/mongoid/query_cache.rb +5 -1
  83. data/lib/mongoid/railties/database.rake +7 -2
  84. data/lib/mongoid/reloadable.rb +5 -3
  85. data/lib/mongoid/stateful.rb +22 -1
  86. data/lib/mongoid/tasks/database.rake +12 -0
  87. data/lib/mongoid/tasks/database.rb +20 -0
  88. data/lib/mongoid/utils.rb +22 -0
  89. data/lib/mongoid/validatable/associated.rb +18 -96
  90. data/lib/mongoid/validatable/macros.rb +5 -5
  91. data/lib/mongoid/validatable.rb +4 -9
  92. data/lib/mongoid/version.rb +1 -1
  93. data/lib/mongoid/warnings.rb +17 -1
  94. data/lib/mongoid.rb +16 -3
  95. data/spec/integration/app_spec.rb +2 -2
  96. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +0 -40
  97. data/spec/integration/callbacks_models.rb +37 -0
  98. data/spec/integration/callbacks_spec.rb +126 -12
  99. data/spec/integration/discriminator_key_spec.rb +4 -5
  100. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  101. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  102. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
  103. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  104. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  105. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  106. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +5 -27
  107. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
  108. data/spec/mongoid/association/syncable_spec.rb +1 -1
  109. data/spec/mongoid/attributes_spec.rb +3 -33
  110. data/spec/mongoid/changeable_spec.rb +299 -24
  111. data/spec/mongoid/clients_spec.rb +122 -13
  112. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  113. data/spec/mongoid/config/defaults_spec.rb +160 -0
  114. data/spec/mongoid/config_spec.rb +154 -27
  115. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  116. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  117. data/spec/mongoid/contextual/mongo_spec.rb +1009 -125
  118. data/spec/mongoid/contextual/none_spec.rb +49 -2
  119. data/spec/mongoid/copyable_spec.rb +2 -10
  120. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
  121. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  122. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  123. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  124. data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -76
  125. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  126. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  127. data/spec/mongoid/criteria_spec.rb +5 -9
  128. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  129. data/spec/mongoid/extensions/hash_spec.rb +3 -3
  130. data/spec/mongoid/extensions/time_spec.rb +8 -43
  131. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  132. data/spec/mongoid/fields/localized_spec.rb +46 -28
  133. data/spec/mongoid/fields_spec.rb +136 -77
  134. data/spec/mongoid/findable_spec.rb +391 -34
  135. data/spec/mongoid/indexable_spec.rb +16 -10
  136. data/spec/mongoid/interceptable_spec.rb +173 -362
  137. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  138. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  139. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  140. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  141. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  142. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  143. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  144. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  145. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  146. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  147. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  148. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  149. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  150. data/spec/mongoid/persistence_context_spec.rb +7 -57
  151. data/spec/mongoid/query_cache_spec.rb +56 -61
  152. data/spec/mongoid/reloadable_spec.rb +24 -28
  153. data/spec/mongoid/scopable_spec.rb +70 -0
  154. data/spec/mongoid/serializable_spec.rb +9 -30
  155. data/spec/mongoid/stateful_spec.rb +122 -8
  156. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  157. data/spec/mongoid/tasks/database_spec.rb +127 -0
  158. data/spec/mongoid/timestamps_spec.rb +9 -11
  159. data/spec/mongoid/touchable_spec.rb +277 -5
  160. data/spec/mongoid/touchable_spec_models.rb +3 -1
  161. data/spec/mongoid/traversable_spec.rb +9 -24
  162. data/spec/mongoid/validatable/associated_spec.rb +30 -13
  163. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  164. data/spec/mongoid_spec.rb +36 -10
  165. data/spec/spec_helper.rb +5 -0
  166. data/spec/support/immutable_ids.rb +118 -0
  167. data/spec/support/macros.rb +47 -15
  168. data/spec/support/models/artist.rb +0 -1
  169. data/spec/support/models/band.rb +1 -0
  170. data/spec/support/models/book.rb +1 -0
  171. data/spec/support/models/building.rb +2 -0
  172. data/spec/support/models/cover.rb +10 -0
  173. data/spec/support/models/name.rb +0 -10
  174. data/spec/support/models/person.rb +0 -1
  175. data/spec/support/models/product.rb +1 -0
  176. data.tar.gz.sig +0 -0
  177. metadata +698 -664
  178. metadata.gz.sig +0 -0
  179. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  180. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  181. data/spec/support/models/purse.rb +0 -9
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Errors
5
+
6
+ # This error is raised when attempting the change the value of an
7
+ # immutable attribute. For example, the _id attribute is immutable,
8
+ # and attempting to change it on a document that has already been
9
+ # persisted will result in this error.
10
+ class ImmutableAttribute < MongoidError
11
+
12
+ # Create the new error.
13
+ #
14
+ # @example Create the new error.
15
+ # ImmutableAttribute.new(:_id, "1234")
16
+ #
17
+ # @param [ Symbol | String ] name The name of the attribute.
18
+ # @param [ Object ] value The attempted set value.
19
+ def initialize(name, value)
20
+ super(
21
+ compose_message("immutable_attribute", { name: name, value: value })
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Errors
5
+
6
+ # This error is raised when a bad async query executor option is attempted
7
+ # to be set.
8
+ class InvalidQueryExecutor < MongoidError
9
+
10
+ # Create the new error.
11
+ #
12
+ # @param [ Symbol | String ] executor The attempted async query executor.
13
+ #
14
+ # @api private
15
+ def initialize(executor)
16
+ super(
17
+ compose_message(
18
+ "invalid_async_query_executor",
19
+ { executor: executor, options: [:immediate, :global_thread_pool] }
20
+ )
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -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
@@ -4,6 +4,8 @@ module Mongoid
4
4
  module Errors
5
5
 
6
6
  # Raised when calling store_in in a sub-class of Mongoid::Document
7
+ #
8
+ # @deprecated
7
9
  class InvalidStorageParent < MongoidError
8
10
 
9
11
  # Create the new error.
@@ -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"
@@ -38,12 +38,8 @@ module Mongoid
38
38
  consolidated = {}
39
39
  each_pair do |key, value|
40
40
  if key =~ /\$/
41
- value.keys.each do |key2|
42
- value2 = value[key2]
43
- real_key = klass.database_field_name(key2)
44
-
45
- value.delete(key2) if real_key != key2
46
- value[real_key] = value_for(key, klass, real_key, value2)
41
+ value.each_pair do |_key, _value|
42
+ value[_key] = (key == "$rename") ? _value.to_s : mongoize_for(key, klass, _key, _value)
47
43
  end
48
44
  consolidated[key] ||= {}
49
45
  consolidated[key].update(value)
@@ -185,24 +181,6 @@ module Mongoid
185
181
 
186
182
  private
187
183
 
188
- # Get the value for the provided operator, klass, key and value.
189
- #
190
- # This is necessary for special cases like $rename, $addToSet and $push.
191
- #
192
- # @param [ String ] operator The operator.
193
- # @param [ Class ] klass The model class.
194
- # @param [ String | Symbol ] key The field key.
195
- # @param [ Object ] value The original value.
196
- #
197
- # @return [ Object ] Value prepared for the provided operator.
198
- def value_for(operator, klass, key, value)
199
- case operator
200
- when "$rename" then value.to_s
201
- when "$addToSet", "$push" then value.mongoize
202
- else mongoize_for(operator, klass, operator, value)
203
- end
204
- end
205
-
206
184
  # Mongoize for the klass, key and value.
207
185
  #
208
186
  # @api private
@@ -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 [ Array ] args The arguments.
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 [ Array ] args The arguments.
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.
@@ -34,6 +34,8 @@ module Mongoid
34
34
  # ::Time.configured
35
35
  #
36
36
  # @return [ Time ] The configured time.
37
+ #
38
+ # @deprecated
37
39
  def configured
38
40
  Mongoid.use_activesupport_time_zone? ? (::Time.zone || ::Time) : ::Time
39
41
  end
@@ -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.
@@ -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,11 +779,21 @@ 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
799
  opts[:type] = retrieve_and_validate_type(name, options[:type])
@@ -782,22 +814,32 @@ module Mongoid
782
814
  #
783
815
  # @api private
784
816
  def retrieve_and_validate_type(name, type)
785
- result = TYPE_MAPPINGS[type] || unmapped_type(type)
786
- raise Errors::InvalidFieldType.new(self, name, type) if !result.is_a?(Class)
787
-
788
- if unsupported_type?(result)
789
- warn_message = "Using #{result} as the field type is not supported. "
790
- if result == BSON::Decimal128
791
- 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+. To use literal BSON::Decimal128 fields with BSON 5, set Mongoid.allow_bson5_decimal128 to true.'
792
- else
793
- 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.'
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)
821
+ else
822
+ if INVALID_BSON_CLASSES.include?(result)
823
+ warn_message = "Using #{result} as the field type is not supported. "
824
+ if result == BSON::Decimal128
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+."
826
+ else
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."
828
+ end
829
+ Mongoid.logger.warn(warn_message)
794
830
  end
795
- Mongoid.logger.warn(warn_message)
796
831
  end
797
-
798
832
  result
799
833
  end
800
834
 
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
801
843
  def unmapped_type(type)
802
844
  if "Boolean" == type.to_s
803
845
  Mongoid::Boolean
@@ -805,19 +847,6 @@ module Mongoid
805
847
  type || Object
806
848
  end
807
849
  end
808
-
809
- # Queries whether or not the given type is permitted as a declared field
810
- # type.
811
- #
812
- # @param [ Class ] type The type to query
813
- #
814
- # @return [ true | false ] whether or not the type is supported
815
- #
816
- # @api private
817
- def unsupported_type?(type)
818
- return !Mongoid::Config.allow_bson5_decimal128? if type == BSON::Decimal128
819
- INVALID_BSON_CLASSES.include?(type)
820
- end
821
850
  end
822
851
  end
823
852
  end
@@ -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
- def exists?
92
- with_default_scope.exists?
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 _id value(s) to find.
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
  #
@@ -140,120 +140,31 @@ module Mongoid
140
140
  #
141
141
  # @api private
142
142
  def _mongoid_run_child_callbacks(kind, children: nil, &block)
143
- if Mongoid::Config.around_callbacks_for_embeds
144
- _mongoid_run_child_callbacks_with_around(kind, children: children, &block)
145
- else
146
- _mongoid_run_child_callbacks_without_around(kind, children: children, &block)
147
- end
148
- end
149
-
150
- # Execute the callbacks of given kind for embedded documents including
151
- # around callbacks.
152
- #
153
- # @note This method is prone to stack overflow errors if the document
154
- # has a large number of embedded documents. It is recommended to avoid
155
- # using around callbacks for embedded documents until a proper solution
156
- # is implemented.
157
- #
158
- # @param [ Symbol ] kind The type of callback to execute.
159
- # @param [ Array<Document> ] children Children to execute callbacks on. If
160
- # nil, callbacks will be executed on all cascadable children of
161
- # the document.
162
- #
163
- # @api private
164
- def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block)
165
143
  child, *tail = (children || cascadable_children(kind))
144
+ with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
166
145
  if child.nil?
167
146
  block&.call
168
147
  elsif tail.empty?
169
- child.run_callbacks(child_callback_type(kind, child), &block)
148
+ child.run_callbacks(child_callback_type(kind, child), with_children: with_children, &block)
170
149
  else
171
- child.run_callbacks(child_callback_type(kind, child)) do
172
- _mongoid_run_child_callbacks_with_around(kind, children: tail, &block)
173
- end
174
- end
175
- end
176
-
177
- # Execute the callbacks of given kind for embedded documents without
178
- # around callbacks.
179
- #
180
- # @param [ Symbol ] kind The type of callback to execute.
181
- # @param [ Array<Document> ] children Children to execute callbacks on. If
182
- # nil, callbacks will be executed on all cascadable children of
183
- # the document.
184
- #
185
- # @api private
186
- def _mongoid_run_child_callbacks_without_around(kind, children: nil, &block)
187
- children = (children || cascadable_children(kind))
188
- callback_list = _mongoid_run_child_before_callbacks(kind, children: children)
189
- return false if callback_list == false
190
- value = block&.call
191
- callback_list.each do |_next_sequence, env|
192
- env.value &&= value
193
- end
194
- return false if _mongoid_run_child_after_callbacks(callback_list: callback_list) == false
195
-
196
- value
197
- end
198
-
199
- # Execute the before callbacks of given kind for embedded documents.
200
- #
201
- # @param [ Symbol ] kind The type of callback to execute.
202
- # @param [ Array<Document> ] children Children to execute callbacks on.
203
- # @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
204
- # pairs of callback sequence and environment. This list will be later used
205
- # to execute after callbacks in reverse order.
206
- #
207
- # @api private
208
- def _mongoid_run_child_before_callbacks(kind, children: [], callback_list: [])
209
- children.each do |child|
210
- chain = child.__callbacks[child_callback_type(kind, child)]
211
- env = ActiveSupport::Callbacks::Filters::Environment.new(child, false, nil)
212
- next_sequence = compile_callbacks(chain)
213
- unless next_sequence.final?
214
- Mongoid.logger.warn("Around callbacks are disabled for embedded documents. Skipping around callbacks for #{child.class.name}.")
215
- Mongoid.logger.warn("To enable around callbacks for embedded documents, set Mongoid::Config.around_callbacks_for_embeds to true.")
216
- end
217
- next_sequence.invoke_before(env)
218
- return false if env.halted
219
- env.value = !env.halted
220
- callback_list << [next_sequence, env]
221
- if (grandchildren = child.send(:cascadable_children, kind))
222
- _mongoid_run_child_before_callbacks(kind, children: grandchildren, callback_list: callback_list)
150
+ child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
151
+ _mongoid_run_child_callbacks(kind, children: tail, &block)
223
152
  end
224
153
  end
225
- callback_list
226
- end
227
-
228
- # Execute the after callbacks.
229
- #
230
- # @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
231
- # pairs of callback sequence and environment.
232
- def _mongoid_run_child_after_callbacks(callback_list: [])
233
- callback_list.reverse_each do |next_sequence, env|
234
- next_sequence.invoke_after(env)
235
- return false if env.halted
236
- end
237
154
  end
238
155
 
239
- # Returns the stored callbacks to be executed later.
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.
240
160
  #
241
- # @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
161
+ # @return [ Array<Symbol> ] an array of symbols that represent the pending callbacks.
242
162
  #
243
163
  # @api private
244
164
  def pending_callbacks
245
165
  @pending_callbacks ||= [].to_set
246
166
  end
247
167
 
248
- # Stores callbacks to be executed later. A good use case for
249
- # this is delaying the after_find and after_initialize callbacks until the
250
- # associations are set on the document. This can also be used to delay
251
- # applying the defaults on a document.
252
- #
253
- # @param [ Array<Symbol> ] value Method symbols of the pending callbacks to store.
254
- #
255
- # @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
256
- #
257
168
  # @api private
258
169
  def pending_callbacks=(value)
259
170
  @pending_callbacks = value
@@ -388,7 +299,7 @@ module Mongoid
388
299
  end
389
300
  self.class.send :define_method, name do
390
301
  env = ActiveSupport::Callbacks::Filters::Environment.new(self, false, nil)
391
- sequence = compile_callbacks(chain)
302
+ sequence = chain.compile
392
303
  sequence.invoke_before(env)
393
304
  env.value = !env.halted
394
305
  sequence.invoke_after(env)
@@ -398,24 +309,5 @@ module Mongoid
398
309
  end
399
310
  send(name)
400
311
  end
401
-
402
- # Compile the callback chain.
403
- #
404
- # This method hides the differences between ActiveSupport implementations
405
- # before and after 7.1.
406
- #
407
- # @param [ ActiveSupport::Callbacks::CallbackChain ] chain The callback chain.
408
- # @param [ Symbol | nil ] type The type of callback chain to compile.
409
- #
410
- # @return [ ActiveSupport::Callbacks::CallbackSequence ] The compiled callback sequence.
411
- def compile_callbacks(chain, type = nil)
412
- if chain.method(:compile).arity == 0
413
- # ActiveSupport < 7.1
414
- chain.compile
415
- else
416
- # ActiveSupport >= 7.1
417
- chain.compile(type)
418
- end
419
- end
420
312
  end
421
313
  end
@@ -46,7 +46,7 @@ module Mongoid
46
46
  end
47
47
  end
48
48
 
49
- # Per https://docs.mongodb.com/ruby-driver/current/tutorials/bson-v4/#time-instances,
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
  #
@@ -1,7 +1,7 @@
1
1
  module Mongoid
2
2
  module Matcher
3
3
 
4
- # @see https://docs.mongodb.com/manual/reference/operator/query/type/
4
+ # @see https://www.mongodb.com/docs/manual/reference/operator/query/type/
5
5
  #
6
6
  # @api private
7
7
  module Type
@@ -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