mongoid 6.2.1 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3c168797ecc312fa19fb9e5e411faac9d8d0386
4
- data.tar.gz: d8221f9f5edf4199630a5951169150ed864830af
3
+ metadata.gz: 5c7e1fbb3fda280fb0e0f74c312b36b7a73dad79
4
+ data.tar.gz: 92dcab3023e9005560efd4209e3eecd26032b259
5
5
  SHA512:
6
- metadata.gz: 8f7acb7b8783289ff4a2986353e4eeb0443643d4b957ed15752a37045a7e906bda3cb5cc5ebf3d75c222ce8926aee29176b38cab2baad80e663fc83eb0bb1b02
7
- data.tar.gz: 45304b581fdcca4076ce109db08926de9e30917f9ac439f94b2bd51fbfe3939d32dce787f48236738cd015c0c0b2e90c7d68905dd5744b08ec33adb3a8ccaae2
6
+ metadata.gz: 44e65ba1446fc7c42e545b38223d4122e798f85d26aeb93103b85c45e7a4abc17e3b7da9f60853a7a38a24b5d4a258338111759d0b22bb4e5f99611e002eaa0f
7
+ data.tar.gz: 25b84f09ac4fb6366a0d9782d0865a0a1ae214234fbdbde4ce57146d8bf740823b66f15d4871e4a45b0d3fc5f0557b9f91dd743501713ae6920a430e90bab62e
@@ -1,2 +1,3 @@
1
- y~zL�|tT��נq'��`�B~gg�%�U�&?U�Ů�;����@nWɞ����H����ۄ�\{6�!$u�42{�8�GC���W�Q8����9�]�c~+,*�V{{��@=*ȴ��7�$_b���2�`���dQ7���#-g�**w�v����7���૏~��Q�?�A���;^IԪFN�ARm?��)7�����1��Y�
2
- �Ċ�;]����%D������y:<H����/�PTu�,O%�s��1��Dۯ
1
+ kpQ5NePGlt
2
+ ���#$[?�)�} �A�����!�QV��+i�t�[=w
3
+ �->dƩHR�uǖ{v�|��G\bS$���l��g���=�82���̵�� W��>��BL+�Z�cS�E9�����c ����Ox��)�6Ũ�Nd#���'ĝc,��5������h���UfO\LE*�{��'%��d�\@�Y���z�c�N� �W�?���@�:�e3Ҟv-��
data.tar.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- �v��qz�G�"�:�~�,X�{h�;(�!�E2�Ç ����ct�W�^G�%@ ��Y�ª�e֚�=~m�/�(� �"��6ɯ��%|vC$��u�����/'΃!�86���'{n!h6�:��טr)!Aޜk�������nw}�{*�ٰ��G�#�>�X��#ӝM�?d�1;>�� "$�����p긚]����}k�� U���9�P����H~R���)�jHUK�HQ�0}��
2
- ��
1
+ ��2�{&r�<`��?R��|$���L�����Yک�}NGbf�Đ���R܀6>��t������� 8�I_�^a�@:vt����ލ� }� ���G����`�?�;b9}
2
+ -�.�ɮog@B���M�F�0��_e_�Bc�9yY�M-+\��
@@ -110,10 +110,10 @@ module Mongoid
110
110
  # performed in a single operation. Conflicting modifications are
111
111
  # detected by the 'haveConflictingMod' function in MongoDB.
112
112
  # Examination of the code suggests that two modifications (a $set
113
- # and a $pushAll, for example) conflict if:
113
+ # and a $push with $each, for example) conflict if:
114
114
  # (1) the key paths being modified are equal.
115
115
  # (2) one key path is a prefix of the other.
116
- # So a $set of 'addresses.0.street' will conflict with a $pushAll
116
+ # So a $set of 'addresses.0.street' will conflict with a $push and $each
117
117
  # to 'addresses', and we will need to split our update into two
118
118
  # pieces. We do not, however, attempt to match MongoDB's logic
119
119
  # exactly. Instead, we assume that two updates conflict if the
@@ -218,7 +218,7 @@ module Mongoid
218
218
  # @example Get the pushes.
219
219
  # person.atomic_pushes
220
220
  #
221
- # @return [ Hash ] The $pushAll operations.
221
+ # @return [ Hash ] The The $push and $each operations.
222
222
  #
223
223
  # @since 2.1.0
224
224
  def atomic_pushes
@@ -68,7 +68,7 @@ module Mongoid
68
68
  modifications.each_pair do |field, value|
69
69
  push_fields[field] = field
70
70
  mods = push_conflict?(field) ? conflicting_pushes : pushes
71
- add_operation(mods, field, Array.wrap(value))
71
+ add_operation(mods, field, { '$each' => Array.wrap(value) })
72
72
  end
73
73
  end
74
74
 
@@ -118,8 +118,12 @@ module Mongoid
118
118
  # @since 2.2.0
119
119
  def add_operation(mods, field, value)
120
120
  if mods.has_key?(field)
121
- value.each do |val|
122
- mods[field].push(val)
121
+ if mods[field].is_a?(Array)
122
+ value.each do |val|
123
+ mods[field].push(val)
124
+ end
125
+ elsif mods[field]['$each']
126
+ mods[field]['$each'].concat(value['$each'])
123
127
  end
124
128
  else
125
129
  mods[field] = value
@@ -190,7 +194,7 @@ module Mongoid
190
194
  #
191
195
  # @since 2.2.0
192
196
  def conflicting_pushes
193
- conflicts["$pushAll"] ||= {}
197
+ conflicts["$push"] ||= {}
194
198
  end
195
199
 
196
200
  # Get the conflicting set modifications.
@@ -277,16 +281,16 @@ module Mongoid
277
281
  self["$pull"] ||= {}
278
282
  end
279
283
 
280
- # Get the $pushAll operations or intialize a new one.
284
+ # Get the $push/$each operations or initialize a new one.
281
285
  #
282
- # @example Get the $pushAll operations.
286
+ # @example Get the $push/$each operations.
283
287
  # modifiers.pushes
284
288
  #
285
- # @return [ Hash ] The $pushAll operations.
289
+ # @return [ Hash ] The $push/$each operations.
286
290
  #
287
291
  # @since 2.1.0
288
292
  def pushes
289
- self["$pushAll"] ||= {}
293
+ self["$push"] ||= {}
290
294
  end
291
295
 
292
296
  # Get the $set operations or intialize a new one.
@@ -84,6 +84,7 @@ module Mongoid
84
84
  Validatable,
85
85
  Equality,
86
86
  Relations::Synchronization,
87
+ Relations::Macros,
87
88
  ActiveModel::Model,
88
89
  ActiveModel::Validations
89
90
  ]
