mongoid 4.0.0 → 4.0.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -1
  3. data/README.md +6 -2
  4. data/lib/config/locales/en.yml +2 -2
  5. data/lib/mongoid/atomic.rb +2 -2
  6. data/lib/mongoid/attributes.rb +2 -0
  7. data/lib/mongoid/contextual/aggregable/memory.rb +2 -2
  8. data/lib/mongoid/contextual/memory.rb +5 -5
  9. data/lib/mongoid/contextual/mongo.rb +13 -3
  10. data/lib/mongoid/criteria/#findable.rb# +141 -0
  11. data/lib/mongoid/document.rb +7 -7
  12. data/lib/mongoid/extensions.rb +13 -0
  13. data/lib/mongoid/findable.rb +27 -5
  14. data/lib/mongoid/persistable/creatable.rb +2 -1
  15. data/lib/mongoid/persistable/settable.rb +1 -1
  16. data/lib/mongoid/persistable/updatable.rb +2 -1
  17. data/lib/mongoid/query_cache.rb +10 -2
  18. data/lib/mongoid/railtie.rb +2 -15
  19. data/lib/mongoid/railties/database.rake +1 -1
  20. data/lib/mongoid/relations/accessors.rb +2 -2
  21. data/lib/mongoid/relations/binding.rb +1 -1
  22. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +1 -1
  23. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  24. data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
  25. data/lib/mongoid/relations/counter_cache.rb +2 -2
  26. data/lib/mongoid/relations/many.rb +21 -0
  27. data/lib/mongoid/relations/one.rb +1 -1
  28. data/lib/mongoid/relations/referenced/many.rb +4 -4
  29. data/lib/mongoid/relations/referenced/many_to_many.rb +5 -5
  30. data/lib/mongoid/relations/synchronization.rb +4 -4
  31. data/lib/mongoid/relations/targets/enumerable.rb +10 -10
  32. data/lib/mongoid/reloadable.rb +3 -3
  33. data/lib/mongoid/sessions/options.rb +7 -2
  34. data/lib/mongoid/threaded.rb +26 -15
  35. data/lib/mongoid/traversable.rb +6 -2
  36. data/lib/mongoid/validatable/uniqueness.rb +3 -3
  37. data/lib/mongoid/version.rb +1 -1
  38. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +33 -1
  39. data/spec/app/models/contextable_item.rb +5 -0
  40. data/spec/app/models/id_key.rb +6 -0
  41. data/spec/mongoid/#atomic_spec.rb# +365 -0
  42. data/spec/mongoid/attributes/nested_spec.rb +139 -144
  43. data/spec/mongoid/attributes_spec.rb +36 -0
  44. data/spec/mongoid/contextual/atomic_spec.rb +7 -13
  45. data/spec/mongoid/contextual/memory_spec.rb +7 -2
  46. data/spec/mongoid/criteria/modifiable_spec.rb +5 -8
  47. data/spec/mongoid/criteria_spec.rb +86 -75
  48. data/spec/mongoid/document_spec.rb +9 -5
  49. data/spec/mongoid/extensions_spec.rb +14 -0
  50. data/spec/mongoid/findable_spec.rb +99 -11
  51. data/spec/mongoid/persistable/creatable_spec.rb +41 -0
  52. data/spec/mongoid/persistable/savable_spec.rb +37 -0
  53. data/spec/mongoid/persistable/settable_spec.rb +23 -0
  54. data/spec/mongoid/positional_spec.rb +5 -10
  55. data/spec/mongoid/query_cache_spec.rb +32 -0
  56. data/spec/mongoid/relations/embedded/many_spec.rb +74 -0
  57. data/spec/mongoid/relations/referenced/many_spec.rb +153 -0
  58. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +49 -0
  59. data/spec/mongoid/reloadable_spec.rb +23 -0
  60. data/spec/mongoid/sessions/options_spec.rb +2 -1
  61. data/spec/mongoid/sessions_spec.rb +30 -0
  62. data/spec/spec_helper.rb +2 -0
  63. metadata +10 -3
@@ -0,0 +1,365 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Atomic do
4
+
5
+ describe "#add_atomic_pull" do
6
+
7
+ let!(:person) do
8
+ Person.create
9
+ end
10
+
11
+ let(:address) do
12
+ person.addresses.create
13
+ end
14
+
15
+ let(:location) do
16
+ address.locations.create
17
+ end
18
+
19
+ before do
20
+ person.add_atomic_pull(address)
21
+ end
22
+
23
+ it "adds the document to the delayed atomic pulls" do
24
+ expect(person.delayed_atomic_pulls["addresses"]).to eq([ address ])
25
+ end
26
+
27
+ it "flags the document for destruction" do
28
+ expect(address).to be_flagged_for_destroy
29
+ end
30
+ end
31
+
32
+ describe "#add_atomic_unset" do
33
+
34
+ let!(:person) do
35
+ Person.new
36
+ end
37
+
38
+ let(:name) do
39
+ person.build_name
40
+ end
41
+
42
+ before do
43
+ person.add_atomic_unset(name)
44
+ end
45
+
46
+ it "adds the document to the delayed atomic unsets" do
47
+ expect(person.delayed_atomic_unsets["name"]).to eq([ name ])
48
+ end
49
+
50
+ it "flags the document for destruction" do
51
+ expect(name).to be_flagged_for_destroy
52
+ end
53
+ end
54
+
55
+ describe "#atomic_updates" do
56
+
57
+ context "when the document is persisted" do
58
+
59
+ let(:person) do
60
+ Person.create
61
+ end
62
+
63
+ context "when the document is modified" do
64
+
65
+ before do
66
+ person.title = "Sir"
67
+ end
68
+
69
+ it "returns the atomic updates" do
70
+ expect(person.atomic_updates).to eq({ "$set" => { "title" => "Sir" }})
71
+ end
72
+
73
+ context "when an embeds many child is added" do
74
+
75
+ let!(:address) do
76
+ person.addresses.build(street: "Oxford St")
77
+ end
78
+
79
+ it "returns a $set and $pushAll for modifications" do
80
+ expect(person.atomic_updates).to eq(
81
+ {
82
+ "$set" => { "title" => "Sir" },
83
+ "$pushAll" => { "addresses" => [
84
+ { "_id" => "oxford-st", "street" => "Oxford St" }
85
+ ]}
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" => "Lionel-", "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
+ "$pushAll" => {
201
+ "addresses.0.locations" => [{ "_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
+ "$pushAll" => {
219
+ "addresses.0.locations" => [{ "_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
+ "$pushAll" => {
267
+ "addresses" => [{
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
+ "$pushAll" => {
314
+ "addresses" => [{
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 $pushAlls for all levels" do
343
+ expect(person.atomic_updates).to eq(
344
+ {
345
+ "$set" => {
346
+ "title" => "Sir",
347
+ },
348
+ "$pushAll" => {
349
+ "addresses" => [{
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