mongoid 5.1.5 → 5.2.0

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 (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +15 -0
  5. data/lib/mongoid.rb +5 -0
  6. data/lib/mongoid/attributes/dynamic.rb +3 -3
  7. data/lib/mongoid/clients/factory.rb +2 -0
  8. data/lib/mongoid/config.rb +1 -0
  9. data/lib/mongoid/config/options.rb +1 -1
  10. data/lib/mongoid/contextual/aggregable/mongo.rb +0 -1
  11. data/lib/mongoid/contextual/map_reduce.rb +20 -97
  12. data/lib/mongoid/contextual/memory.rb +1 -0
  13. data/lib/mongoid/contextual/mongo.rb +20 -15
  14. data/lib/mongoid/criteria.rb +2 -0
  15. data/lib/mongoid/document.rb +1 -0
  16. data/lib/mongoid/errors.rb +1 -0
  17. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +20 -0
  18. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  19. data/lib/mongoid/extensions.rb +1 -0
  20. data/lib/mongoid/extensions/decimal128.rb +39 -0
  21. data/lib/mongoid/fields/localized.rb +8 -3
  22. data/lib/mongoid/indexable/validators/options.rb +2 -1
  23. data/lib/mongoid/persistable/deletable.rb +3 -7
  24. data/lib/mongoid/persistable/settable.rb +3 -1
  25. data/lib/mongoid/query_cache.rb +24 -2
  26. data/lib/mongoid/relations/accessors.rb +1 -1
  27. data/lib/mongoid/relations/builders.rb +2 -2
  28. data/lib/mongoid/relations/eager.rb +2 -2
  29. data/lib/mongoid/relations/reflections.rb +5 -3
  30. data/lib/mongoid/relations/touchable.rb +1 -1
  31. data/lib/mongoid/scopable.rb +1 -1
  32. data/lib/mongoid/version.rb +1 -1
  33. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +6 -2
  34. data/spec/app/models/band.rb +1 -0
  35. data/spec/config/mongoid.yml +5 -0
  36. data/spec/mongoid/clients/factory_spec.rb +8 -0
  37. data/spec/mongoid/clients_spec.rb +78 -1
  38. data/spec/mongoid/config_spec.rb +31 -0
  39. data/spec/mongoid/contextual/atomic_spec.rb +342 -76
  40. data/spec/mongoid/contextual/map_reduce_spec.rb +111 -119
  41. data/spec/mongoid/contextual/memory_spec.rb +316 -56
  42. data/spec/mongoid/contextual/mongo_spec.rb +391 -11
  43. data/spec/mongoid/criteria_spec.rb +21 -2
  44. data/spec/mongoid/extensions/decimal128_spec.rb +44 -0
  45. data/spec/mongoid/extensions/time_spec.rb +2 -2
  46. data/spec/mongoid/fields/localized_spec.rb +91 -0
  47. data/spec/mongoid/indexable_spec.rb +44 -0
  48. data/spec/mongoid/persistable/settable_spec.rb +44 -0
  49. data/spec/mongoid/query_cache_spec.rb +86 -0
  50. data/spec/mongoid/relations/cyclic_spec.rb +22 -0
  51. data/spec/mongoid/relations/referenced/many_spec.rb +11 -0
  52. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +11 -0
  53. data/spec/mongoid/relations/reflections_spec.rb +9 -9
  54. data/spec/mongoid/scopable_spec.rb +12 -0
  55. data/spec/spec_helper.rb +9 -0
  56. metadata +26 -16
  57. metadata.gz.sig +0 -0
@@ -3078,14 +3078,14 @@ describe Mongoid::Criteria do
3078
3078
  context "when not including private methods" do
3079
3079
 
3080
3080
  it "returns false" do
3081
- expect(criteria).to_not respond_to(:fork)
3081
+ expect(criteria).to_not respond_to(:initialize_copy)
3082
3082
  end
3083
3083
  end
3084
3084
 
3085
3085
  context "when including private methods" do
3086
3086
 
3087
3087
  it "returns true" do
3088
- expect(criteria.respond_to?(:fork, true)).to be true
3088
+ expect(criteria.respond_to?(:initialize_copy, true)).to be true
3089
3089
  end
3090
3090
  end
3091
3091
  end
@@ -3352,6 +3352,25 @@ describe Mongoid::Criteria do
3352
3352
  end
3353
3353
  end
3354
3354
 
3355
+ context "when querying on a BSON::Decimal128", if: decimal128_supported? do
3356
+
3357
+ let(:decimal) do
3358
+ BSON::Decimal128.new("0.0005")
3359
+ end
3360
+
3361
+ let!(:band) do
3362
+ Band.create(name: "Boards of Canada", decimal: decimal)
3363
+ end
3364
+
3365
+ let(:from_db) do
3366
+ Band.where(decimal: decimal).first
3367
+ end
3368
+
3369
+ it "finds the document by the big decimal value" do
3370
+ expect(from_db).to eq(band)
3371
+ end
3372
+ end
3373
+
3355
3374
  context 'when querying on a polymorphic relation' do
3356
3375
 
3357
3376
  let(:movie) do
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Extensions::Decimal128 do
4
+
5
+ let(:decimal128) do
6
+ BSON::Decimal128.new("0.0005")
7
+ end
8
+
9
+ describe "#__evolve_decimal128__" do
10
+
11
+ it "returns the same instance" do
12
+ expect(decimal128.__evolve_decimal128__).to be(decimal128)
13
+ end
14
+ end
15
+
16
+ describe ".evolve" do
17
+
18
+ context "when provided a single decimal128" do
19
+
20
+ let(:evolved) do
21
+ BSON::Decimal128.evolve(decimal128)
22
+ end
23
+
24
+ it "returns the decimal128" do
25
+ expect(evolved).to be(decimal128)
26
+ end
27
+ end
28
+
29
+ context "when provided an array of decimal128s" do
30
+
31
+ let(:other_decimal128) do
32
+ BSON::Decimal128.new("3.14")
33
+ end
34
+
35
+ let(:evolved) do
36
+ BSON::ObjectId.evolve([decimal128, other_decimal128])
37
+ end
38
+
39
+ it "returns the array of decimal128s" do
40
+ expect(evolved).to eq([decimal128, other_decimal128])
41
+ end
42
+ end
43
+ end
44
+ end
@@ -281,7 +281,7 @@ describe Mongoid::Extensions::Time do
281
281
  end
282
282
 
283
283
  it "does not alter seconds with fractions" do
284
- expect(DateTime.mongoize(11.11).to_f).to eq(11.11)
284
+ expect(DateTime.mongoize(1.11).to_f).to eq(1.11)
285
285
  end
286
286
 
287
287
  context "when using the ActiveSupport time zone" do
@@ -344,7 +344,7 @@ describe Mongoid::Extensions::Time do
344
344
  end
345
345
 
346
346
  it "does not alter seconds with fractions" do
347
- expect(Time.mongoize(102.63).to_f).to eq(102.63)
347
+ expect(Time.mongoize(102.25).to_f).to eq(102.25)
348
348
  end
349
349
  end
350
350
 
@@ -430,6 +430,97 @@ describe Mongoid::Fields::Localized do
430
430
  expect(value).to eq({ "de" => 100 })
431
431
  end
432
432
  end
433
+
434
+ context 'when the type is Boolean' do
435
+
436
+ before do
437
+ I18n.enforce_available_locales = false
438
+ ::I18n.locale = :de
439
+ end
440
+
441
+ after do
442
+ ::I18n.locale = :en
443
+ end
444
+
445
+ context "when the value is false" do
446
+
447
+ let(:field) do
448
+ described_class.new(:boolean_value, localize: true, type: Boolean)
449
+ end
450
+
451
+ let(:value) do
452
+ field.demongoize({ "de" => false })
453
+ end
454
+
455
+ it "returns the boolean value from the set locale" do
456
+ expect(value).to eq(false)
457
+ end
458
+ end
459
+
460
+ context "when the value is true" do
461
+
462
+ let(:field) do
463
+ described_class.new(:boolean_value, localize: true, type: Boolean)
464
+ end
465
+
466
+ let(:value) do
467
+ field.demongoize({"de" => true})
468
+ end
469
+
470
+ it "returns the boolean value from the set locale" do
471
+ expect(value).to eq(true)
472
+ end
473
+ end
474
+
475
+ context "when fallbacks are defined" do
476
+
477
+ before(:all) do
478
+ require "i18n/backend/fallbacks"
479
+ I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
480
+ end
481
+
482
+ context "when the lookup does not need to use fallbacks" do
483
+
484
+ context "when the value is false" do
485
+
486
+ before do
487
+ ::I18n.fallbacks[:de] = [:en, :es]
488
+ end
489
+
490
+ let(:field) do
491
+ described_class.new(:boolean_value, localize: true, type: Boolean)
492
+ end
493
+
494
+ let(:value) do
495
+ field.demongoize({"de" => false})
496
+ end
497
+
498
+ it "returns the boolean value from the set locale" do
499
+ expect(value).to eq(false)
500
+ end
501
+ end
502
+
503
+ context "when the value is true" do
504
+
505
+ before do
506
+ ::I18n.fallbacks[:de] = [:en, :es]
507
+ end
508
+
509
+ let(:field) do
510
+ described_class.new(:boolean_value, localize: true, type: Boolean)
511
+ end
512
+
513
+ let(:value) do
514
+ field.demongoize({"de" => true})
515
+ end
516
+
517
+ it "returns the boolean value from the set locale" do
518
+ expect(value).to eq(true)
519
+ end
520
+ end
521
+ end
522
+ end
523
+ end
433
524
  end
434
525
  end
435
526
  end
@@ -114,6 +114,34 @@ describe Mongoid::Indexable do
114
114
  expect(indexes.get(_type: 1)).to_not be_nil
115
115
  end
116
116
  end
117
+
118
+ context "when a collation option is specified", if: collation_supported? do
119
+
120
+ let(:klass) do
121
+ Class.new do
122
+ include Mongoid::Document
123
+ store_in collection: "test_db_indexes"
124
+ index({name: 1}, {collation: {locale: 'en_US', strength: 2}})
125
+ end
126
+ end
127
+
128
+ before do
129
+ klass.create_indexes
130
+ end
131
+
132
+ after do
133
+ klass.remove_indexes
134
+ end
135
+
136
+ let(:indexes) do
137
+ klass.collection.indexes
138
+ end
139
+
140
+ it "creates the indexes" do
141
+ expect(indexes.get("name_1")["collation"]).to_not be_nil
142
+ expect(indexes.get("name_1")["collation"]["locale"]).to eq('en_US')
143
+ end
144
+ end
117
145
  end
118
146
 
119
147
  describe ".add_indexes" do
@@ -149,6 +177,7 @@ describe Mongoid::Indexable do
149
177
  Class.new do
150
178
  include Mongoid::Document
151
179
  field :a, as: :authentication_token
180
+ store_in collection: :specs
152
181
  end
153
182
  end
154
183
 
@@ -257,6 +286,21 @@ describe Mongoid::Indexable do
257
286
  end
258
287
  end
259
288
 
289
+ context "when providing a collation option", if: collation_supported? do
290
+
291
+ before do
292
+ klass.index({ name: 1 }, collation: { locale: 'en_US', strength: 2 })
293
+ end
294
+
295
+ let(:options) do
296
+ klass.index_specification(name: 1).options
297
+ end
298
+
299
+ it "sets the index with a collation option" do
300
+ expect(options).to eq(collation: { locale: 'en_US', strength: 2 })
301
+ end
302
+ end
303
+
260
304
  context "when providing a compound index" do
261
305
 
262
306
  before do
@@ -263,6 +263,50 @@ describe Mongoid::Persistable::Settable do
263
263
  end
264
264
  end
265
265
 
266
+ context 'when the field is a nested hash' do
267
+
268
+ context 'when a leaf value in the nested hash is updated' do
269
+
270
+ let(:church) do
271
+ Church.new.tap do |a|
272
+ a.location = {'address' => {'city' => 'Berlin', 'street' => 'Yorckstr'}}
273
+ a.name = 'Church1'
274
+ a.save
275
+ end
276
+ end
277
+
278
+ before do
279
+ church.set('location.address.city' => 'Munich')
280
+ end
281
+
282
+ it 'does not reset the nested hash' do
283
+ expect(church.name).to eq('Church1')
284
+ expect(church.location).to eql({'address' => {'city' => 'Munich', 'street' => 'Yorckstr'}})
285
+ end
286
+ end
287
+
288
+
289
+ context 'when the nested hash is many levels deep' do
290
+
291
+ let(:church) do
292
+ Church.new.tap do |a|
293
+ a.location = {'address' => {'state' => {'address' => {'city' => 'Berlin', 'street' => 'Yorckstr'}}}}
294
+ a.name = 'Church1'
295
+ a.save
296
+ end
297
+ end
298
+
299
+ before do
300
+ church.set('location.address.state.address.city' => 'Munich')
301
+ end
302
+
303
+ it 'does not reset the nested hash' do
304
+ expect(church.name).to eq('Church1')
305
+ expect(church.location).to eql({'address' => {'state' => {'address' => {'city' => 'Munich', 'street' => 'Yorckstr'}}}})
306
+ end
307
+ end
308
+ end
309
+
266
310
  context 'when the field is not already set locally' do
267
311
 
268
312
  let(:church) do
@@ -75,6 +75,40 @@ describe Mongoid::QueryCache do
75
75
  end
76
76
  end
77
77
 
78
+ context 'when the first query has a collation', if: collation_supported? do
79
+
80
+ before do
81
+ Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
82
+ end
83
+
84
+ context "when the next query has the same collation" do
85
+
86
+ it "uses the cache" do
87
+ expect_no_queries do
88
+ Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
89
+ end
90
+ end
91
+ end
92
+
93
+ context "when the next query does not have the same collation" do
94
+
95
+ it "queries again" do
96
+ expect_query(1) do
97
+ Band.where(name: 'DEPECHE MODE').collation(locale: 'fr', strength: 2).to_a
98
+ end
99
+ end
100
+ end
101
+
102
+ context "when the next query does not have a collation" do
103
+
104
+ it "queries again" do
105
+ expect_query(1) do
106
+ Band.where(name: 'DEPECHE MODE').to_a
107
+ end
108
+ end
109
+ end
110
+ end
111
+
78
112
  context "when the first query has no limit" do
79
113
 
80
114
  let(:game) do
@@ -173,6 +207,27 @@ describe Mongoid::QueryCache do
173
207
  end
174
208
  end
175
209
 
210
+ context "when sorting documents" do
211
+ before do
212
+ Band.asc(:id).to_a
213
+ end
214
+
215
+ context "with different selector" do
216
+
217
+ it "queries again" do
218
+ expect_query(1) do
219
+ Band.desc(:id).to_a
220
+ end
221
+ end
222
+ end
223
+
224
+ it "does not query again" do
225
+ expect_query(0) do
226
+ Band.asc(:id).to_a
227
+ end
228
+ end
229
+ end
230
+
176
231
  context "when query caching is enabled and the batch_size is set" do
177
232
 
178
233
  around(:each) do |example|
@@ -250,6 +305,37 @@ describe Mongoid::QueryCache do
250
305
  end
251
306
  end
252
307
 
308
+ context "when reloading a document" do
309
+
310
+ let!(:band_id) do
311
+ Band.create.id
312
+ end
313
+
314
+ context 'when query cache is disabled' do
315
+
316
+ before do
317
+ Mongoid::QueryCache.enabled = false
318
+ end
319
+
320
+ it "queries again" do
321
+ band = Band.find(band_id)
322
+ expect_query(1) do
323
+ band.reload
324
+ end
325
+ end
326
+ end
327
+
328
+ context 'when query cache is enabled' do
329
+
330
+ it "queries again" do
331
+ band = Band.find(band_id)
332
+ expect_query(1) do
333
+ band.reload
334
+ end
335
+ end
336
+ end
337
+ end
338
+
253
339
  context "when querying a very large collection" do
254
340
 
255
341
  before do
@@ -21,6 +21,17 @@ describe Mongoid::Relations::Cyclic do
21
21
  it "sets cyclic to true" do
22
22
  expect(document.cyclic).to be true
23
23
  end
24
+
25
+ context "when a query is executed" do
26
+
27
+ before do
28
+ document.save
29
+ end
30
+
31
+ it "queries the database, not memory" do
32
+ expect(Role.first).to be_a(Role)
33
+ end
34
+ end
24
35
  end
25
36
 
26
37
  context "when the name is not inflected easily" do
@@ -133,6 +144,17 @@ describe Mongoid::Relations::Cyclic do
133
144
  expect(document.class.relations['child_mango']).to be_cascading_callbacks
134
145
  end
135
146
  end
147
+
148
+ context "when a query is executed" do
149
+
150
+ before do
151
+ document.save
152
+ end
153
+
154
+ it "queries the database, not memory" do
155
+ expect(Shelf.first).to be_a(Shelf)
156
+ end
157
+ end
136
158
  end
137
159
 
138
160
  context "when building a namespaced hierarchy" do