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.
Files changed (174) 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/nested/one.rb +40 -2
  17. data/lib/mongoid/association/proxy.rb +1 -1
  18. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  19. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  20. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  21. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
  22. data/lib/mongoid/association/reflections.rb +2 -2
  23. data/lib/mongoid/atomic.rb +0 -7
  24. data/lib/mongoid/attributes/dynamic.rb +1 -1
  25. data/lib/mongoid/attributes/nested.rb +2 -2
  26. data/lib/mongoid/attributes/projector.rb +1 -1
  27. data/lib/mongoid/attributes/readonly.rb +1 -1
  28. data/lib/mongoid/attributes.rb +8 -2
  29. data/lib/mongoid/changeable.rb +107 -5
  30. data/lib/mongoid/clients/storage_options.rb +2 -5
  31. data/lib/mongoid/clients/validators/storage.rb +1 -13
  32. data/lib/mongoid/collection_configurable.rb +58 -0
  33. data/lib/mongoid/composable.rb +2 -0
  34. data/lib/mongoid/config/defaults.rb +60 -0
  35. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  36. data/lib/mongoid/config/validators.rb +1 -0
  37. data/lib/mongoid/config.rb +101 -0
  38. data/lib/mongoid/contextual/atomic.rb +1 -1
  39. data/lib/mongoid/contextual/memory.rb +233 -33
  40. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  41. data/lib/mongoid/contextual/mongo.rb +373 -113
  42. data/lib/mongoid/contextual/none.rb +162 -7
  43. data/lib/mongoid/contextual.rb +12 -0
  44. data/lib/mongoid/criteria/findable.rb +2 -2
  45. data/lib/mongoid/criteria/includable.rb +4 -3
  46. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  47. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  48. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  49. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  50. data/lib/mongoid/criteria.rb +6 -5
  51. data/lib/mongoid/deprecable.rb +1 -1
  52. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  53. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  54. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  55. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  56. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  57. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  58. data/lib/mongoid/errors.rb +4 -1
  59. data/lib/mongoid/extensions/object.rb +2 -2
  60. data/lib/mongoid/extensions/time.rb +2 -0
  61. data/lib/mongoid/fields/localized.rb +10 -0
  62. data/lib/mongoid/fields/standard.rb +10 -0
  63. data/lib/mongoid/fields.rb +69 -13
  64. data/lib/mongoid/findable.rb +27 -3
  65. data/lib/mongoid/interceptable.rb +7 -6
  66. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  67. data/lib/mongoid/matcher/type.rb +1 -1
  68. data/lib/mongoid/persistable/creatable.rb +1 -0
  69. data/lib/mongoid/persistable/deletable.rb +1 -1
  70. data/lib/mongoid/persistable/savable.rb +13 -1
  71. data/lib/mongoid/persistable/unsettable.rb +2 -2
  72. data/lib/mongoid/persistable/updatable.rb +51 -1
  73. data/lib/mongoid/persistable/upsertable.rb +20 -1
  74. data/lib/mongoid/persistable.rb +3 -0
  75. data/lib/mongoid/query_cache.rb +5 -1
  76. data/lib/mongoid/railties/database.rake +7 -2
  77. data/lib/mongoid/reloadable.rb +5 -3
  78. data/lib/mongoid/stateful.rb +22 -1
  79. data/lib/mongoid/tasks/database.rake +12 -0
  80. data/lib/mongoid/tasks/database.rb +20 -0
  81. data/lib/mongoid/utils.rb +22 -0
  82. data/lib/mongoid/validatable/macros.rb +5 -5
  83. data/lib/mongoid/validatable.rb +4 -1
  84. data/lib/mongoid/version.rb +1 -1
  85. data/lib/mongoid/warnings.rb +17 -1
  86. data/lib/mongoid.rb +16 -3
  87. data/spec/integration/app_spec.rb +2 -2
  88. data/spec/integration/callbacks_models.rb +37 -0
  89. data/spec/integration/callbacks_spec.rb +134 -0
  90. data/spec/integration/discriminator_key_spec.rb +4 -5
  91. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  92. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  93. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
  94. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  95. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  96. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  97. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +5 -27
  98. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
  99. data/spec/mongoid/association/syncable_spec.rb +1 -1
  100. data/spec/mongoid/attributes_spec.rb +3 -6
  101. data/spec/mongoid/changeable_spec.rb +299 -24
  102. data/spec/mongoid/clients_spec.rb +122 -13
  103. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  104. data/spec/mongoid/config/defaults_spec.rb +160 -0
  105. data/spec/mongoid/config_spec.rb +154 -18
  106. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  107. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  108. data/spec/mongoid/contextual/mongo_spec.rb +995 -36
  109. data/spec/mongoid/contextual/none_spec.rb +49 -2
  110. data/spec/mongoid/copyable_spec.rb +3 -11
  111. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
  112. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  113. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  114. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  115. data/spec/mongoid/criteria/queryable/selector_spec.rb +1 -1
  116. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  117. data/spec/mongoid/criteria_spec.rb +5 -9
  118. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  119. data/spec/mongoid/extensions/time_spec.rb +8 -43
  120. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  121. data/spec/mongoid/fields/localized_spec.rb +46 -28
  122. data/spec/mongoid/fields_spec.rb +136 -34
  123. data/spec/mongoid/findable_spec.rb +391 -34
  124. data/spec/mongoid/indexable_spec.rb +16 -10
  125. data/spec/mongoid/interceptable_spec.rb +15 -3
  126. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  127. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  128. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  129. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  130. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  131. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  132. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  133. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  134. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  135. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  136. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  137. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  138. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  139. data/spec/mongoid/persistence_context_spec.rb +7 -57
  140. data/spec/mongoid/query_cache_spec.rb +56 -61
  141. data/spec/mongoid/reloadable_spec.rb +24 -28
  142. data/spec/mongoid/scopable_spec.rb +70 -0
  143. data/spec/mongoid/serializable_spec.rb +9 -30
  144. data/spec/mongoid/stateful_spec.rb +122 -8
  145. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  146. data/spec/mongoid/tasks/database_spec.rb +127 -0
  147. data/spec/mongoid/timestamps_spec.rb +9 -11
  148. data/spec/mongoid/touchable_spec.rb +277 -5
  149. data/spec/mongoid/touchable_spec_models.rb +3 -1
  150. data/spec/mongoid/traversable_spec.rb +9 -24
  151. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  152. data/spec/mongoid_spec.rb +36 -10
  153. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  154. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  155. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  156. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  157. data/spec/shared/lib/mrss/utils.rb +28 -6
  158. data/spec/shared/share/Dockerfile.erb +36 -40
  159. data/spec/shared/shlib/server.sh +32 -8
  160. data/spec/shared/shlib/set_env.sh +4 -4
  161. data/spec/spec_helper.rb +5 -0
  162. data/spec/support/immutable_ids.rb +118 -0
  163. data/spec/support/macros.rb +47 -15
  164. data/spec/support/models/artist.rb +0 -1
  165. data/spec/support/models/band.rb +1 -0
  166. data/spec/support/models/book.rb +1 -0
  167. data/spec/support/models/building.rb +2 -0
  168. data/spec/support/models/cover.rb +10 -0
  169. data/spec/support/models/product.rb +1 -0
  170. data.tar.gz.sig +0 -0
  171. metadata +686 -650
  172. metadata.gz.sig +0 -0
  173. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  174. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