@@ -106,10 +106,10 @@ module Mongoid
106
106
  view.update_many("$push" => collect_operations(pushes))
107
107
  end
108
108
 
109
- # Perform an atomic $pushAll operation on the matching documents.
109
+ # Perform an atomic $push/$each operation on the matching documents.
110
110
  #
111
111
  # @example Push the values to the matching docs.
112
- # context.push(members: [ "Alan", "Fletch" ])
112
+ # context.push_all(members: [ "Alan", "Fletch" ])
113
113
  #
114
114
  # @param [ Hash ] pushes The operations.
115
115
  #
@@ -117,7 +117,10 @@ module Mongoid
117
117
  #
118
118
  # @since 3.0.0
119
119
  def push_all(pushes)
120
- view.update_many("$pushAll" => collect_operations(pushes))
120
+ push_each_updates = collect_operations(pushes).each.inject({}) do |ops, (field, elements)|
121
+ ops.merge!(field => {'$each' => elements})
122
+ end
123
+ view.update_many("$push" => push_each_updates)
121
124
  end
122
125
 
123
126
  # Perform an atomic $rename of fields on the matching documents.
@@ -486,12 +486,16 @@ module Mongoid
486
486
  # context.update({ "$set" => { name: "Smiths" }})
487
487
  #
488
488
  # @param [ Hash ] attributes The new attributes for the document.
489
+ # @param [ Hash ] opts The update operation options.
490
+ #
491
+ # @option opts [ Array ] :array_filters A set of filters specifying to which array elements
492
+ # an update should apply.
489
493
  #
490
494
  # @return [ nil, false ] False if no attributes were provided.
491
495
  #
492
496
  # @since 3.0.0
493
- def update(attributes = nil)
494
- update_documents(attributes)
497
+ def update(attributes = nil, opts = {})
498
+ update_documents(attributes, :update_one, opts)
495
499
  end
496
500
 
