mongoid 8.0.10 → 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.
Files changed (212) 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 +18 -67
  6. data/lib/config/locales/en.yml +46 -14
  7. data/lib/mongoid/association/accessors.rb +3 -7
  8. data/lib/mongoid/association/builders.rb +1 -1
  9. data/lib/mongoid/association/eager_loadable.rb +0 -3
  10. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  11. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  12. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  14. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +6 -6
  15. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  16. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  17. data/lib/mongoid/association/macros.rb +0 -6
  18. data/lib/mongoid/association/nested/one.rb +40 -2
  19. data/lib/mongoid/association/proxy.rb +1 -1
  20. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  21. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  22. data/lib/mongoid/association/referenced/has_many/enumerable.rb +6 -23
  23. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
  24. data/lib/mongoid/association/reflections.rb +2 -2
  25. data/lib/mongoid/atomic.rb +7 -16
  26. data/lib/mongoid/attributes/dynamic.rb +1 -1
  27. data/lib/mongoid/attributes/nested.rb +2 -2
  28. data/lib/mongoid/attributes/processing.rb +5 -29
  29. data/lib/mongoid/attributes/projector.rb +1 -1
  30. data/lib/mongoid/attributes/readonly.rb +1 -1
  31. data/lib/mongoid/attributes.rb +8 -2
  32. data/lib/mongoid/changeable.rb +107 -5
  33. data/lib/mongoid/clients/storage_options.rb +2 -5
  34. data/lib/mongoid/clients/validators/storage.rb +1 -13
  35. data/lib/mongoid/collection_configurable.rb +58 -0
  36. data/lib/mongoid/composable.rb +2 -0
  37. data/lib/mongoid/config/defaults.rb +60 -0
  38. data/lib/mongoid/config/options.rb +0 -3
  39. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  40. data/lib/mongoid/config/validators.rb +1 -0
  41. data/lib/mongoid/config.rb +88 -27
  42. data/lib/mongoid/contextual/atomic.rb +1 -1
  43. data/lib/mongoid/contextual/memory.rb +233 -33
  44. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  45. data/lib/mongoid/contextual/mongo.rb +370 -133
  46. data/lib/mongoid/contextual/none.rb +162 -7
  47. data/lib/mongoid/contextual.rb +12 -0
  48. data/lib/mongoid/criteria/findable.rb +2 -2
  49. data/lib/mongoid/criteria/includable.rb +4 -3
  50. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -15
  51. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  52. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  53. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  54. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  55. data/lib/mongoid/criteria/queryable/selector.rb +1 -1
  56. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  57. data/lib/mongoid/criteria.rb +6 -5
  58. data/lib/mongoid/deprecable.rb +1 -2
  59. data/lib/mongoid/deprecation.rb +3 -3
  60. data/lib/mongoid/document.rb +1 -8
  61. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  62. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  63. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  64. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  65. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  66. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  67. data/lib/mongoid/errors.rb +4 -1
  68. data/lib/mongoid/extensions/hash.rb +2 -24
  69. data/lib/mongoid/extensions/object.rb +2 -2
  70. data/lib/mongoid/extensions/time.rb +2 -0
  71. data/lib/mongoid/fields/localized.rb +10 -0
  72. data/lib/mongoid/fields/standard.rb +10 -0
  73. data/lib/mongoid/fields.rb +59 -35
  74. data/lib/mongoid/findable.rb +27 -3
  75. data/lib/mongoid/interceptable.rb +6 -116
  76. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  77. data/lib/mongoid/matcher/type.rb +1 -1
  78. data/lib/mongoid/persistable/creatable.rb +1 -0
  79. data/lib/mongoid/persistable/deletable.rb +1 -1
  80. data/lib/mongoid/persistable/savable.rb +13 -1
  81. data/lib/mongoid/persistable/unsettable.rb +2 -2
  82. data/lib/mongoid/persistable/updatable.rb +51 -1
  83. data/lib/mongoid/persistable/upsertable.rb +20 -1
  84. data/lib/mongoid/persistable.rb +3 -0
  85. data/lib/mongoid/query_cache.rb +5 -1
  86. data/lib/mongoid/railties/database.rake +7 -2
  87. data/lib/mongoid/reloadable.rb +5 -3
  88. data/lib/mongoid/stateful.rb +22 -1
  89. data/lib/mongoid/tasks/database.rake +12 -0
  90. data/lib/mongoid/tasks/database.rb +20 -0
  91. data/lib/mongoid/timestamps/created.rb +1 -8
  92. data/lib/mongoid/traversable.rb +0 -12
  93. data/lib/mongoid/utils.rb +22 -0
  94. data/lib/mongoid/validatable/associated.rb +17 -98
  95. data/lib/mongoid/validatable/macros.rb +5 -5
  96. data/lib/mongoid/validatable.rb +4 -9
  97. data/lib/mongoid/version.rb +1 -1
  98. data/lib/mongoid/warnings.rb +17 -1
  99. data/lib/mongoid.rb +16 -3
  100. data/spec/integration/app_spec.rb +2 -6
  101. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +0 -40
  102. data/spec/integration/callbacks_spec.rb +99 -12
  103. data/spec/integration/discriminator_key_spec.rb +4 -5
  104. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  105. data/spec/mongoid/association/eager_spec.rb +2 -24
  106. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  107. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
  108. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  109. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +0 -4
  110. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  111. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  112. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +42 -55
  113. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
  114. data/spec/mongoid/association/syncable_spec.rb +1 -1
  115. data/spec/mongoid/association_spec.rb +0 -60
  116. data/spec/mongoid/attributes_spec.rb +3 -33
  117. data/spec/mongoid/changeable_spec.rb +299 -24
  118. data/spec/mongoid/clients_spec.rb +122 -13
  119. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  120. data/spec/mongoid/config/defaults_spec.rb +160 -0
  121. data/spec/mongoid/config_spec.rb +154 -27
  122. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  123. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  124. data/spec/mongoid/contextual/mongo_spec.rb +1009 -125
  125. data/spec/mongoid/contextual/none_spec.rb +49 -2
  126. data/spec/mongoid/copyable_spec.rb +2 -10
  127. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
  128. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  129. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  130. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  131. data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -76
  132. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  133. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  134. data/spec/mongoid/criteria_spec.rb +5 -9
  135. data/spec/mongoid/document_spec.rb +0 -27
  136. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  137. data/spec/mongoid/extensions/hash_spec.rb +3 -3
  138. data/spec/mongoid/extensions/time_spec.rb +8 -43
  139. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  140. data/spec/mongoid/fields/localized_spec.rb +46 -28
  141. data/spec/mongoid/fields_spec.rb +136 -77
  142. data/spec/mongoid/findable_spec.rb +391 -34
  143. data/spec/mongoid/indexable_spec.rb +16 -10
  144. data/spec/mongoid/interceptable_spec.rb +153 -442
  145. data/spec/mongoid/interceptable_spec_models.rb +111 -51
  146. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  147. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  148. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  149. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  150. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  151. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  152. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  153. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  154. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  155. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  156. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  157. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  158. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  159. data/spec/mongoid/persistence_context_spec.rb +7 -57
  160. data/spec/mongoid/query_cache_spec.rb +56 -61
  161. data/spec/mongoid/reloadable_spec.rb +24 -28
  162. data/spec/mongoid/scopable_spec.rb +70 -0
  163. data/spec/mongoid/serializable_spec.rb +23 -44
  164. data/spec/mongoid/stateful_spec.rb +122 -8
  165. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  166. data/spec/mongoid/tasks/database_spec.rb +127 -0
  167. data/spec/mongoid/timestamps/created_spec.rb +0 -23
  168. data/spec/mongoid/timestamps_spec.rb +9 -11
  169. data/spec/mongoid/touchable_spec.rb +277 -5
  170. data/spec/mongoid/touchable_spec_models.rb +3 -1
  171. data/spec/mongoid/traversable_spec.rb +9 -24
  172. data/spec/mongoid/validatable/associated_spec.rb +34 -27
  173. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  174. data/spec/mongoid_spec.rb +36 -10
  175. data/spec/shared/LICENSE +20 -0
  176. data/spec/shared/bin/get-mongodb-download-url +17 -0
  177. data/spec/shared/bin/s3-copy +45 -0
  178. data/spec/shared/bin/s3-upload +69 -0
  179. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  180. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  181. data/spec/shared/lib/mrss/constraints.rb +378 -0
  182. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  183. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  184. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  185. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  186. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  187. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  188. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  189. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  190. data/spec/shared/lib/mrss/utils.rb +37 -0
  191. data/spec/shared/share/Dockerfile.erb +321 -0
  192. data/spec/shared/share/haproxy-1.conf +16 -0
  193. data/spec/shared/share/haproxy-2.conf +17 -0
  194. data/spec/shared/shlib/config.sh +27 -0
  195. data/spec/shared/shlib/distro.sh +74 -0
  196. data/spec/shared/shlib/server.sh +416 -0
  197. data/spec/shared/shlib/set_env.sh +169 -0
  198. data/spec/spec_helper.rb +5 -0
  199. data/spec/support/immutable_ids.rb +118 -0
  200. data/spec/support/macros.rb +47 -15
  201. data/spec/support/models/artist.rb +0 -1
  202. data/spec/support/models/band.rb +1 -0
  203. data/spec/support/models/building.rb +2 -0
  204. data/spec/support/models/name.rb +0 -10
  205. data/spec/support/models/person.rb +0 -1
  206. data/spec/support/models/product.rb +1 -0
  207. data.tar.gz.sig +0 -0
  208. metadata +745 -637
  209. metadata.gz.sig +2 -0
  210. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  211. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  212. data/spec/support/models/purse.rb +0 -9
