mongoid_monkey 0.3.1 → 0.3.2

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.
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