497
501
  # Update all the matching documents atomically.
@@ -500,12 +504,16 @@ module Mongoid
500
504
  # context.update_all({ "$set" => { name: "Smiths" }})
501
505
  #
502
506
  # @param [ Hash ] attributes The new attributes for each document.
507
+ # @param [ Hash ] opts The update operation options.
508
+ #
509
+ # @option opts [ Array ] :array_filters A set of filters specifying to which array elements
510
+ # an update should apply.
503
511
  #
504
512
  # @return [ nil, false ] False if no attributes were provided.
505
513
  #
506
514
  # @since 3.0.0
507
- def update_all(attributes = nil)
508
- update_documents(attributes, :update_many)
515
+ def update_all(attributes = nil, opts = {})
516
+ update_documents(attributes, :update_many, opts)
509
517
  end
510
518
 
511
519
  private
@@ -541,10 +549,10 @@ module Mongoid
541
549
  # @return [ true, false ] If the update succeeded.
542
550
  #
543
551
  # @since 3.0.4
544
- def update_documents(attributes, method = :update_one)
552
+ def update_documents(attributes, method = :update_one, opts = {})
545
553
  return false unless attributes
546
554
  attributes = Hash[attributes.map { |k, v| [klass.database_field_name(k.to_s), v] }]
547
- view.send(method, attributes.__consolidate__(klass))
555
+ view.send(method, attributes.__consolidate__(klass), opts)
548
556
  end
549
557
 
550
558
  # Apply the field limitations.
@@ -17,7 +17,8 @@ module Mongoid
17
17
  #
18
18
  # @return [ Document ] The instantiated document.
19
19
  def build(klass, attributes = nil)
20
- type = (attributes || {})[TYPE]
20
+ attributes ||= {}
21
+ type = attributes[TYPE] || attributes[TYPE.to_sym]
21
22
  if type && klass._types.include?(type)
22
23
  type.constantize.new(attributes)
23
24
  else
@@ -195,10 +195,10 @@ module Mongoid
195
195
  Thread.current["[mongoid][#{object.object_id}]:context"]
196
196
  end
197
197
 
198
- # Get the persistence context for a particular class or model instance.
198
+ # Clear the persistence context for a particular class or model instance.
199
199
  #
200
- # @example Get the persistence context for a class or model instance.
201
- # PersistenceContext.get(model)
200
+ # @example Clear the persistence context for a class or model instance.
201
+ # PersistenceContext.clear(model)
202
202
  #
203
203
  # @param [ Class, Object ] object The class or model instance.
204
204
  # @param [ Mongo::Cluster ] cluster The original cluster before this context was used.
@@ -208,8 +208,9 @@ module Mongoid
208
208
  if context = get(object)
209
209
  context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
210
210
  end
211
+ ensure
211
212
  Thread.current["[mongoid][#{object.object_id}]:context"] = nil
212
213
  end
213
214
  end
214
215
  end
215
- end
216
+ end
@@ -222,9 +222,11 @@ module Mongoid
222
222
  super
223
223
  else
224
224
  unless cursor = cached_cursor
225
- server = read.select_server(cluster)
226
- cursor = CachedCursor.new(view, send_initial_query(server), server)
227
- QueryCache.cache_table[cache_key] = cursor
225
+ read_with_retry do
226
+ server = server_selector.select_server(cluster)
227
+ cursor = CachedCursor.new(view, send_initial_query(server), server)
228
+ QueryCache.cache_table[cache_key] = cursor
229
+ end
228
230
  end
229
231
  cursor.each do |doc|
230
232
  yield doc
@@ -8,7 +8,7 @@ module Mongoid
8
8
  module Batchable
9
9
  include Positional
10
10
 
11
- # Insert new documents as a batch push ($pushAll). This ensures that
11
+ # Insert new documents as a batch push ($push with $each). This ensures that
12
12
  # all callbacks are run at the appropriate time and only 1 request is
13
13
  # made to the database.
14
14
  #
@@ -21,7 +21,7 @@ module Mongoid
21
21
  #
22
22
  # @since 3.0.0
23
23
  def batch_insert(docs)
24
- execute_batch_insert(docs, "$pushAll")
24
+ execute_batch_push(docs)
25
25
  end
26
26
 
27
27
  # Clear all of the docs out of the relation in a single swipe.