@@ -14,6 +14,7 @@ module Mongoid
14
14
  #
15
15
  # @return [ nil ] Always nil.
16
16
  def clear_cache
17
+ Mongoid::Warnings.warn_mongoid_query_cache_clear
17
18
  Mongo::QueryCache.clear
18
19
  end
19
20
 
@@ -24,6 +25,7 @@ module Mongoid
24
25
  #
25
26
  # @param [ true | false ] value The enabled value.
26
27
  def enabled=(value)
28
+ Mongoid::Warnings.warn_mongoid_query_cache
27
29
  Mongo::QueryCache.enabled = value
28
30
  end
29
31
 
@@ -34,6 +36,7 @@ module Mongoid
34
36
  #
35
37
  # @return [ true | false ] If the cache is enabled.
36
38
  def enabled?
39
+ Mongoid::Warnings.warn_mongoid_query_cache
37
40
  Mongo::QueryCache.enabled?
38
41
  end
39
42
 
@@ -44,6 +47,7 @@ module Mongoid
44
47
  #
45
48
  # @return [ Object ] The result of the block.
46
49
  def cache(&block)
50
+ Mongoid::Warnings.warn_mongoid_query_cache
47
51
  Mongo::QueryCache.cache(&block)
48
52
  end
49
53
 
@@ -54,6 +58,7 @@ module Mongoid
54
58
  #