@@ -15,113 +15,32 @@ module Mongoid
15
15
  #
16
16
  # validates_associated :name, :addresses
17
17
  # end
18
- class AssociatedValidator < ActiveModel::Validator
19
- # Required by `validates_with` so that the validator
20
- # gets added to the correct attributes.
21
- def attributes
22
- options[:attributes]
23
- end
18
+ class AssociatedValidator < ActiveModel::EachValidator
24
19
 
25
- # Checks that the named associations of the given record
26
- # (`attributes`) are valid. This does NOT load the associations
27
- # from the database, and will only validate records that are dirty
28
- # or unpersisted.
20
+ # Validates that the associations provided are either all nil or all
21
+ # valid. If neither is true then the appropriate errors will be added to
22
+ # the parent document.
29
23
  #
30
- # If anything is not valid, appropriate errors will be added to
31
- # the `document` parameter.
32
- #
33
- # @param [ Mongoid::Document ] document the document with the
34
- # associations to validate.
35
- def validate(document)
36
- options[:attributes].each do |attr_name|
37
- validate_association(document, attr_name)
38
- end
39
- end
40
-
41
- private
42
-
43
- # Validates that the given association provided is either nil,
44
- # persisted and unchanged, or invalid. Otherwise, the appropriate errors
45
- # will be added to the parent document.
24
+ # @example Validate the association.
25
+ # validator.validate_each(document, :name, name)
46
26
  #
