mongoid 7.1.0 → 7.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +6 -6
  5. data/README.md +1 -1
  6. data/Rakefile +14 -5
  7. data/lib/config/locales/en.yml +5 -5
  8. data/lib/mongoid/association/accessors.rb +37 -2
  9. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  10. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  11. data/lib/mongoid/association/proxy.rb +1 -1
  12. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -1
  13. data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
  14. data/lib/mongoid/association/referenced/eager.rb +29 -9
  15. data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
  16. data/lib/mongoid/atomic.rb +13 -3
  17. data/lib/mongoid/clients/factory.rb +2 -2
  18. data/lib/mongoid/clients/options.rb +8 -8
  19. data/lib/mongoid/clients/sessions.rb +20 -4
  20. data/lib/mongoid/clients/storage_options.rb +5 -5
  21. data/lib/mongoid/config.rb +39 -9
  22. data/lib/mongoid/criteria.rb +23 -4
  23. data/lib/mongoid/criteria/modifiable.rb +2 -1
  24. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  25. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -6
  26. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  27. data/lib/mongoid/criteria/queryable/mergeable.rb +75 -8
  28. data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
  29. data/lib/mongoid/criteria/queryable/selectable.rb +120 -13
  30. data/lib/mongoid/criteria/queryable/storable.rb +104 -99
  31. data/lib/mongoid/errors/eager_load.rb +2 -0
  32. data/lib/mongoid/errors/no_client_config.rb +2 -2
  33. data/lib/mongoid/errors/no_default_client.rb +1 -1
  34. data/lib/mongoid/extensions/hash.rb +4 -2
  35. data/lib/mongoid/extensions/regexp.rb +1 -1
  36. data/lib/mongoid/fields.rb +2 -1
  37. data/lib/mongoid/fields/validators/macro.rb +4 -1
  38. data/lib/mongoid/matchable/regexp.rb +2 -2
  39. data/lib/mongoid/persistable/pushable.rb +11 -2
  40. data/lib/mongoid/persistence_context.rb +6 -6
  41. data/lib/mongoid/query_cache.rb +61 -18
  42. data/lib/mongoid/serializable.rb +9 -3
  43. data/lib/mongoid/tasks/database.rb +38 -3
  44. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  45. data/lib/mongoid/version.rb +1 -1
  46. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
  47. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  48. data/spec/app/models/coding.rb +4 -0
  49. data/spec/app/models/coding/pull_request.rb +12 -0
  50. data/spec/app/models/delegating_patient.rb +16 -0
  51. data/spec/app/models/passport.rb +1 -0
  52. data/spec/app/models/person.rb +2 -0
  53. data/spec/app/models/phone.rb +1 -0
  54. data/spec/app/models/publication.rb +5 -0
  55. data/spec/app/models/publication/encyclopedia.rb +12 -0
  56. data/spec/app/models/publication/review.rb +14 -0
  57. data/spec/app/models/series.rb +1 -0
  58. data/spec/app/models/wiki_page.rb +1 -0
  59. data/spec/integration/app_spec.rb +254 -0
  60. data/spec/integration/associations/embedded_spec.rb +54 -0
  61. data/spec/integration/associations/embeds_many_spec.rb +24 -0
  62. data/spec/integration/associations/embeds_one_spec.rb +24 -0
  63. data/spec/integration/associations/has_many_spec.rb +76 -0
  64. data/spec/integration/associations/has_one_spec.rb +76 -0
  65. data/spec/integration/bson_regexp_raw_spec.rb +20 -0
  66. data/spec/integration/criteria/date_field_spec.rb +41 -0
  67. data/spec/integration/criteria/logical_spec.rb +13 -0
  68. data/spec/integration/document_spec.rb +22 -0
  69. data/spec/integration/shardable_spec.rb +20 -4
  70. data/spec/lite_spec_helper.rb +12 -4
  71. data/spec/mongoid/association/accessors_spec.rb +238 -63
  72. data/spec/mongoid/association/embedded/embeds_many_models.rb +19 -0
  73. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  74. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  75. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
  76. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  77. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +105 -0
  78. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  79. data/spec/mongoid/clients/factory_spec.rb +8 -8
  80. data/spec/mongoid/clients/options_spec.rb +11 -11
  81. data/spec/mongoid/clients/sessions_spec.rb +8 -4
  82. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  83. data/spec/mongoid/clients_spec.rb +2 -2
  84. data/spec/mongoid/contextual/atomic_spec.rb +22 -11
  85. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  86. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  87. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  88. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +1 -1
  89. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  90. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  91. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  92. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  93. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +45 -12
  94. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1051 -392
  95. data/spec/mongoid/criteria/queryable/selectable_spec.rb +52 -0
  96. data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
  97. data/spec/mongoid/criteria_spec.rb +36 -2
  98. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  99. data/spec/mongoid/errors/no_client_config_spec.rb +2 -2
  100. data/spec/mongoid/errors/no_client_database_spec.rb +3 -3
  101. data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -3
  102. data/spec/mongoid/fields_spec.rb +24 -1
  103. data/spec/mongoid/indexable_spec.rb +6 -4
  104. data/spec/mongoid/matchable/default_spec.rb +1 -1
  105. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  106. data/spec/mongoid/matchable_spec.rb +2 -2
  107. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  108. data/spec/mongoid/query_cache_spec.rb +77 -9
  109. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  110. data/spec/mongoid/scopable_spec.rb +2 -1
  111. data/spec/mongoid/serializable_spec.rb +129 -18
  112. data/spec/mongoid/shardable_models.rb +1 -1
  113. data/spec/mongoid/shardable_spec.rb +2 -2
  114. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  115. data/spec/mongoid/tasks/database_spec.rb +1 -1
  116. data/spec/shared/LICENSE +20 -0
  117. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  118. data/spec/shared/lib/mrss/cluster_config.rb +211 -0
  119. data/spec/shared/lib/mrss/constraints.rb +312 -0
  120. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  121. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  122. data/spec/spec_helper.rb +2 -31
  123. data/spec/support/child_process_helper.rb +76 -0
  124. data/spec/support/cluster_config.rb +3 -3
  125. data/spec/support/constraints.rb +26 -10
  126. data/spec/support/expectations.rb +3 -1
  127. data/spec/support/helpers.rb +11 -0
  128. data/spec/support/session_registry.rb +50 -0
  129. data/spec/support/spec_config.rb +12 -4
  130. metadata +520 -473
  131. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8352346c7b47e2323d4afee8968a5581b091735a11d3aacaf9a1c73197d511db