55
59
  # @return [ Object ] The result of the block.
56
60
  def uncached(&block)
61
+ Mongoid::Warnings.warn_mongoid_query_cache
57
62
  Mongo::QueryCache.uncached(&block)
58
63
  end
59
64
  end
@@ -61,4 +66,3 @@ module Mongoid
61
66
  Middleware = Mongo::QueryCache::Middleware
62
67
  end
63
68
  end
64
-
@@ -25,7 +25,7 @@ namespace :db do
25
25
 
26
26
  unless Rake::Task.task_defined?("db:setup")
27
27
  desc "Create the database, and initialize with the seed data"
28
- task :setup => [ "db:create", "mongoid:create_indexes", "db:seed" ]
28
+ task :setup => [ "db:create", "mongoid:create_collections", "mongoid:create_indexes", "db:seed" ]
29
29
  end
30
30
 
31
31
  unless Rake::Task.task_defined?("db:reset")
@@ -55,10 +55,15 @@ namespace :db do
55
55
 
56
56
  unless Rake::Task.task_defined?("db:test:prepare")
57
57
  namespace :test do
58
- task :prepare => "mongoid:create_indexes"
58
+ task :prepare => ["mongoid:create_collections", "mongoid:create_indexes"]
59
59
  end
60
60
  end
61
61
 
62
+ unless Rake::Task.task_defined?("db:create_collections")
63
+ desc "Create collections specified in Mongoid models"
64
+ task :create_collections => "mongoid:create_collections"
65
+ end
66
+
62
67
  unless Rake::Task.task_defined?("db:create_indexes")
63
68
  desc "Create indexes specified in Mongoid models"
64
69
  task :create_indexes => "mongoid:create_indexes"
@@ -16,14 +16,16 @@ module Mongoid
16
16
  #
17
17
  # @return [ Document ] The document, reloaded.
18
18
  def reload
19
+ if @atomic_selector
20
+ # Clear atomic_selector cache for sharded clusters. MONGOID-5076
21
+ remove_instance_variable('@atomic_selector')
22
+ end
23
+
19
24
  reloaded = _reload
20
25
  if Mongoid.raise_not_found_error && (reloaded.nil? || reloaded.empty?)
21
26
  shard_keys = atomic_selector.with_indifferent_access.slice(*shard_key_fields, :_id)
22
27
  raise Errors::DocumentNotFound.new(self.class, _id, shard_keys)
23
28
  end
24
-
25
- reset_atomic_updates!
26
-
27
29
  @attributes = reloaded
28
30
  @attributes_before_type_cast = @attributes.dup
29
31
  @changed_attributes = {}
@@ -95,6 +95,23 @@ module Mongoid
95
95
  !_parent.delayed_atomic_sets[atomic_path]
96
96
  end
97
97
 