47
27
  # @param [ Document ] document The document to validate.
48
28
  # @param [ Symbol ] attribute The association to validate.
49
- def validate_association(document, attribute)
50
- # grab the proxy from the instance variable directly; we don't want
51
- # any loading logic to run; we just want to see if it's already
52
- # been loaded.
53
- proxy = document.ivar(attribute)
54
- return unless proxy
55
-
56
- # if the variable exists, now we see if it is a proxy, or an actual
57
- # document. It might be a literal document instead of a proxy if this
58
- # document was created with a Document instance as a provided attribute,
59
- # e.g. "Post.new(message: Message.new)".
60
- target = proxy.respond_to?(:_target) ? proxy._target : proxy
61
-
62
- # Now, fetch the list of documents from the target. Target may be a
63
- # single value, or a list of values, and in the case of HasMany,
64
- # might be a rather complex collection. We need to do this without
65
- # triggering a load, so it's a bit of a delicate dance.
66
- list = get_target_documents(target)
67
-
68
- valid = document.validating do
69
- # Now, treating the target as an array, look at each element
70
- # and see if it is valid, but only if it has already been
71
- # persisted, or changed, and hasn't been flagged for destroy.
72
- #
73
- # use map.all? instead of just all?, because all? will do short-circuit
74
- # evaluation and terminate on the first failed validation.
75
- list.map do |value|
76
- if value && !value.flagged_for_destroy?
77
- value.validated? ? true : value.valid?
78
- else
29
+ # @param [ Object ] value The value of the association.
30
+ def validate_each(document, attribute, value)
31
+ begin
32
+ document.begin_validate
33
+ valid = Array.wrap(value).collect do |doc|
34
+ if doc.nil? || doc.flagged_for_destroy?
79
35
  true
36
+ else
37
+ doc.validated? ? true : doc.valid?
80
38
  end
81
39
  end.all?