4
- data.tar.gz: 4780a1d8ec316330301e933a145957e48f4927c9fbcbe582404f062179280947
3
+ metadata.gz: 2dc047b0566d39e527a503400ca7bd624afcea9aebd7db795870333a795644c3
4
+ data.tar.gz: 600c7431bf9a3464f24794c02807510f22b56d74a3981826cb1c6f2013a6c5e5
5
5
  SHA512:
6
- metadata.gz: 870e9d5aff9bd06217cea69dd7b86b15ea9ec89464a8e6f579e24e58789a1e5612256026927e6cdd0e17cb39340cf4ef7758bc75fc1b5176939f8b11968bd76c
7
- data.tar.gz: fc095139739ed83771b35d9f2c91b2a0e33bb99125df7622fe0f8f24bf971c6d0cabcd5ac507d4bb72e8a178bc988661197258f20f0193b7e72c8d7a219d2459
6
+ metadata.gz: 6a430d43d0646baa0424f06471f4891330470d85dc23af4e2166779e36fa2e58cc44e1d645062290e8ec30dbad583dfc42f4d898b66ff5995422489e8868f577
7
+ data.tar.gz: d35537d5127ff1840f4b8c920a446a22bee7bedcf675fe8212989798cc949d1d0e01c03e6df1b782def1956bbd4ecc81f1812d3b768e17029cd87e5e6583df96
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1848,18 +1848,18 @@ child elements.
1848
1848
  set a child on a relation without the proper inverse_of definitions