98
+ # Flags the document as readonly. Will cause a ReadonlyDocument error to be
99
+ # raised if the document is attempted to be saved, updated or destroyed.
100
+ #
101
+ # @example Flag the document as readonly.
102
+ # document.readonly!
103
+ #
104
+ # @return [ true | false ] true if the document was successfully marked
105
+ # readonly, false otherwise.
106
+ def readonly!
107
+ if Mongoid.legacy_readonly
108
+ Mongoid::Warnings.warn_legacy_readonly
109
+ false
110
+ else
111
+ @readonly = true
112
+ end
113
+ end
114
+
98
115
  # Is the document readonly?
99
116
  #
100
117
  # @example Is the document readonly?
@@ -102,7 +119,11 @@ module Mongoid
102
119
  #
103
120
  # @return [ true | false ] If the document is readonly.
104
121
  def readonly?
105
- __selected_fields != nil
122
+ if Mongoid.legacy_readonly
123
+ __selected_fields != nil
124
+ else
125
+ @readonly ||= false
126
+ end
106
127
  end
107
128
 
108
129
  # Determine if the document can be set.
@@ -5,6 +5,11 @@ namespace :db do
5
5
  task :load_models do
6
6
  end
7
7
 
8
+ desc "Create collections for Mongoid models"
9
+ task :create_collections => [:environment, :load_models] do
10
+ ::Mongoid::Tasks::Database.create_collections
11
+ end
12
+
8
13
  desc "Create indexes specified in Mongoid models"
9
14
  task :create_indexes => [:environment, :load_models] do
10
15
  ::Mongoid::Tasks::Database.create_indexes
@@ -34,5 +39,12 @@ namespace :db do
34
39
  task :purge => :environment do
35
40
  ::Mongoid.purge!
36
41
  end
42
+
43
+ namespace :create_collections do
44
+ desc "Drop and create collections for Mongoid models"
45
+ task :force => [:environment, :load_models] do
46
+ ::Mongoid::Tasks::Database.create_collections(force: true)
47
+ end
48
+ end
37
49
  end
38
50
  end
@@ -5,6 +5,26 @@ module Mongoid
5
5
  module Database
6
6
  extend self
7
7
 
8
+ # Create collections for each model given the provided globs and the class is
9
+ # not embedded.
10
+ #
11
+ # @param [ Array<Mongoid::Document> ] models. Array of document classes for
12
+ # which collections should be created. Defaulted to all document classes
13
+ # in the application.
14
+ # @param [ true | false ] force If true, the method will drop existing
15
+ # collections before creating new ones. If false, the method will create
16
+ # only new collection (that do not exist in the database).
17
+ def create_collections(models = ::Mongoid.models, force: false)
18
+ models.each do |model|
19
+ if !model.embedded? || model.cyclic?
20
+ model.create_collection(force: force)
21
+ logger.info("MONGOID: Created collection for #{model}:")
22
+ else
23
+ logger.info("MONGOID: collection options ignored on: #{model}, please define in the root model.")
24
+ end
25
+ end
26
+ end
27
+
8
28
  # Create indexes for each model given the provided globs and the class is
9
29
  # not embedded.
10
30
  #
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+
5
+ # @api private
6
+ module Utils
7
+
8
+ # This function should be used if you need to measure time.
9
+ # @example Calculate elapsed time.
10
+ # starting = Utils.monotonic_time
11
+ # # do something time consuming
12
+ # ending = Utils.monotonic_time
13
+ # puts "It took #{(ending - starting).to_i} seconds"
14
+ #
15
+ # @see https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
16
+ #
17
+ # @return [Float] seconds according to monotonic clock
18
+ module_function def monotonic_time
19
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
20
+ end
21
+ end
22
+ 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
@@ -44,6 +44,8 @@ module Mongoid
44
44
  #
45
45
  # @param [ Hash ] options The options to check.
46
46
  #
47
+ # @option options [ true | false ] :validate Whether or not to validate.
48
+ #
47
49
  # @return [ true | false ] If we are validating.