40
+ ensure
41
+ document.exit_validate
82
42
  end
83
-
84
- document.errors.add(attribute, :invalid) unless valid
85
- end
86
-
87
- private
88
-
89
- # Examine the given target object and return an array of
90
- # documents (possibly empty) that the target represents.
91
- #
92
- # @param [ Array | Mongoid::Document | Mongoid::Association::Proxy | HasMany::Enumerable ] target
93
- # the target object to examine.
94
- #
95
- # @return [ Array<Mongoid::Document> ] the list of documents
96
- def get_target_documents(target)
97
- if target.respond_to?(:_loaded?)
98
- get_target_documents_for_has_many(target)
99
- else
100
- get_target_documents_for_other(target)
101
- end
102
- end
103
-
104
- # Returns the list of all currently in-memory values held by
105
- # the target. The target will not be loaded.
106
- #
107
- # @param [ HasMany::Enumerable ] target the target that will
108
- # be examined for in-memory documents.
109
- #
110
- # @return [ Array<Mongoid::Document> ] the in-memory documents
111
- # held by the target.
112
- def get_target_documents_for_has_many(target)
113
- [ *target._loaded.values, *target._added.values ]
114
- end
115
-
116
- # Returns the target as an array. If the target represents a single
117
- # value, it is wrapped in an array.
118
- #
119
- # @param [ Array | Mongoid::Document | Mongoid::Association::Proxy ] target
120
- # the target to return.
121
- #
122
- # @return [ Array<Mongoid::Document> ] the target, as an array.
123
- def get_target_documents_for_other(target)
124
- Array.wrap(target)
43
+ document.errors.add(attribute, :invalid, **options) unless valid
125
44
  end
126
45
  end
127
46
  end
@@ -18,7 +18,7 @@ module Mongoid
18
18
  # validates_associated :name, :addresses
19
19
  # end
20
20
  #
21
- # @param [ Array ] args The arguments to pass to the validator.
21
+ # @param [ Object... ] *args The arguments to pass to the validator.
22
22
  def validates_associated(*args)
23
23
  validates_with(AssociatedValidator, _merge_attributes(args))
24
24
  end
@@ -35,7 +35,7 @@ module Mongoid
35
35
  # validates_uniqueness_of :title
36
36
  # end
37
37
  #
38
- # @param [ Array ] args The arguments to pass to the validator.
38
+ # @param [ Object... ] *args The arguments to pass to the validator.
39
39
  def validates_uniqueness_of(*args)
40
40
  validates_with(UniquenessValidator, _merge_attributes(args))
41
41
  end
@@ -50,7 +50,7 @@ module Mongoid
50
50
  # validates_format_of :title, with: /\A[a-z0-9 \-_]*\z/i
51
51
  # end
52
52
  #
53
- # @param [ Array ] args The names of the fields to validate.
53
+ # @param [ Object... ] *args The names of the field(s) to validate.
54
54
  def validates_format_of(*args)
55
55
  validates_with(FormatValidator, _merge_attributes(args))
56
56
  end
@@ -65,7 +65,7 @@ module Mongoid
65
65
  # validates_length_of :title, minimum: 100
66
66
  # end
67
67
  #
68
- # @param [ Array ] args The names of the fields to validate.
68
+ # @param [ Object... ] *args The names of the field(s) to validate.
69
69
  def validates_length_of(*args)
70
70
  validates_with(LengthValidator, _merge_attributes(args))
71
71
  end
@@ -80,7 +80,7 @@ module Mongoid
80
80
  # validates_presence_of :title
81
81
  # end
82
82
  #
83
- # @param [ Array ] args The names of the fields to validate.
83
+ # @param [ Object... ] *args The names of the field(s) to validate.
84
84
  def validates_presence_of(*args)
85
85
  validates_with(PresenceValidator, _merge_attributes(args))
86
86
  end
@@ -37,14 +37,6 @@ module Mongoid
37
37
  Threaded.exit_validate(self)
38
38
  end
39
39
 
40
- # Perform a validation within the associated block.
41
- def validating
42
- begin_validate
43
- yield
44
- ensure
45
- exit_validate
46
- end
47
-
48
40
  # Given the provided options, are we performing validations?
49
41
  #
50
42
  # @example Are we performing validations?
@@ -52,6 +44,8 @@ module Mongoid
52
44
  #
53
45
  # @param [ Hash ] options The options to check.
54
46
  #