1849
1849
  due to Mongoid not being able to determine it.
1850
1850
 
1851
- class Lush
1851
+ class Car
1852
1852
  include Mongoid::Document
1853
- embeds_one :whiskey, class_name: "Drink"
1853
+ embeds_one :engine, class_name: "Motor"
1854
1854
  end
1855
1855
 
1856
- class Drink
1856
+ class Motor
1857
1857
  include Mongoid::Document
1858
- embedded_in :alcoholic, class_name: "Lush"
1858
+ embedded_in :machine, class_name: "Car"
1859
1859
  end
1860
1860
 
1861
- lush = Lush.new
1862
- lush.whiskey = Drink.new # raises an InverseNotFound error.
1861
+ car = Car.new
1862
+ car.engine = Motor.new # raises an InverseNotFound error.
1863
1863
 
1864
1864
  * \#1680 Polymorphic relations now use `*_type` keys in lookup queries.
1865
1865
 
data/README.md CHANGED
@@ -31,7 +31,7 @@ Support
31
31
  -------
32
32
 
33
33
  * [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoid)
34
- * [Mongoid Google Group](http://groups.google.com/group/mongoid)
34
+ * [MongoDB Community Forum](https://developer.mongodb.com/community/forums/tags/c/drivers-odms-connectors/7/mongoid-odm)
35
35
  * [#mongoid](http://webchat.freenode.net/?channels=mongoid) on Freenode IRC
36
36
 
37
37
  License
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler"
4
+ require "bundler/gem_tasks"
4
5
  Bundler.setup
5
6
 
6
7
  require "rake"
@@ -9,6 +10,9 @@ require "rspec/core/rake_task"
9
10
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
10
11
  require "mongoid/version"
11
12
 
13
+ tasks = Rake.application.instance_variable_get('@tasks')
14
+ tasks['release:do'] = tasks.delete('release')
15
+
12
16
  task :gem => :build
13
17
  task :build do
14
18
  system "gem build mongoid.gemspec"
@@ -18,11 +22,8 @@ task :install => :build do
18
22
  system "sudo gem install mongoid-#{Mongoid::VERSION}.gem"
19
23
  end
20
24
 
21
- task :release => :build do
22
- system "git tag -a v#{Mongoid::VERSION} -m 'Tagging #{Mongoid::VERSION}'"
23
- system "git push --tags"
24
- system "gem push mongoid-#{Mongoid::VERSION}.gem"
25
- system "rm mongoid-#{Mongoid::VERSION}.gem"
25
+ task :release do
26
+ raise "Please use ./release.sh to release"
26
27
  end
27
28
 
28
29
  RSpec::Core::RakeTask.new("spec") do |spec|
@@ -47,3 +48,11 @@ namespace :docs do
47
48
  system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
48
49
  end
49
50
  end
51
+
52
+ namespace :release do
53
+ task :check_private_key do
54
+ unless File.exist?('gem-private_key.pem')
55
+ raise "No private key present, cannot release"
56
+ end
57
+ end
58
+ end
@@ -249,7 +249,7 @@ en:
249
249
  Example:\n
250
250
  \_\_class Band\n
251
251
  \_\_\_\_include Mongoid::Document\n
252
- \_\_\_\_store_in collection: 'artists', database: 'secondary'\n
252
+ \_\_\_\_store_in collection: 'artists', database: 'music'\n
253
253
  \_\_end\n\n"
254
254
  invalid_storage_parent:
255
255
  message: "Invalid store_in call on class %{klass}."
@@ -282,13 +282,13 @@ en:
282
282
  you will need to explicitly tell Mongoid on the association what
283
283
  the inverse is.\n\n
284
284
  Example:\n
285
- \_\_class Lush\n
285
+ \_\_class Car\n
286
286
  \_\_\_\_include Mongoid::Document\n
287
- \_\_\_\_has_one :whiskey, class_name: \"Drink\", inverse_of: :alcoholic\n
287
+ \_\_\_\_has_one :engine, class_name: \"Motor\", inverse_of: :machine\n
288
288
  \_\_end\n\n
289
- \_\_class Drink\n
289
+ \_\_class Motor\n
290
290
  \_\_\_\_include Mongoid::Document\n
291
- \_\_\_\_belongs_to :alcoholic, class_name: \"Lush\", inverse_of: :whiskey\n
291
+ \_\_\_\_belongs_to :machine, class_name: \"Car\", inverse_of: :engine\n
292
292
  \_\_end"
293
293
  invalid_set_polymorphic_relation:
294
294
  message: "The %{name} attribute can't be set to an instance of
@@ -131,15 +131,50 @@ module Mongoid
131
131
  # @api private
132
132
  def _mongoid_filter_selected_fields(assoc_key)
133
133
  return nil unless __selected_fields
134
+
135
+ projecting_assoc = false
136
+
134
137
  filtered = {}
135
138
  __selected_fields.each do |k, v|
136
139
  bits = k.split('.')
140
+
141
+ # If we are asked to project an association, we need all of that
142
+ # association's fields. However, we may be asked to project
143
+ # an association *and* its fields in the same query. In this case
144
+ # behavior differs according to server version:
145
+ #
146
+ # 4.2 and lower take the most recent projection specification, meaning
147
+ # projecting foo followed by foo.bar effectively projects foo.bar and
148
+ # projecting foo.bar followed by foo effectively projects foo.
149
+ # To match this behavior we need to track when we are being asked
150
+ # to project the association and when we are asked to project a field,
151
+ # and if we are asked to project the association last we need to
152
+ # remove any field projections.
153
+ #
154
+ # 4.4 (and presumably higher) do not allow projection to be on an
155
+ # association and its field, so it doesn't matter what we do. Hence
156
+ # we just need to handle the 4.2 and lower case correctly.
137
157
  if bits.first == assoc_key
138
- bits.shift
139
- filtered[bits.join('.')] = v
158
+ # Projecting the entire association OR some of its fields
159
+ if bits.length > 1
160
+ # Projecting a field
161
+ bits.shift
162
+ filtered[bits.join('.')] = v
163
+ projecting_assoc = false
164
+ else
165
+ # Projecting the entire association
166
+ projecting_assoc = true
167
+ end
140
168
  end
141
169
  end
142
170
 
171
+ if projecting_assoc
172
+ # The last projection was of the entire association; we may have
173
+ # also been projecting fields, but discard the field projections
174
+ # and return nil indicating we want the entire association.
175
+ return nil
176
+ end
177
+
143
178
  # Positional projection is specified as "foo.$". In this case the
144
179
  # document that the $ is referring to should be retrieved with all
145
180
  # fields. See https://docs.mongodb.com/manual/reference/operator/projection/positional/
@@ -200,7 +200,8 @@ module Mongoid
200
200
  def determine_inverses(other)
201
201
  matches = relation_class.relations.values.select do |rel|
202
202
  relation_complements.include?(rel.class) &&
203
- rel.relation_class_name == inverse_class_name
203
+ # https://jira.mongodb.org/browse/MONGOID-4882
204
+ rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
204
205
  end
205
206
  if matches.size > 1
206
207
  raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
@@ -162,7 +162,8 @@ module Mongoid
162
162
  def determine_inverses(other)
163
163
  matches = relation_class.relations.values.select do |rel|
164
164
  relation_complements.include?(rel.class) &&
165
- rel.relation_class_name == inverse_class_name
165
+ # https://jira.mongodb.org/browse/MONGOID-4882
166
+ rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
166
167
 
167
168
  end
168
169
  if matches.size > 1
@@ -16,7 +16,7 @@ module Mongoid
16
16
  # We undefine most methods to get them sent through to the target.
17
17
  instance_methods.each do |method|
18
18
  undef_method(method) unless
19
- method =~ /^(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)$/
19
+ method =~ /\A(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)\z/
20
20
  end
21
21
 
22
22
  include Threaded::Lifecycle
@@ -76,7 +76,7 @@ module Mongoid
76
76
  # @since 3.0.0
77
77
  def check_polymorphic_inverses!(doc)
78
78
  inverses = _association.inverses(doc)
79
- if inverses.count > 1 && _base.send(_association.foreign_key).nil?
79
+ if inverses.length > 1 && _base.send(_association.foreign_key).nil?
80
80
  raise Errors::InvalidSetPolymorphicRelation.new(
81
81
  _association.name, _base.class.name, _target.class.name
82
82
  )
@@ -12,8 +12,6 @@ module Mongoid
12
12
  private
13
13
 
14
14
  def preload
15
- raise Errors::EagerLoad.new(@association.name) if @association.polymorphic?
16
-
17
15
  @docs.each do |d|
18
16
  set_relation(d, nil)
19
17
  end
@@ -24,6 +22,44 @@ module Mongoid
24
22
  end
25
23
  end
26
24
 
25
+ # Retrieves the documents referenced by the association, and
26
+ # yields each one sequentially to the provided block. If the
27
+ # association is not polymorphic, all documents are retrieved in
28
+ # a single query. If the association is polymorphic, one query is
29
+ # issued per association target class.
30
+ def each_loaded_document(&block)
31
+ if @association.polymorphic?
32
+ keys_by_type_from_docs.each do |type, keys|
33
+ each_loaded_document_of_class(Object.const_get(type), keys, &block)
34
+ end
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ # Returns a map from association target class name to foreign key
41
+ # values for the documents of that association target class,
42
+ # as referenced by this association.
43
+ def keys_by_type_from_docs
44
+ inverse_type_field = @association.inverse_type
45
+
46
+ @docs.each_with_object({}) do |doc, keys_by_type|
47
+ next unless doc.respond_to?(inverse_type_field) && doc.respond_to?(group_by_key)
48
+ inverse_type_name = doc.send(inverse_type_field)
49
+ # If a particular document does not have a value for this
50
+ # association, inverse_type_name will be nil.
51
+ next if inverse_type_name.nil?
52
+
53
+ key_value = doc.send(group_by_key)
54
+ # If a document has the *_type field set but the corresponding
55
+ # *_id field not set, the key value here will be nil.
56
+ next unless key_value
57
+
58
+ keys_by_type[inverse_type_name] ||= []
59
+ keys_by_type[inverse_type_name].push(key_value)
60
+ end
61
+ end
62
+
27
63
  def group_by_key
28
64
  @association.foreign_key
29
65
  end
@@ -59,17 +59,29 @@ module Mongoid
59
59
  raise NotImplementedError
60
60
  end
61
61
 
62
- # Run the preloader.
63
- #
64
- # @example Iterate over the documents loaded for the current association
65
- # loader.each_loaded_document { |doc| }
62
+ # Retrieves the documents referenced by the association, and
63
+ # yields each one sequentially to the provided block. If the
64
+ # association is not polymorphic, all documents are retrieved in
65
+ # a single query. If the association is polymorphic, one query is
66
+ # issued per association target class.
66
67
  #
67
68
  # @since 4.0.0
68
- def each_loaded_document
69
- doc_keys = keys_from_docs
70
- return @association.klass.none if doc_keys.all?(&:nil?)
69
+ def each_loaded_document(&block)
70
+ each_loaded_document_of_class(@association.klass, keys_from_docs, &block)
71
+ end
71
72
 
72
- criteria = @association.klass.any_in(key => doc_keys)
73
+ # Retrieves the documents of the specified class, that have the
74
+ # foreign key included in the specified list of keys.
75
+ #
76
+ # When the documents are retrieved, the set of inclusions applied
77
+ # is the set of inclusions applied to the host document minus the
78
+ # association that is being eagerly loaded.
79
+ private def each_loaded_document_of_class(cls, keys)
80
+ # Note: keys should not include nil elements.
81
+ # Upstream code is responsible for eliminating nils from keys.
82
+ return cls.none if keys.empty?
83
+
84
+ criteria = cls.any_in(key => keys)
73
85
  criteria.inclusions = criteria.inclusions - [@association]
74
86
  criteria.each do |doc|
75
87
  yield doc
@@ -93,6 +105,9 @@ module Mongoid
93
105
 
94
106
  # Return a hash with the current documents grouped by key.
95
107
  #
108
+ # Documents that do not have a value for the association being loaded
109
+ # are not returned.
110
+ #
96
111
  # @example Return a hash with the current documents grouped by key.
97
112
  # loader.grouped_docs
98
113
  #
@@ -102,10 +117,15 @@ module Mongoid
102
117
  def grouped_docs
103
118
  @grouped_docs[@association.name] ||= @docs.group_by do |doc|
104
119
  doc.send(group_by_key) if doc.respond_to?(group_by_key)
120
+ end.reject do |k, v|
121
+ k.nil?
105
122
  end
106
123
  end
107
124
 
108
- # Group the documents and return the keys
125
+ # Group the documents and return the keys.
126
+ #
127
+ # This method omits nil keys (i.e. keys from documents that do not
128
+ # have a value for the association being loaded).
109
129
  #
110
130
  # @example
111
131
  # loader.keys_from_docs
@@ -54,9 +54,14 @@ module Mongoid
54
54
  #
55
55
  # @since 2.0.0.rc.1
56
56
  def substitute(replacement)
57
+ # If the same object currently associated is being assigned,
58
+ # rebind the association and save the target but do not destroy
59
+ # the target.
60
+
57
61
  unbind_one
58
62
  if persistable?
59
- if _association.destructive?
63
+ # TODO can this entire method be skipped if self == replacement?
64
+ if _association.destructive? && self != replacement
60
65
  send(_association.dependent)
61
66
  else
62
67
  save if persisted?
@@ -38,7 +38,9 @@ module Mongoid
38
38
  # @since 2.2.0
39
39
  def add_atomic_pull(document)
40
40
  document.flagged_for_destroy = true
41
- (delayed_atomic_pulls[document.association_name.to_s] ||= []).push(document)
41
+ key = document.association_name.to_s
42
+ delayed_atomic_pulls[key] ||= []
43
+ delayed_atomic_pulls[key] << document
42
44
  end
43
45
 
44
46
  # Add an atomic unset for the document.
@@ -53,7 +55,9 @@ module Mongoid
53
55
  # @since 3.0.0
54
56
  def add_atomic_unset(document)
55
57
  document.flagged_for_destroy = true
56
- (delayed_atomic_unsets[document.association_name.to_s] ||= []).push(document)
58
+ key = document.association_name.to_s
59
+ delayed_atomic_unsets[key] ||= []
60
+ delayed_atomic_unsets[key] << document
57
61
  end
58
62
 
59
63
  # Returns path of the attribute for modification
@@ -191,7 +195,13 @@ module Mongoid
191
195
  #
192
196
  # @since 2.1.0
193
197
  def atomic_paths
194
- @atomic_paths ||= _association ? _association.path(self) : Atomic::Paths::Root.new(self)
198
+ @atomic_paths ||= begin
199
+ if _association
200
+ _association.path(self)
201
+ else
202
+ Atomic::Paths::Root.new(self)
203
+ end
204
+ end
195
205
  end
196
206
 
197
207
  # Get all the attributes that need to be pulled.
@@ -12,9 +12,9 @@ module Mongoid
12
12
  # raised.
13
13
  #
14
14
  # @example Create the client.
15
- # Factory.create(:secondary)
15
+ # Factory.create(:analytics)
16
16
  #
17
- # @param [ String, Symbol ] name The named client configuration.
17
+ # @param [ String | Symbol ] name The named client configuration.
18
18
  #
19
19
  # @raise [ Errors::NoClientConfig ] If no config could be found.
20
20
  #
@@ -9,16 +9,16 @@ module Mongoid
9
9
  # Change the persistence context for this object during the block.
10
10
  #
11
11
  # @example Save the current document to a different collection.
12
- # model.with(collection: "secondary") do |m|
12
+ # model.with(collection: "bands") do |m|
13
13
  # m.save
14
14
  # end
15
15
  #
16
16
  # @param [ Hash, Mongoid::PersistenceContext ] options_or_context
17
17
  # The storage options or a persistence context.
18
18
  #
19
- # @option options [ String, Symbol ] :collection The collection name.
20
- # @option options [ String, Symbol ] :database The database name.
21
- # @option options [ String, Symbol ] :client The client name.
19
+ # @option options [ String | Symbol ] :collection The collection name.
20
+ # @option options [ String | Symbol ] :database The database name.
21
+ # @option options [ String | Symbol ] :client The client name.
22
22
  #
23
23
  # @since 6.0.0
24
24
  def with(options_or_context, &block)
@@ -83,15 +83,15 @@ module Mongoid
83
83
  # Change the persistence context for this class during the block.
84
84
  #
85
85
  # @example Save the current document to a different collection.
86
- # Model.with(collection: "secondary") do |m|
86
+ # Model.with(collection: "bands") do |m|
87
87
  # m.create
88
88
  # end
89
89
  #
90
90
  # @param [ Hash ] options The storage options.
91
91
  #
92
- # @option options [ String, Symbol ] :collection The collection name.
93
- # @option options [ String, Symbol ] :database The database name.
94
- # @option options [ String, Symbol ] :client The client name.
92
+ # @option options [ String | Symbol ] :collection The collection name.
93
+ # @option options [ String | Symbol ] :database The database name.
94
+ # @option options [ String | Symbol ] :client The client name.
95
95
  #
96
96
  # @since 6.0.0
97
97
  def with(options, &block)
@@ -41,12 +41,20 @@ module Mongoid
41
41
  #
42
42
  # @since 6.4.0
43
43
  def with_session(options = {})
44
- raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting) if Threaded.get_session
44
+ if Threaded.get_session
45
+ raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting)
46
+ end
45
47
  session = persistence_context.client.start_session(options)
46
48
  Threaded.set_session(session)
47
49
  yield(session)
48
50
  rescue Mongo::Error::InvalidSession => ex
49
- if ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
51
+ if
52
+ # Driver 2.13.0+
53
+ defined?(Mongo::Error::SessionsNotSupported) &&
54
+ Mongo::Error::SessionsNotSupported === ex ||
55
+ # Legacy drivers
56
+ ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
57
+ then
50
58
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
51
59
  end
52
60
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)
@@ -92,12 +100,20 @@ module Mongoid
92
100
  #
93
101
  # @since 6.4.0
94
102
  def with_session(options = {})
95
- raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting) if Threaded.get_session
103
+ if Threaded.get_session
104
+ raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting)
105
+ end
96
106
  session = persistence_context.client.start_session(options)
97
107
  Threaded.set_session(session)
98
108
  yield(session)
99
109
  rescue Mongo::Error::InvalidSession => ex
100
- if ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
110
+ if
111
+ # Driver 2.13.0+
112
+ defined?(Mongo::Error::SessionsNotSupported) &&
113
+ Mongo::Error::SessionsNotSupported === ex ||
114
+ # Legacy drivers
115
+ ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
116
+ then
101
117
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
102
118
  end
103
119
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)