mongoid_monkey 0.3.1 → 0.3.2

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: f0da38ef748517309df870fa4d43e8f76a874659
4
- data.tar.gz: f7383666ee6df0a7ebaa5f508a069da887004f16
3
+ metadata.gz: bbc718cd026b11dfad809f69e4827de71609036d
4
+ data.tar.gz: c0cee3e83c4283ee4df01eeb04a0f0b3c7adb7cf
5
5
  SHA512:
6
- metadata.gz: 4e742d660af83f2b147a6fd58776802d14689fc13a06446f0195d99a3c78218d246b212c06cbf64b351590deb88a864b0214f934ae83cc6edc8f9a9786352162
7
- data.tar.gz: 8a24211a8bf84e5f218a4525914d22fdcc2411f548c80569f22168bcb611ec64aef49c7099ea8d1223ad7dd2630d04ade35347b89ee6badf1fb23493e2ef10fd
6
+ metadata.gz: cd27fedca19eb03a3fc4f022e0c1beb8622b7cb72015bc8961d4b3333fb048245ae51e0283b75806a31dca12c7831aa0cc566305fc8de5b700dcfb954dba6611
7
+ data.tar.gz: 13d63146ced11e02fdb97ce0c447aa511f30f25edbf626927ae1e0f0520d96cc7d2313e0c167bd01685355703721640feecce2a75c0b066288d7c0bb196fe06a
data/README.md CHANGED
@@ -38,6 +38,7 @@ If you would only like some of the patches, please copy and paste the code to yo
38
38
  | `instrument.rb` | Backport instrumentation change to Moped 1. | ● | ○ | ○ |
39
39
  | `reorder.rb` | Backport `Criteria#reorder` method from Mongoid 4. | ● | ○ | ○ |