47
+ # @option options [ true | false ] :validate Whether or not to validate.
48
+ #
55
49
  # @return [ true | false ] If we are validating.
56
50
  def performing_validations?(options = {})
57
51
  options[:validate].nil? ? true : options[:validate]
@@ -137,7 +131,8 @@ module Mongoid
137
131
  # @example Validate with a specific validator.
138
132
  # validates_with MyValidator, on: :create
139
133
  #
140
- # @param [ Class<Array> | Hash ] args The validator classes and options.
134
+ # @param [ ActiveModel::Validator..., Hash ] *args The validator classes
135
+ # and options hash.
141
136
  #
142
137
  # @note See ActiveModel::Validations::With for full options. This is
143
138
  # overridden to add autosave functionality when presence validation is
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mongoid
4
- VERSION = "8.0.10"
4
+ VERSION = "8.1.0"
5
5
  end
@@ -23,6 +23,22 @@ module Mongoid
23
23
 
24
24
  warning :geo_haystack_deprecated, 'The geoHaystack type is deprecated.'
25
25
  warning :as_json_compact_deprecated, '#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.'
26
- warning :symbol_type_deprecated, 'The BSON Symbol type is deprecated by MongoDB. Please use String or StringifiedSymbol field types instead of the Symbol field type'
26
+ warning :symbol_type_deprecated, 'The BSON Symbol type is deprecated by MongoDB. Please use String or StringifiedSymbol field types instead of the Symbol field type.'
27
+ warning :legacy_readonly, 'The readonly! method will only mark the document readonly when the legacy_readonly feature flag is switched off.'
28
+ warning :use_activesupport_time_zone_deprecated, 'Config option :use_activesupport_time_zone is deprecated and should be removed from your config. It will always be true beginning in Mongoid 9.0.'
29
+ warning :broken_aggregables_deprecated, 'Config option :broken_aggregables is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
30
+ warning :broken_alias_handling_deprecated, 'Config option :broken_alias_handling is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
31
+ warning :broken_and_deprecated, 'Config option :broken_and is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
32
+ warning :broken_scoping_deprecated, 'Config option :broken_scoping is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
33
+ warning :broken_updates_deprecated, 'Config option :broken_updates is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
34
+ warning :compare_time_by_ms_deprecated, 'Config option :compare_time_by_ms is deprecated. It will always be true beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
35
+ warning :legacy_attributes_deprecated, 'Config option :legacy_attributes is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
36
+ warning :legacy_pluck_distinct_deprecated, 'Config option :legacy_pluck_distinct is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
37
+ warning :legacy_triple_equals_deprecated, 'Config option :legacy_triple_equals is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
38
+ warning :object_id_as_json_oid_deprecated, 'Config option :object_id_as_json_oid is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
39
+ warning :overwrite_chained_operators_deprecated, 'Config option :overwrite_chained_operators is deprecated. It will always be false beginning in Mongoid 9.0. Please use load_defaults for Mongoid 8.0 or later, then remove it from your config.'
40
+ warning :mutable_ids, 'In Mongoid 9.0 the _id field will be immutable. In earlier versions of 8.x, mutating the _id field was supported inconsistently. Prepare your code for 9.0 by setting Mongoid::Config.immutable_ids to true.'
41
+ warning :mongoid_query_cache, 'In Mongoid 9.0, Mongoid::QueryCache will be removed. Please replace it with Mongo::QueryCache.'
42
+ warning :mongoid_query_cache_clear, 'In Mongoid 9.0, Mongoid::QueryCache#clear_cache should be replaced it with Mongo::QueryCache#clear.'
27
43
  end
28
44
  end
data/lib/mongoid.rb CHANGED
@@ -12,8 +12,10 @@ require "active_support/inflector"
12
12
  require "active_support/time_with_zone"
13
13
  require "active_model"
14
14
 
15
+ require 'concurrent-ruby'
16
+
15
17
  require "mongo"
16
- require 'mongo/active_support'
18
+ require "mongo/active_support"
17
19
 
18
20
  require "mongoid/version"
19
21
  require "mongoid/deprecable"
@@ -25,6 +27,7 @@ require "mongoid/document"
25
27
  require "mongoid/tasks/database"
26
28
  require "mongoid/query_cache"
27
29
  require "mongoid/warnings"
30
+ require "mongoid/utils"
28
31
 
29
32
  # If we are using Rails then we will include the Mongoid railtie. This has all
