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 +4 -4
- data/README.md +1 -0
- data/lib/mongoid_monkey.rb +1 -0
- data/lib/patches/atomic.rb +10 -31
- data/lib/patches/push_each.rb +63 -0
- data/lib/version.rb +1 -1
- data/spec/unit/push_each_spec.rb +810 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbc718cd026b11dfad809f69e4827de71609036d
|
4
|
+
data.tar.gz: c0cee3e83c4283ee4df01eeb04a0f0b3c7adb7cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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. | ● | ● | ○ |
|
data/lib/mongoid_monkey.rb
CHANGED
data/lib/patches/atomic.rb
CHANGED
@@ -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" =>
|
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
|
106
|
-
ops.
|
107
|
-
operations[database_field_name(field)] =
|
108
|
-
|
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
|
data/lib/version.rb
CHANGED
@@ -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.
|
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-
|
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
|