@@ -89,7 +89,7 @@ module Mongoid
89
89
  base.delayed_atomic_sets.clear unless _assigning?
90
90
  docs = normalize_docs(docs).compact
91
91
  target.clear and _unscoped.clear
92
- inserts = execute_batch_insert(docs, "$set")
92
+ inserts = execute_batch_set(docs)
93
93
  add_atomic_sets(inserts)
94
94
  end
95
95
  end
@@ -116,32 +116,52 @@ module Mongoid
116
116
  end
117
117
  end
118
118
 
119
- # Perform a batch persist of the provided documents with the supplied
120
- # operation.
119
+ # Perform a batch persist of the provided documents with a $set.
121
120
  #
122
121
  # @api private
123
122
  #
124
- # @example Perform a batch operation.
125
- # batchable.execute_batch(docs, "$set")
123
+ #@example Perform a batch $set.
124
+ # batchable.execute_batch_set(docs)
126
125
  #
127
126
  # @param [ Array<Document> ] docs The docs to persist.
128
- # @param [ String ] operation The atomic operation.
129
127
  #
130
128
  # @return [ Array<Hash> ] The inserts.
131
129
  #
132
- # @since 3.0.0
133
- def execute_batch_insert(docs, operation)
130
+ # @since 7.0.0
131
+ def execute_batch_set(docs)
134
132
  self.inserts_valid = true
135
133
  inserts = pre_process_batch_insert(docs)
136
134
  if insertable?
137
135
  collection.find(selector).update_one(
138
- positionally(selector, operation => { path => inserts })
139
- )
136
+ positionally(selector, '$set' => { path => inserts }))
140
137
  post_process_batch_insert(docs)
141
138
  end
142
139
  inserts
143
140
  end
144
141
 
142
+ # Perform a batch persist of the provided documents with $push and $each.
143
+ #
144
+ # @api private
145
+ #
146
+ # @example Perform a batch push.
147
+ # batchable.execute_batch_push(docs)
148
+ #
149
+ # @param [ Array<Document> ] docs The docs to persist.
150
+ #
151
+ # @return [ Array<Hash> ] The inserts.
152
+ #
153
+ # @since 7.0.0
154
+ def execute_batch_push(docs)
155
+ self.inserts_valid = true
156
+ pushes = pre_process_batch_insert(docs)
157
+ if insertable?
158
+ collection.find(selector).update_one(
159
+ positionally(selector, '$push' => { path => { '$each' => pushes } }))
160
+ post_process_batch_insert(docs)
161
+ end
162
+ pushes
163
+ end
164
+
145
165
  # Are we in a state to be able to batch insert?
146
166
  #
147
167
  # @api private
@@ -81,7 +81,7 @@ module Mongoid
81
81
  adds, subs = new - (old || []), (old || []) - new
82
82
 
83
83
  # If we are autosaving we don't want a duplicate to get added - the
84
- # $addToSet would run previously and then the $pushAll from the
84
+ # $addToSet would run previously and then the $push and $each from the
85
85
  # inverse on the autosave would cause this. We delete each id from
86
86
  # what's in memory in case a mix of id addition and object addition
87
87
  # had occurred.
@@ -214,12 +214,22 @@ module Mongoid
214
214
  # @example Get the first document.
215
215
  # enumerable.first
216
216
  #
217
+ # @note Automatically adding a sort on _id when no other sort is
218
+ # defined on the criteria has the potential to cause bad performance issues.
219
+ # If you experience unexpected poor performance when using #first or #last,
220
+ # use the option { id_sort: :none }.
221
+ # Be aware that #first/#last won't guarantee order in this case.
222
+ #
223
+ # @param [ Hash ] opts The options for the query returning the first document.
224
+ #
225
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
226
+ #
217
227
  # @return [ Document ] The first document found.
218
228
  #
219
229
  # @since 2.1.0
220
- def first
230
+ def first(opts = {})
221
231
  _loaded.try(:values).try(:first) ||
222
- _added[(ul = _unloaded.try(:first)).try(:id)] ||
232
+ _added[(ul = _unloaded.try(:first, opts)).try(:id)] ||
223
233
  ul ||
224
234
  _added.values.try(:first)
225
235
  end
@@ -298,13 +308,23 @@ module Mongoid
298
308
  # @example Get the last document.
299
309
  # enumerable.last
300
310
  #