30
33
  # the nifty initializers that Mongoid needs.
@@ -58,9 +61,19 @@ module Mongoid
58
61
  # }
59
62
  # end
60
63
  #
64
+ # @example Using a block without an argument. Use `config` inside
65
+ # the block to perform variable assignment.
66
+ #
67
+ # Mongoid.configure do
68
+ # connect_to("mongoid_test")
69
+ #
70
+ # config.preload_models = true
71
+ #
61
72
  # @return [ Config ] The configuration object.
62
- def configure
63
- block_given? ? yield(Config) : Config
73
+ def configure(&block)
74
+ return Config unless block_given?
75
+
76
+ block.arity == 0 ? Config.instance_exec(&block) : yield(Config)
64
77
  end
65
78
 
66
79
  # Convenience method for getting the default client.
@@ -16,10 +16,6 @@ describe 'Mongoid application tests' do
16
16
  skip 'Set APP_TESTS=1 in environment to run application tests'
17
17
  end
18
18
 
19
- if SpecConfig.instance.rails_version < '7.1'
20
- skip 'App tests require Rails > 7.0 (see https://stackoverflow.com/questions/79360526)'
21
- end
22
-
23
19
  require 'fileutils'
24
20
  require 'mrss/child_process_helper'
25
21
  require 'open-uri'
@@ -330,7 +326,7 @@ describe 'Mongoid application tests' do
330
326
  end
331
327
 
332
328
  def wait_for_port(port, timeout, process)
333
- deadline = Time.now + timeout
329
+ deadline = Mongoid::Utils.monotonic_time + timeout
334
330
  loop do
335
331
  begin
336
332
  Socket.tcp('localhost', port, nil, nil, connect_timeout: 0.5) do |socket|
@@ -340,7 +336,7 @@ describe 'Mongoid application tests' do
340
336
  unless process.alive?
341
337
  raise "Process #{process} died while waiting for port #{port}"
342
338
  end
343
- if Time.now > deadline
339
+ if Mongoid::Utils.monotonic_time > deadline
344
340
  raise
345
341
  end
346
342
  end
@@ -2,28 +2,6 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- module HabtmSpec
6
- class Page
7
- include Mongoid::Document
8
- embeds_many :blocks, class_name: 'HabtmSpec::Block'
9
- end
10
-
11
- class Block
12
- include Mongoid::Document
13
- embedded_in :page, class_name: 'HabtmSpec::Page'
14
- end
15
-
16
- class ImageBlock < Block
17
- has_and_belongs_to_many :attachments, inverse_of: nil, class_name: 'HabtmSpec::Attachment'
18
- accepts_nested_attributes_for :attachments
19
- end
20
-
21
- class Attachment
22
- include Mongoid::Document
23
- field :file, type: String
24
- end
25
- end
26
-
27
5
  describe 'has_and_belongs_to_many associations' do
28
6
 
29
7
  context 'when an anonymous class defines a has_and_belongs_to_many association' do
@@ -40,22 +18,4 @@ describe 'has_and_belongs_to_many associations' do
40
18
  expect(klass.new.movies.build).to be_a Movie
41
19
  end
42
20
  end
43
-
44
- context 'when an embedded has habtm relation' do
45
- let(:attachment) { HabtmSpec::Attachment.create!(file: 'foo.jpg') }
46
-
47
- let(:page) { HabtmSpec::Page.create! }
48
-
49
- let(:image_block) do
50
- image_block = page.blocks.build({
51
- _type: 'HabtmSpec::ImageBlock',
52
- attachment_ids: [ attachment.id.to_s ],
53
- attachments_attributes: { '1234' => { file: 'bar.jpg', id: attachment.id.to_s } }
54
- })
55
- end
56
-
57
- it 'does not raise on save' do
58
- expect { image_block.save! }.not_to raise_error
59
- end
60
- end
61
21
  end
@@ -448,23 +448,110 @@ describe 'callbacks integration tests' do
448
448
  end
449
449
  end
450
450
 
451
- context 'cascade callbacks' do
452
- ruby_version_gte '3.0'
453
- config_override :around_callbacks_for_embeds, false
451
+ context 'saved_change_to_attribute, attribute_before_last_save, will_save_change_to_attribute' do
452
+ class TestSCTAAndABLSInCallbacks
453
+ include Mongoid::Document
454
454
 