40
40
  | `only_pluck_localized.rb` | Backport [PR #4299](https://github.com/mongodb/mongoid/pull/4299) from Mongoid 6 which fixes `#only`, `#without`, and `#pluck` with localized fields. | ● | × | × |
41
+ | `push_each.rb` | Backport [PR #4460](https://github.com/mongodb/mongoid/pull/4460) to replace usage of $pushAll with $push + $each for MongoDB 3.6 support. | ● | × | × |
41
42
  | `embedded_touch.rb` (1) | Backport [Issue #3310](https://github.com/mongodb/mongoid/commit/a94c2f43573e58f973913c881ad9d11d62bf857c) from Mongoid 4 to add `:touch` option to `embedded_in`. | ● | ○ | ○ |
42
43
  | `embedded_touch.rb` (2) | Backport [PR #4392](https://github.com/mongodb/mongoid/pull/4392) from Mongoid 6 to fix an infinite loop issue related to `:touch` callbacks. | ● | ● | ● |
43
44
  | `index_options.rb` | Backport latest index valid index options from Mongoid 6. | ● | ● | ○ |
@@ -2,6 +2,7 @@ require 'version'
2
2
 
3
3
  require 'patches/aggregate_cursor'
4
4
  require 'patches/atomic'
5
+ require 'patches/push_each'
5
6
  require 'patches/big_decimal'
6
7
  require 'patches/db_commands'
7
8
  require 'patches/index_options'
@@ -72,7 +72,7 @@ module Atomic
72
72
  # Uses $push + $each rather than $pushAll
73
73
  def push_all(*args)
74
74
  if args.length == 1 && args.first.is_a?(Hash)
75
- query.update_all("$push" => collect_operations(args.first, true))
75
+ query.update_all("$push" => collect_each_operations(args.first))
76
76
  else
77
77
  query.update_all("$push" => { database_field_name(args[0]) => { "$each" => Array.wrap(args[1]) } })
78
78
  end
@@ -102,10 +102,15 @@ module Atomic
102
102
 
103
103
  private
104
104
 
105
- def collect_operations(ops, use_each = false)
106
- ops.inject({}) do |operations, (field, value)|
107
- operations[database_field_name(field)] = use_each ? { '$each' => Array.wrap(value.mongoize) } : value.mongoize
108
- operations
105
+ def collect_operations(ops)
106
+ ops.each_with_object({}) do |(field, value), operations|
107
+ operations[database_field_name(field)] = value.mongoize
108
+ end
109
+ end
110
+
111
+ def collect_each_operations(ops)
112
+ ops.each_with_object({}) do |(field, value), operations|
113
+ operations[database_field_name(field)] = { "$each" => Array.wrap(value).mongoize }
109
114
  end
110
115
  end
111
116
  end
@@ -344,30 +349,4 @@ end
344
349
  end
345
350
  end
346
351
 
347
- # Replace usage of $pushAll with $push + $each
348
- module Mongoid
349
- module Relations
350
- module Embedded
351
- module Batchable
352
-
353
- def batch_insert(docs)
354
- execute_batch_insert(docs, "$push", true)
355
- end
356
-
357
- def execute_batch_insert(docs, operation, use_each = false)
358
- self.inserts_valid = true
359
- inserts = pre_process_batch_insert(docs)
360
- if insertable?
361
- collection.find(selector).update(
362
- positionally(selector, operation => { path => use_each ? { '$each' => Array.wrap(inserts) } : inserts })
363
- )
364
- post_process_batch_insert(docs)
365
- end
366
- inserts
367
- end
368
- end
369
- end
370
- end
371
- end
372
-
373
352
  end
@@ -0,0 +1,63 @@
1
+ # Replace usage of $pushAll with $push + $each for MongoDB 3.6 support.
2
+ # Note that some of this is done in the `atomic.rb` patch as well.
3
+
4
+ if Mongoid::VERSION =~ /\A3\./
5
+
6
+ module Mongoid
7
+ module Relations
8
+ module Embedded
9
+ module Batchable
10
+ def batch_insert(docs)
11
+ execute_batch_insert(docs, "$push", true)
12
+ end
13
+
14
+ def execute_batch_insert(docs, operation, use_each = false)
15
+ self.inserts_valid = true
16
+ inserts = pre_process_batch_insert(docs)
17
+ if insertable?
18
+ collection.find(selector).update(
19
+ positionally(selector, operation => { path => use_each ? { '$each' => inserts } : inserts })
20
+ )
21
+ post_process_batch_insert(docs)
22
+ end
23
+ inserts
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ module Mongoid
31
+ module Atomic
32
+ class Modifiers < Hash
33
+ def push(modifications)
34
+ modifications.each_pair do |field, value|
35
+ push_fields[field] = field
36
+ mods = push_conflict?(field) ? conflicting_pushes : pushes
37
+ add_each_operation(mods, field, value)
38
+ end
39
+ end
40
+
41
+ def add_each_operation(mods, field, value)
42
+ value = Array.wrap(value)
43
+ if mods.has_key?(field)
44
+ value.each do |val|
45
+ mods[field]["$each"].push(val)
46
+ end
47
+ else
48
+ mods[field] = { "$each" => value }
49
+ end
50
+ end
51
+
52
+ def conflicting_pushes
53
+ conflicts["$push"] ||= {}
54
+ end
55
+
56
+ def pushes
57
+ self["$push"] ||= {}
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ end
@@ -1,3 +1,3 @@
1
1
  module MongoidMonkey
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'
3
3
  end
@@ -0,0 +1,810 @@
1
+ require "spec_helper"
2
+
3
+ if Mongoid::VERSION =~ /\A3\./
4
+
5
+ describe Mongoid::Atomic do
6
+
7
+ describe "#add_atomic_pull" do
8
+
9
+ let!(:person) do
10
+ Person.create
11
+ end
12
+
13
+ let(:address) do
14
+ person.addresses.create
15
+ end
16
+
17
+ let(:location) do
18
+ address.locations.create
19
+ end
20
+
21
+ before do
22
+ person.add_atomic_pull(address)
23
+ end
24
+
25
+ it "adds the document to the delayed atomic pulls" do
26
+ expect(person.delayed_atomic_pulls["addresses"]).to eq([ address ])
27
+ end
28
+
29
+ it "flags the document for destruction" do
30
+ expect(address).to be_flagged_for_destroy
31
+ end
32
+ end
33
+
34
+ describe "#add_atomic_unset" do
35
+
36
+ let!(:person) do
37
+ Person.new
38
+ end
39
+
40
+ let(:name) do
41
+ person.build_name
42
+ end
43
+
44
+ before do
45
+ person.add_atomic_unset(name)
46
+ end
47
+
48
+ it "adds the document to the delayed atomic unsets" do
49
+ expect(person.delayed_atomic_unsets["name"]).to eq([ name ])
50
+ end
51
+
52
+ it "flags the document for destruction" do
53
+ expect(name).to be_flagged_for_destroy
54
+ end
55
+ end
56
+
57
+ describe "#atomic_updates" do
58
+
59
+ context "when the document is persisted" do
60
+
61
+ let(:person) do
62
+ Person.create
63
+ end
64
+
65
+ context "when the document is modified" do
66
+
67
+ before do
68
+ person.title = "Sir"
69
+ end
70
+
71
+ it "returns the atomic updates" do
72
+ expect(person.atomic_updates).to eq({ "$set" => { "title" => "Sir" }})
73
+ end
74
+
75
+ context "when an embeds many child is added" do
76
+
77
+ let!(:address) do
78
+ person.addresses.build(street: "Oxford St")
79
+ end
80
+
81
+ it "returns a $set and $push for modifications" do
82
+ expect(person.atomic_updates).to eq(
83
+ {
84
+ "$set" => { "title" => "Sir" },
85
+ "$push" => { "addresses" => { "$each" => [{ "_id" => address._id, "street" => "Oxford St" }] } }
86
+ }
87
+ )
88
+ end
89
+ end
90
+
91
+ context "when an embeds one child is added" do
92
+
93
+ let!(:name) do
94
+ person.build_name(first_name: "Lionel")
95
+ end
96
+
97
+ it "returns a $set for modifications" do
98
+ expect(person.atomic_updates).to eq(
99
+ {
100
+ "$set" => {
101
+ "title" => "Sir",
102
+ "name" => { "_id" => name._id, "first_name" => "Lionel" }
103
+ }
104
+ }
105
+ )
106
+ end
107
+ end
108
+
109
+ context "when an existing embeds many gets modified" do
110
+
111
+ let!(:address) do
112
+ person.addresses.create(street: "Oxford St")
113
+ end
114
+
115
+ before do
116
+ address.street = "Bond St"
117
+ end
118
+
119
+ context "when asking for the updates from the root" do
120
+
121
+ it "returns the $set with correct position and modifications" do
122
+ expect(person.atomic_updates).to eq(
123
+ { "$set" => { "title" => "Sir", "addresses.0.street" => "Bond St" }}
124
+ )
125
+ end
126
+ end
127
+
128
+ context "when asking for the updates from the child" do
129
+
130
+ it "returns the $set with correct position and modifications" do
131
+ expect(address.atomic_updates).to eq(
132
+ { "$set" => { "addresses.0.street" => "Bond St" }}
133
+ )
134
+ end
135
+ end
136
+
137
+ context "when an existing 2nd level embedded child gets modified" do
138
+
139
+ let!(:location) do
140
+ address.locations.create(name: "Home")
141
+ end
142
+
143
+ before do
144
+ location.name = "Work"
145
+ end
146
+
147
+ context "when asking for the updates from the root" do
148
+
149
+ it "returns the $set with correct positions and modifications" do
150
+ expect(person.atomic_updates).to eq(
151
+ { "$set" => {
152
+ "title" => "Sir",
153
+ "addresses.0.street" => "Bond St",
154
+ "addresses.0.locations.0.name" => "Work" }
155
+ }
156
+ )
157
+ end
158
+ end
159
+
160
+ context "when asking for the updates from the 1st level child" do
161
+
162
+ it "returns the $set with correct positions and modifications" do
163
+ expect(address.atomic_updates).to eq(
164
+ { "$set" => {
165
+ "addresses.0.street" => "Bond St",
166
+ "addresses.0.locations.0.name" => "Work" }
167
+ }
168
+ )
169
+ end
170
+ end
171
+
172
+ context "when asking for the updates from the 2nd level child" do
173
+
174
+ it "returns the $set with correct positions and modifications" do
175
+ expect(location.atomic_updates).to eq(
176
+ { "$set" => {
177
+ "addresses.0.locations.0.name" => "Work" }
178
+ }
179
+ )
180
+ end
181
+ end
182
+ end
183
+
184
+ context "when a 2nd level embedded child gets added" do
185
+
186
+ let!(:location) do
187
+ address.locations.build(name: "Home")
188
+ end
189
+
190
+ context "when asking for the updates from the root" do
191
+
192
+ it "returns the $set with correct positions and modifications" do
193
+ expect(person.atomic_updates).to eq(
194
+ {
195
+ "$set" => {
196
+ "title" => "Sir",
197
+ "addresses.0.street" => "Bond St"
198
+ },
199
+ conflicts: {
200
+ "$push" => {
201
+ "addresses.0.locations" => { "$each" => [{ "_id" => location.id, "name" => "Home" }] }
202
+ }
203
+ }
204
+ }
205
+ )
206
+ end
207
+ end
208
+
209
+ context "when asking for the updates from the 1st level child" do
210
+
211
+ it "returns the $set with correct positions and modifications" do
212
+ expect(address.atomic_updates).to eq(
213
+ {
214
+ "$set" => {
215
+ "addresses.0.street" => "Bond St"
216
+ },
217
+ conflicts: {
218
+ "$push" => {
219
+ "addresses.0.locations" => { "$each" => [{ "_id" => location.id, "name" => "Home" }] }
220
+ }
221
+ }
222
+ }
223
+ )
224
+ end
225
+ end
226
+ end
227
+
228
+ context "when an embedded child gets unset" do
229
+
230
+ before do
231
+ person.attributes = { addresses: nil }
232
+ end
233
+
234
+ let(:updates) do
235
+ person.atomic_updates
236
+ end
237
+
238
+ it "returns the $set for the first level and $unset for other." do
239
+ expect(updates).to eq({
240
+ "$unset" => { "addresses" => true },
241
+ "$set" => { "title" => "Sir" }
242
+ })
243
+ end
244
+ end
245
+
246
+ context "when adding a new second level child" do
247
+
248
+ let!(:new_address) do
249
+ person.addresses.build(street: "Another")
250
+ end
251
+
252
+ let!(:location) do
253
+ new_address.locations.build(name: "Home")
254
+ end
255
+
256
+ context "when asking for the updates from the root document" do
257
+
258
+ it "returns the $set for 1st level and other for the 2nd level" do
259
+ expect(person.atomic_updates).to eq(
260
+ {
261
+ "$set" => {
262
+ "title" => "Sir",
263
+ "addresses.0.street" => "Bond St"
264
+ },
265
+ conflicts: {
266
+ "$push" => {
267
+ "addresses" => { "$each" => [{
268
+ "_id" => new_address.id,
269
+ "street" => "Another",
270
+ "locations" => [
271
+ "_id" => location.id,
272
+ "name" => "Home"
273
+ ]
274
+ }] }
275
+ }
276
+ }
277
+ }
278
+ )
279
+ end
280
+ end
281
+
282
+ context "when asking for the updates from the 1st level document" do
283
+
284
+ it "returns the $set for 1st level and other for the 2nd level" do
285
+ expect(address.atomic_updates).to eq(
286
+ { "$set" => { "addresses.0.street" => "Bond St" }}
287
+ )
288
+ end
289
+ end
290
+ end
291
+
292
+ context "when adding a new child beetween two existing and updating one of them" do
293
+
294
+ let!(:new_address) do
295
+ person.addresses.build(street: "Ipanema")
296
+ end
297
+
298
+ let!(:location) do
299
+ new_address.locations.build(name: "Home")
300
+ end
301
+
302
+ before do
303
+ person.addresses[0] = new_address
304
+ person.addresses[1] = address
305
+ end
306
+
307
+ it "returns the $set for 1st and 2nd level and other for the 3nd level" do
308
+ expect(person.atomic_updates).to eq(
309
+ {
310
+ "$set" => {
311
+ "title" => "Sir"
312
+ },
313
+ "$push" => {
314
+ "addresses" => { "$each" => [{
315
+ "_id" => new_address.id,
316
+ "street" => "Ipanema",
317
+ "locations" => [
318
+ "_id" => location.id,
319
+ "name" => "Home"
320
+ ]
321
+ }] }
322
+ },
323
+ conflicts: {
324
+ "$set" => { "addresses.0.street"=>"Bond St" }
325
+ }
326
+ }
327
+ )
328
+ end
329
+ end
330
+ end
331
+
332
+ context "when adding new embedded docs at multiple levels" do
333
+
334
+ let!(:address) do
335
+ person.addresses.build(street: "Another")
336
+ end
337
+
338
+ let!(:location) do
339
+ address.locations.build(name: "Home")
340
+ end
341
+
342
+ it "returns the proper $sets and $pushes for all levels" do
343
+ expect(person.atomic_updates).to eq(
344
+ {
345
+ "$set" => {
346
+ "title" => "Sir",
347
+ },
348
+ "$push" => {
349
+ "addresses" => { "$each" => [{
350
+ "_id" => address.id,
351
+ "street" => "Another",
352
+ "locations" => [
353
+ "_id" => location.id,
354
+ "name" => "Home"
355
+ ]
356
+ }] }
357
+ }
358
+ }
359
+ )
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end
365
+ end
366
+
367
+ describe Mongoid::Atomic::Modifiers do
368
+
369
+ let(:modifiers) do
370
+ described_class.new
371
+ end
372
+
373
+ describe "#add_to_set" do
374
+
375
+ context "when the unique adds are empty" do
376
+
377
+ before do
378
+ modifiers.add_to_set({})
379
+ end
380
+
381
+ it "does not contain any operations" do
382
+ expect(modifiers).to eq({})
383
+ end
384
+ end
385
+
386
+ context "when the adds are not empty" do
387
+
388
+ let(:adds) do
389
+ { "preference_ids" => [ "one", "two" ] }
390
+ end
391
+
392
+ context "when adding a single field" do
393
+
394
+ before do
395
+ modifiers.add_to_set(adds)
396
+ end
397
+
398
+ it "adds the add to set with each modifiers" do
399
+ expect(modifiers).to eq({
400
+ "$addToSet" => { "preference_ids" => { "$each" => [ "one", "two" ] }}
401
+ })
402
+ end
403
+ end
404
+
405
+ context "when adding to an existing field" do
406
+
407
+ let(:adds_two) do
408
+ { "preference_ids" => [ "three" ] }
409
+ end
410
+
411
+ before do
412
+ modifiers.add_to_set(adds)
413
+ modifiers.add_to_set(adds_two)
414
+ end
415
+
416
+ it "adds the add to set with each modifiers" do
417
+ expect(modifiers).to eq({
418
+ "$addToSet" =>
419
+ { "preference_ids" =>
420
+ { "$each" => [ "one", "two", "three" ] }
421
+ }
422
+ })
423
+ end
424
+ end
425
+ end
426
+ end
427
+
428
+ describe "#pull" do
429
+
430
+ context "when the pulls are empty" do
431
+
432
+ before do
433
+ modifiers.pull({})
434
+ end
435
+
436
+ it "does not contain any pull operations" do
437
+ expect(modifiers).to eq({})
438
+ end
439
+ end
440
+
441
+ context "when no conflicting modifications are present" do
442
+
443
+ context "when adding a single pull" do
444
+
445
+ let(:pulls) do
446
+ { "addresses" => { "_id" => { "$in" => [ "one" ]}} }
447
+ end
448
+
449
+ before do
450
+ modifiers.pull(pulls)
451
+ end
452
+
453
+ it "adds the push all modifiers" do
454
+ expect(modifiers).to eq(
455
+ { "$pull" => { "addresses" => { "_id" => { "$in" => [ "one" ]}}}}
456
+ )
457
+ end
458
+ end
459
+
460
+ context "when adding to an existing pull" do
461
+
462
+ let(:pull_one) do
463
+ { "addresses" => { "_id" => { "$in" => [ "one" ]}} }
464
+ end
465
+
466
+ let(:pull_two) do
467
+ { "addresses" => { "_id" => { "$in" => [ "two" ]}} }
468
+ end
469
+
470
+ before do
471
+ modifiers.pull(pull_one)
472
+ modifiers.pull(pull_two)
473
+ end
474
+
475
+ it "overwrites the previous pulls" do
476
+ expect(modifiers).to eq(
477
+ { "$pull" => { "addresses" => { "_id" => { "$in" => [ "two" ]}}}}
478
+ )
479
+ end
480
+ end
481
+ end
482
+ end
483
+
484
+ describe "#pull_all" do
485
+
486
+ context "when the pulls are empty" do
487
+
488
+ before do
489
+ modifiers.pull_all({})
490
+ end
491
+
492
+ it "does not contain any pull operations" do
493
+ expect(modifiers).to eq({})
494
+ end
495
+ end
496
+
497
+ context "when no conflicting modifications are present" do
498
+
499
+ context "when adding a single pull" do
500
+
501
+ let(:pulls) do
502
+ { "addresses" => [{ "_id" => "one" }] }
503
+ end
504
+
505
+ before do
506
+ modifiers.pull_all(pulls)
507
+ end
508
+
509
+ it "adds the push all modifiers" do
510
+ expect(modifiers).to eq(
511
+ { "$pullAll" =>
512
+ { "addresses" => [
513
+ { "_id" => "one" }
514
+ ]
515
+ }
516
+ }
517
+ )
518
+ end
519
+ end
520
+
521
+ context "when adding to an existing pull" do
522
+
523
+ let(:pull_one) do
524
+ { "addresses" => [{ "street" => "Hobrechtstr." }] }
525
+ end
526
+
527
+ let(:pull_two) do
528
+ { "addresses" => [{ "street" => "Pflugerstr." }] }
529
+ end
530
+
531
+ before do
532
+ modifiers.pull_all(pull_one)
533
+ modifiers.pull_all(pull_two)
534
+ end
535
+
536
+ it "adds the pull all modifiers" do
537
+ expect(modifiers).to eq(
538
+ { "$pullAll" =>
539
+ { "addresses" => [
540
+ { "street" => "Hobrechtstr." },
541
+ { "street" => "Pflugerstr." }
542
+ ]
543
+ }
544
+ }
545
+ )
546
+ end
547
+ end
548
+ end
549
+ end
550
+
551
+ describe "#push" do
552
+
553
+ context "when the pushes are empty" do
554
+
555
+ before do
556
+ modifiers.push({})
557
+ end
558
+
559
+ it "does not contain any push operations" do
560
+ expect(modifiers).to eq({})
561
+ end
562
+ end
563
+
564
+ context "when no conflicting modification is present" do
565
+
566
+ context "when adding a single push" do
567
+
568
+ let(:pushes) do
569
+ { "addresses" => { "street" => "Oxford St" } }
570
+ end
571
+
572
+ before do
573
+ modifiers.push(pushes)
574
+ end
575
+
576
+ it "adds the push all modifiers" do
577
+ expect(modifiers).to eq(
578
+ { "$push" =>
579
+ { "addresses" => { "$each" => [{ "street" => "Oxford St" }] } }
580
+ }
581
+ )
582
+ end
583
+ end
584
+
585
+ context "when adding to an existing push" do
586
+
587
+ let(:push_one) do
588
+ { "addresses" => { "street" => "Hobrechtstr." } }
589
+ end
590
+
591
+ let(:push_two) do
592
+ { "addresses" => { "street" => "Pflugerstr." } }
593
+ end
594
+
595
+ before do
596
+ modifiers.push(push_one)
597
+ modifiers.push(push_two)
598
+ end
599
+
600
+ it "adds the push all modifiers" do
601
+ expect(modifiers).to eq(
602
+ { "$push" =>
603
+ { "addresses" => { "$each" => [
604
+ { "street" => "Hobrechtstr." },
605
+ { "street" => "Pflugerstr." }
606
+ ] }
607
+ }
608
+ }
609
+ )
610
+ end
611
+ end
612
+ end
613
+
614
+ context "when a conflicting modification exists" do
615
+
616
+ context "when the conflicting modification is a set" do
617
+
618
+ let(:sets) do
619
+ { "addresses.0.street" => "Bond" }
620
+ end
621
+
622
+ let(:pushes) do
623
+ { "addresses" => { "street" => "Oxford St" } }
624
+ end
625
+
626
+ before do
627
+ modifiers.set(sets)
628
+ modifiers.push(pushes)
629
+ end
630
+
631
+ it "adds the push all modifiers to the conflicts hash" do
632
+ expect(modifiers).to eq(
633
+ { "$set" => { "addresses.0.street" => "Bond" },
634
+ conflicts: { "$push" =>
635
+ { "addresses" => { "$each" => [{ "street" => "Oxford St" }] } }
636
+ }
637
+ }
638
+ )
639
+ end
640
+ end
641
+
642
+ context "when the conflicting modification is a pull" do
643
+
644
+ let(:pulls) do
645
+ { "addresses" => { "street" => "Bond St" } }
646
+ end
647
+
648
+ let(:pushes) do
649
+ { "addresses" => { "street" => "Oxford St" } }
650
+ end
651
+
652
+ before do
653
+ modifiers.pull_all(pulls)
654
+ modifiers.push(pushes)
655
+ end
656
+
657
+ it "adds the push all modifiers to the conflicts hash" do
658
+ expect(modifiers).to eq(
659
+ { "$pullAll" => {
660
+ "addresses" => { "street" => "Bond St" }},
661
+ conflicts: { "$push" =>
662
+ { "addresses" => { "$each" => [{ "street" => "Oxford St" }] } }
663
+ }
664
+ }
665
+ )
666
+ end
667
+ end
668
+
669
+ context "when the conflicting modification is a push" do
670
+
671
+ let(:nested) do
672
+ { "addresses.0.locations" => { "street" => "Bond St" } }
673
+ end
674
+
675
+ let(:pushes) do
676
+ { "addresses" => { "street" => "Oxford St" } }
677
+ end
678
+
679
+ before do
680
+ modifiers.push(nested)
681
+ modifiers.push(pushes)
682
+ end
683
+
684
+ it "adds the push all modifiers to the conflicts hash" do
685
+ expect(modifiers).to eq(
686
+ { "$push" => {
687
+ "addresses.0.locations" => { "$each" => [{ "street" => "Bond St" }] } },
688
+ conflicts: { "$push" =>
689
+ { "addresses" => { "$each" => [{ "street" => "Oxford St" }] } }
690
+ }
691
+ }
692
+ )
693
+ end
694
+ end
695
+ end
696
+ end
697
+
698
+ describe "#set" do
699
+
700
+ describe "when adding to the root level" do
701
+
702
+ context "when no conflicting mods exist" do
703
+
704
+ context "when the sets have values" do
705
+
706
+ let(:sets) do
707
+ { "title" => "Sir" }
708
+ end
709
+
710
+ before do
711
+ modifiers.set(sets)
712
+ end
713
+
714
+ it "adds the sets to the modifiers" do
715
+ expect(modifiers).to eq({ "$set" => { "title" => "Sir" } })
716
+ end
717
+ end
718
+
719
+ context "when the sets contain an id" do
720
+
721
+ let(:sets) do
722
+ { "_id" => Moped::BSON::ObjectId.new }
723
+ end
724
+
725
+ before do
726
+ modifiers.set(sets)
727
+ end
728
+
729
+ it "does not include the id sets" do
730
+ expect(modifiers).to eq({})
731
+ end
732
+ end
733
+
734
+ context "when the sets are empty" do
735
+
736
+ before do
737
+ modifiers.set({})
738
+ end
739
+
740
+ it "does not contain set operations" do
741
+ expect(modifiers).to eq({})
742
+ end
743
+ end
744
+ end
745
+
746
+ context "when a conflicting modification exists" do
747
+
748
+ let(:pulls) do
749
+ { "addresses" => [{ "_id" => "one" }] }
750
+ end
751
+
752
+ let(:sets) do
753
+ { "addresses.0.title" => "Sir" }
754
+ end
755
+
756
+ before do
757
+ modifiers.pull_all(pulls)
758
+ modifiers.set(sets)
759
+ end
760
+
761
+ it "adds the set modifiers to the conflicts hash" do
762
+ expect(modifiers).to eq(
763
+ { "$pullAll" =>
764
+ { "addresses" => [
765
+ { "_id" => "one" }
766
+ ]
767
+ },
768
+ conflicts:
769
+ { "$set" => { "addresses.0.title" => "Sir" }}
770
+ }
771
+ )
772
+ end
773
+ end
774
+ end
775
+ end
776
+
777
+ describe "#unset" do
778
+
779
+ describe "when adding to the root level" do
780
+
781
+ context "when the unsets have values" do
782
+
783
+ let(:unsets) do
784
+ [ "addresses" ]
785
+ end
786
+
787
+ before do
788
+ modifiers.unset(unsets)
789
+ end
790
+
791
+ it "adds the unsets to the modifiers" do
792
+ expect(modifiers).to eq({ "$unset" => { "addresses" => true } })
793
+ end
794
+ end
795
+
796
+ context "when the unsets are empty" do
797
+
798
+ before do
799
+ modifiers.unset([])
800
+ end
801
+
802
+ it "does not contain unset operations" do
803
+ expect(modifiers).to eq({})
804
+ end
805
+ end
806
+ end
807
+ end
808
+ end
809
+
810
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_monkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - johnnyshields
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-07 00:00:00.000000000 Z
11
+ date: 2018-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -71,6 +71,7 @@ files:
71
71
  - lib/patches/index_options.rb
72
72
  - lib/patches/instrument.rb
73
73
  - lib/patches/only_pluck_localized.rb
74
+ - lib/patches/push_each.rb
74
75
  - lib/patches/reorder.rb
75
76
  - lib/patches/write_concern.rb
76
77
  - lib/version.rb
@@ -139,6 +140,7 @@ files:
139
140
  - spec/unit/index_options_spec.rb
140
141
  - spec/unit/instrument_spec.rb
141
142
  - spec/unit/only_pluck_localized_spec.rb
143
+ - spec/unit/push_each_spec.rb
142
144
  - spec/unit/reorder_spec.rb
143
145
  - spec/unit/write_concern_spec.rb
144
146
  homepage: https://github.com/johnnyshields/mongoid_monkey
@@ -231,5 +233,6 @@ test_files:
231
233
  - spec/unit/index_options_spec.rb
232
234
  - spec/unit/instrument_spec.rb
233
235
  - spec/unit/only_pluck_localized_spec.rb
236
+ - spec/unit/push_each_spec.rb
234
237
  - spec/unit/reorder_spec.rb
235
238
  - spec/unit/write_concern_spec.rb