48
50
  def performing_validations?(options = {})
49
51
  options[:validate].nil? ? true : options[:validate]
@@ -129,7 +131,8 @@ module Mongoid
129
131
  # @example Validate with a specific validator.
130
132
  # validates_with MyValidator, on: :create
131
133
  #
132
- # @param [ Class<Array> | Hash ] args The validator classes and options.
134
+ # @param [ ActiveModel::Validator..., Hash ] *args The validator classes
135
+ # and options hash.
133
136
  #
134
137
  # @note See ActiveModel::Validations::With for full options. This is
135
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.5"
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.
@@ -326,7 +326,7 @@ describe 'Mongoid application tests' do
326
326
  end
327
327
 
328
328
  def wait_for_port(port, timeout, process)
329
- deadline = Time.now + timeout
329
+ deadline = Mongoid::Utils.monotonic_time + timeout
330
330
  loop do
331
331
  begin
332
332
  Socket.tcp('localhost', port, nil, nil, connect_timeout: 0.5) do |socket|
@@ -336,7 +336,7 @@ describe 'Mongoid application tests' do
336
336
  unless process.alive?
337
337
  raise "Process #{process} died while waiting for port #{port}"
338
338
  end
339
- if Time.now > deadline
339
+ if Mongoid::Utils.monotonic_time > deadline
340
340
  raise
341
341
  end
342
342
  end
@@ -153,3 +153,40 @@ class Building
153
153
 
154
154
  has_and_belongs_to_many :architects, dependent: :nullify
155
155
  end
156
+
157
+ class Root
158
+ include Mongoid::Document
159
+ embeds_many :embedded_once, cascade_callbacks: true
160
+ after_save :trace
161
+
162
+ attr_accessor :logger
163
+
164
+ def trace
165
+ logger << :root
166
+ end
167
+ end
168
+
169
+ class EmbeddedOnce
170
+ include Mongoid::Document
171
+ embeds_many :embedded_twice, cascade_callbacks: true
172
+ embedded_in :root
173
+ after_save :trace
174
+
175
+ attr_accessor :logger
176
+
177
+ def trace
178
+ logger << :embedded_once
179
+ end
180
+ end
181
+
182
+ class EmbeddedTwice
183
+ include Mongoid::Document
184
+ embedded_in :embedded_once
185
+ after_save :trace
186
+
187
+ attr_accessor :logger
188
+
189
+ def trace
190
+ logger << :embedded_twice
191
+ end
192
+ end
@@ -447,4 +447,138 @@ describe 'callbacks integration tests' do
447
447
  expect(saved_person.previously_persisted_value).to be_truthy
448
448
  end
449
449
  end
450
+
451
+ context 'saved_change_to_attribute, attribute_before_last_save, will_save_change_to_attribute' do
452
+ class TestSCTAAndABLSInCallbacks
453
+ include Mongoid::Document
454
+
455
+ field :name, type: String
456
+ field :age, type: Integer
457
+
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
508
+ end
509
+ end
510
+
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
+ )
555
+ end
556
+ end
557
+
558
+ context 'nested embedded documents' do
559
+ config_override :prevent_multiple_calls_of_embedded_callbacks, true
560
+
561
+ let(:logger) { Array.new }
562
+
563
+ let(:root) do
564
+ Root.new(
565
+ embedded_once: [
566
+ EmbeddedOnce.new(
567
+ embedded_twice: [EmbeddedTwice.new]
568
+ )
569
+ ]
570
+ )
571
+ end
572
+
573
+ before(:each) do
574
+ root.logger = logger
575
+ root.embedded_once.first.logger = logger
576
+ root.embedded_once.first.embedded_twice.first.logger = logger
577
+ end
578
+
579
+ it 'runs callbacks in the correct order' do
580
+ root.save!
581
+ expect(logger).to eq(%i[embedded_twice embedded_once root])
582
+ end
583
+ end
450
584
  end
@@ -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
 
@@ -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