455
- let(:book) do
456
- Book.new
457
- end
455
+ field :name, type: String
456
+ field :age, type: Integer
458
457
 
459
- before do
460
- 1500.times do
461
- book.pages.build
458
+ set_callback :save, :before do |doc|
459
+ [:name, :age].each do |attr|
460
+ saved_change_to_attribute_values_before[attr] += [saved_change_to_attribute(attr)]
461
+ attribute_before_last_save_values_before[attr] += [attribute_before_last_save(attr)]
462
+ will_save_change_to_attribute_values_before[attr] += [will_save_change_to_attribute?(attr)]
463
+ end
464
+ end
465
+
466
+ set_callback :save, :after do |doc|
467
+ [:name, :age].each do |attr|
468
+ saved_change_to_attribute_values_after[attr] += [saved_change_to_attribute(attr)]
469
+ saved_change_to_attribute_q_values_after[attr] += [saved_change_to_attribute?(attr)]
470
+ attribute_before_last_save_values_after[attr] += [attribute_before_last_save(attr)]
471
+ end
472
+ end
473
+
474
+ def saved_change_to_attribute_values_before
475
+ @saved_change_to_attribute_values_before ||= Hash.new do
476
+ []
477
+ end
478
+ end
479
+
480
+ def attribute_before_last_save_values_before
481
+ @attribute_before_last_save_values_before ||= Hash.new do
482
+ []
483
+ end
484
+ end
485
+
486
+ def saved_change_to_attribute_values_after
487
+ @saved_change_to_attribute_values_after ||= Hash.new do
488
+ []
489
+ end
490
+ end
491
+
492
+ def saved_change_to_attribute_q_values_after
493
+ @saved_change_to_attribute_q_values_after ||= Hash.new do
494
+ []
495
+ end
496
+ end
497
+
498
+ def attribute_before_last_save_values_after
499
+ @attribute_before_last_save_values_after ||= Hash.new do
500
+ []
501
+ end
502
+ end
503
+
504
+ def will_save_change_to_attribute_values_before
505
+ @will_save_change_to_attribute_values_before ||= Hash.new do
506
+ []
507
+ end
462
508
  end
463
509
  end
464
510
 
465
- # https://jira.mongodb.org/browse/MONGOID-5658
466
- it 'does not raise SystemStackError' do
467
- expect { book.save! }.not_to raise_error(SystemStackError)
511
+ it 'reproduces ActiveRecord::AttributeMethods::Dirty behavior' do
512
+ subject = TestSCTAAndABLSInCallbacks.new(name: 'Name 1')
513
+ subject.save!
514
+ subject.age = 18
515
+ subject.save!
516
+ subject.name = 'Name 2'
517
+ subject.save!
518
+
519
+ expect(subject.saved_change_to_attribute_values_before).to eq(
520
+ {
521
+ :name => [nil, [nil, "Name 1"], nil],
522
+ :age => [nil, nil, [nil, 18]],
523
+ }
524
+ )
525
+ expect(subject.saved_change_to_attribute_values_after).to eq(
526
+ {
527
+ :name => [[nil, "Name 1"], nil, ["Name 1", "Name 2"]],
528
+ :age => [nil, [nil, 18], nil],
529
+ }
530
+ )
531
+ expect(subject.saved_change_to_attribute_q_values_after).to eq(
532
+ {
533
+ :name => [true, false, true],
534
+ :age => [false, true, false],
535
+ }
536
+ )
537
+ expect(subject.attribute_before_last_save_values_before).to eq(
538
+ {
539
+ :name => [nil, nil, "Name 1"],
540
+ :age => [nil, nil, nil]
541
+ }
542
+ )
543
+ expect(subject.attribute_before_last_save_values_after).to eq(
544
+ {
545
+ :name => [nil, "Name 1", "Name 1"],
546
+ :age => [nil, nil, 18]
547
+ }
548
+ )
549
+ expect(subject.will_save_change_to_attribute_values_before).to eq(
550
+ {
551
+ :name => [true, false, true],
552
+ :age => [false, true, false]
553
+ }
554
+ )
468
555
  end
469
556
  end
470
557
 
@@ -81,8 +81,9 @@ describe "#discriminator_key" do
81
81
  end
82
82
 
83
83
  context "before class creation" do
84
+ config_override :discriminator_key, "test"
85
+
84
86
  before do
85
- Mongoid.discriminator_key = "test"
86
87
 
87
88
  class PreGlobalIntDiscriminatorParent