311
+ # @note Automatically adding a sort on _id when no other sort is
312
+ # defined on the criteria has the potential to cause bad performance issues.
313
+ # If you experience unexpected poor performance when using #first or #last,
314
+ # use the option { id_sort: :none }.
315
+ # Be aware that #first/#last won't guarantee order in this case.
316
+ #
317
+ # @param [ Hash ] opts The options for the query returning the first document.
318
+ #
319
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
320
+ #
301
321
  # @return [ Document ] The last document found.
302
322
  #
303
323
  # @since 2.1.0
304
- def last
324
+ def last(opts = {})
305
325
  _added.values.try(:last) ||
306
326
  _loaded.try(:values).try(:last) ||
307
- _added[(ul = _unloaded.try(:last)).try(:id)] ||
327
+ _added[(ul = _unloaded.try(:last, opts)).try(:id)] ||
308
328
  ul
309
329
  end
310
330
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid
3
- VERSION = "6.2.1"
3
+ VERSION = "6.3.0"
4
4
  end
@@ -20,6 +20,7 @@ class Band
20
20
 
21
21
  embeds_many :records, cascade_callbacks: true
22
22
  embeds_many :notes, as: :noteable, cascade_callbacks: true, validate: false
23
+ embeds_many :labels
23
24
  embeds_one :label, cascade_callbacks: true
24
25
 
25
26
  has_many :same_name, class_name: 'Agent', inverse_of: :same_name
@@ -211,10 +211,10 @@ describe Mongoid::Atomic::Modifiers do
211
211
 
212
212
  it "adds the push all modifiers" do
213
213
  expect(modifiers).to eq(
214
- { "$pushAll" =>
215
- { "addresses" => [
214
+ { "$push" =>
215
+ { "addresses" => { '$each' => [
216
216
  { "street" => "Oxford St" }
217
- ]
217
+ ] }
218
218
  }
219
219
  }
220
220
  )
@@ -238,11 +238,11 @@ describe Mongoid::Atomic::Modifiers do
238
238
 
239
239
  it "adds the push all modifiers" do
240
240
  expect(modifiers).to eq(
241
- { "$pushAll" =>
242
- { "addresses" => [
241
+ { "$push" =>
242
+ { "addresses" => { '$each' => [
243
243
  { "street" => "Hobrechtstr." },
244
244
  { "street" => "Pflugerstr." }
245
- ]
245
+ ] }
246
246
  }
247
247
  }
248
248
  )
@@ -270,10 +270,10 @@ describe Mongoid::Atomic::Modifiers do
270
270
  it "adds the push all modifiers to the conflicts hash" do
271
271
  expect(modifiers).to eq(
272
272
  { "$set" => { "addresses.0.street" => "Bond" },
273
- conflicts: { "$pushAll" =>
274
- { "addresses" => [
273
+ conflicts: { "$push" =>
274
+ { "addresses" => { '$each' => [
275
275
  { "street" => "Oxford St" }
276
- ]
276
+ ] }
277
277
  }
278
278
  }
279
279
  }
@@ -300,10 +300,10 @@ describe Mongoid::Atomic::Modifiers do
300
300
  expect(modifiers).to eq(
301
301
  { "$pullAll" => {
302
302
  "addresses" => { "street" => "Bond St" }},
303
- conflicts: { "$pushAll" =>
304
- { "addresses" => [
303
+ conflicts: { "$push" =>
304
+ { "addresses" => { '$each' => [
305
305
  { "street" => "Oxford St" }
306
- ]
306
+ ] }
307
307
  }
308
308
  }
309
309
  }
@@ -328,12 +328,12 @@ describe Mongoid::Atomic::Modifiers do
328
328
 
329
329
  it "adds the push all modifiers to the conflicts hash" do
330
330
  expect(modifiers).to eq(
331
- { "$pushAll" => {
332
- "addresses.0.locations" => [{ "street" => "Bond St" }]},
333
- conflicts: { "$pushAll" =>
334
- { "addresses" => [
331
+ { "$push" => {
332
+ "addresses.0.locations" => { '$each' => [{ "street" => "Bond St" }] } },
333
+ conflicts: { "$push" =>
334
+ { "addresses" => { '$each' => [
335
335
  { "street" => "Oxford St" }
336
- ]
336
+ ] }
337
337
  }
338
338
  }
339
339
  }