88
89
  include Mongoid::Document
@@ -93,7 +94,6 @@ describe "#discriminator_key" do
93
94
  end
94
95
 
95
96
  after do
96
- Mongoid.discriminator_key = "_type"
97
97
  Object.send(:remove_const, :PreGlobalIntDiscriminatorParent)
98
98
  Object.send(:remove_const, :PreGlobalIntDiscriminatorChild)
99
99
  end
@@ -336,9 +336,9 @@ describe "#discriminator_key" do
336
336
  end
337
337
 
338
338
  context "Example 3" do
339
- before do
340
- Mongoid.discriminator_key = "shape_type"
339
+ config_override :discriminator_key, "shape_type"
341
340
 
341
+ before do
342
342
  class Example3Shape
343
343
  include Mongoid::Document
344
344
  field :x, type: Integer
@@ -358,7 +358,6 @@ describe "#discriminator_key" do
358
358
  end
359
359
 
360
360
  after do
361
- Mongoid.discriminator_key = "_type"
362
361
  Object.send(:remove_const, :Example3Shape)
363
362
  Object.send(:remove_const, :Example3Circle)
364
363
  Object.send(:remove_const, :Example3Rectangle)
@@ -3,11 +3,12 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe 'i18n fallbacks' do
6
- with_i18n_fallbacks
6
+ require_fallbacks
7
7
 
8
8
  context 'when fallbacks are enabled with a locale list' do
9
+ with_default_i18n_configs
10
+
9
11
  before do
10
- I18n.default_locale = :en
11
12
  I18n.fallbacks[:de] = [ :en ]
12
13
  end
13
14
 
@@ -14,36 +14,14 @@ describe Mongoid::Association::EagerLoadable do
14
14
  Mongoid::Contextual::Mongo.new(criteria)
15
15
  end
16
16
 
17
- let(:association_host) { Account }
18
-
19
17
  let(:inclusions) do
20
18
  includes.map do |key|
21
- association_host.reflect_on_association(key)
19
+ Account.reflect_on_association(key)
22
20
  end
23
21
  end
24
22
 
25
23
  let(:doc) { criteria.first }
26
24
 
27
- context 'when root is an STI subclass' do
28
- # Driver has_one Vehicle
29
- # Vehicle belongs_to Driver
30
- # Truck is a Vehicle
31
-
32
- before do
33
- Driver.create!(vehicle: Truck.new)
34
- end
35
-
36
- let(:criteria) { Truck.all }
37
- let(:includes) { %i[ driver ] }
38
- let(:association_host) { Truck }
39
-
40
- it 'preloads the driver' do
41
- expect(doc.ivar(:driver)).to be false
42
- context.preload(inclusions, [ doc ])
43
- expect(doc.ivar(:driver)).to be == Driver.first
44
- end
45
- end
46
-
47
25
  context "when belongs_to" do
48
26
 
49
27
  let!(:account) do
@@ -64,7 +42,7 @@ describe Mongoid::Association::EagerLoadable do
64
42
  it "preloads the parent" do
65
43
  expect(doc.ivar(:person)).to be false
66
44
  context.preload(inclusions, [doc])
67
- expect(doc.ivar(:person)).to be == person
45
+ expect(doc.ivar(:person)).to eq(doc.person)
68
46
  end
69
47
  end
70
48
 
@@ -616,4 +616,31 @@ describe Mongoid::Association::Embedded::EmbeddedIn::Proxy do
616
616
  end
617
617
  end
618
618
  end
619
+
620
+ context "when assigning a hash" do
621
+ let(:building_address) { BuildingAddress.new }
622
+
623
+ before do
624
+ building_address.building = { name: "Chrysler" }
625
+ end
626
+
627
+ it "creates the objects correctly" do
628
+ expect(building_address.building).to be_a(Building)
629
+ expect(building_address.building.name).to eq("Chrysler")
630
+ end
631
+ end
632
+
633
+ context "when replacing an association with a hash" do
634
+ let(:building_address) { BuildingAddress.new }
635
+
636
+ before do
637
+ building_address.building = { name: "Chrysler" }
638
+ building_address.building = { name: "Empire State" }
639
+ end
640
+
641
+ it "creates the objects correctly" do
642
+ expect(building_address.building).to be_a(Building)
643
+ expect(building_address.building.name).to eq("Empire State")
644
+ end
645
+ end
619
646
  end