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
@@ -167,6 +167,28 @@ describe Mongoid::Contextual::Mongo do
167
167
  expect(count).to eq(2)
168
168
  end
169
169
  end
170
+
171
+ context 'when a collation is specified', if: collation_supported? do
172
+
173
+ let(:context) do
174
+ described_class.new(criteria)
175
+ end
176
+
177
+ context 'when the collation is specified on the criteria' do
178
+
179
+ let(:criteria) do
180
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
181
+ end
182
+
183
+ let(:count) do
184
+ context.count
185
+ end
186
+
187
+ it 'applies the collation' do
188
+ expect(count).to eq(1)
189
+ end
190
+ end
191
+ end
170
192
  end
171
193
 
172
194
  [ :delete, :delete_all ].each do |method|
@@ -208,7 +230,34 @@ describe Mongoid::Contextual::Mongo do
208
230
  end
209
231
  end
210
232
 
211
- context "when the selector is not contraining" do
233
+ context 'when the criteria has a collation', if: collation_supported? do
234
+
235
+ let(:criteria) do
236
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
237
+ end
238
+
239
+ let(:context) do
240
+ described_class.new(criteria)
241
+ end
242
+
243
+ let!(:deleted) do
244
+ context.send(method)
245
+ end
246
+
247
+ it "deletes the matching documents" do
248
+ expect(Band.find(new_order.id)).to eq(new_order)
249
+ end
250
+
251
+ it "deletes the correct number of documents" do
252
+ expect(Band.count).to eq(1)
253
+ end
254
+
255
+ it "returns the number of documents deleted" do
256
+ expect(deleted).to eq(1)
257
+ end
258
+ end
259
+
260
+ context "when the selector is not constraining" do
212
261
 
213
262
  let(:criteria) do
214
263
  Band.all
@@ -266,6 +315,33 @@ describe Mongoid::Contextual::Mongo do
266
315
  it "returns the number of documents destroyed" do
267
316
  expect(destroyed).to eq(1)
268
317
  end
318
+
319
+ context 'when the criteria has a collation', if: collation_supported? do
320
+
321
+ let(:criteria) do
322
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
323
+ end
324
+
325
+ let(:context) do
326
+ described_class.new(criteria)
327
+ end
328
+
329
+ let!(:destroyed) do
330
+ context.send(method)
331
+ end
332
+
333
+ it "destroys the matching documents" do
334
+ expect(Band.find(new_order.id)).to eq(new_order)
335
+ end
336
+
337
+ it "destroys the correct number of documents" do
338
+ expect(Band.count).to eq(1)
339
+ end
340
+
341
+ it "returns the number of documents destroyed" do
342
+ expect(destroyed).to eq(1)
343
+ end
344
+ end
269
345
  end
270
346
 
271
347
  context "when the selector is not contraining" do
@@ -340,6 +416,29 @@ describe Mongoid::Contextual::Mongo do
340
416
  expect(context.distinct(:years)).to eq([ 30, 25 ])
341
417
  end
342
418
  end
419
+
420
+ context 'when a collation is specified', if: collation_supported? do
421
+
422
+ before do
423
+ Band.create(name: 'DEPECHE MODE')
424
+ end
425
+
426
+ let(:context) do
427
+ described_class.new(criteria)
428
+ end
429
+
430
+ let(:expected_results) do
431
+ ["Depeche Mode", "New Order"]
432
+ end
433
+
434
+ let(:criteria) do
435
+ Band.where({}).collation(locale: 'en_US', strength: 2)
436
+ end
437
+
438
+ it 'applies the collation' do
439
+ expect(context.distinct(:name)).to eq(expected_results)
440
+ end
441
+ end
343
442
  end
344
443
 
345
444
  describe "#each" do
@@ -356,6 +455,29 @@ describe Mongoid::Contextual::Mongo do
356
455
  described_class.new(criteria)
357
456
  end
358
457
 
458
+ context 'when the criteria has a collation', if: collation_supported? do
459
+
460
+ let(:criteria) do
461
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
462
+ end
463
+
464
+ it "yields mongoid documents to the block" do
465
+ context.each do |doc|
466
+ expect(doc).to be_a(Mongoid::Document)
467
+ end
468
+ end
469
+
470
+ it "iterates over the matching documents" do
471
+ context.each do |doc|
472
+ expect(doc.name).to eq("Depeche Mode")
473
+ end
474
+ end
475
+
476
+ it "returns self" do
477
+ expect(context.each{}).to be(context)
478
+ end
479
+ end
480
+
359
481
  context "when providing a block" do
360
482
 
361
483
  it "yields mongoid documents to the block" do
@@ -398,9 +520,22 @@ describe Mongoid::Contextual::Mongo do
398
520
 
399
521
  context "when iterating with next" do
400
522
 
523
+ before do
524
+ 10.times { |i| Band.create(name: "Test #{i}") }
525
+ end
526
+
527
+ let(:criteria) do
528
+ Band.batch_size(5)
529
+ end
530
+
401
531
  it "yields mongoid documents" do
402
532
  expect(enum.next).to be_a(Mongoid::Document)
403
533
  end
534
+
535
+ it "does not load all documents" do
536
+ expect(Mongo::Logger.logger).to receive(:debug?).exactly(2).times.and_call_original
537
+ enum.next
538
+ end
404
539
  end
405
540
  end
406
541
  end
@@ -542,6 +677,161 @@ describe Mongoid::Contextual::Mongo do
542
677
  end
543
678
  end
544
679
 
680
+ describe "#find_one_and_replace" do
681
+
682
+ let!(:depeche) do
683
+ Band.create(name: "Depeche Mode")
684
+ end
685
+
686
+ let!(:tool) do
687
+ Band.create(name: "Tool")
688
+ end
689
+
690
+ context "when the selector matches" do
691
+
692
+ context "when not providing options" do
693
+
694
+ let(:criteria) do
695
+ Band.where(name: "Depeche Mode")
696
+ end
697
+
698
+ let(:context) do
699
+ described_class.new(criteria)
700
+ end
701
+
702
+ let!(:result) do
703
+ context.find_one_and_replace(name: 'FKA Twigs')
704
+ end
705
+
706
+ it "returns the first matching document" do
707
+ expect(result).to eq(depeche)
708
+ end
709
+
710
+ it "updates the document in the database" do
711
+ expect(depeche.reload.name).to eq('FKA Twigs')
712
+ end
713
+ end
714
+
715
+ context "when sorting" do
716
+
717
+ let(:criteria) do
718
+ Band.desc(:name)
719
+ end
720
+
721
+ let(:context) do
722
+ described_class.new(criteria)
723
+ end
724
+
725
+ let!(:result) do
726
+ context.find_one_and_replace(likes: 1)
727
+ end
728
+
729
+ it "returns the first matching document" do
730
+ expect(result).to eq(tool)
731
+ end
732
+
733
+ it "updates the document in the database" do
734
+ expect(tool.reload.likes).to eq(1)
735
+ expect(tool.reload.name).to be_nil
736
+ end
737
+ end
738
+
739
+ context "when limiting fields" do
740
+
741
+ let(:criteria) do
742
+ Band.only(:_id)
743
+ end
744
+
745
+ let(:context) do
746
+ described_class.new(criteria)
747
+ end
748
+
749
+ let!(:result) do
750
+ context.find_one_and_replace(name: 'FKA Twigs', likes: 1)
751
+ end
752
+
753
+ it "returns the first matching document" do
754
+ expect(result).to eq(depeche)
755
+ end
756
+
757
+ it "limits the returned fields" do
758
+ expect(result.name).to be_nil
759
+ end
760
+
761
+ it "updates the document in the database" do
762
+ expect(depeche.reload.likes).to eq(1)
763
+ end
764
+ end
765
+
766
+ context "when returning new" do
767
+
768
+ let(:criteria) do
769
+ Band.where(name: "Depeche Mode")
770
+ end
771
+
772
+ let(:context) do
773
+ described_class.new(criteria)
774
+ end
775
+
776
+ let!(:result) do
777
+ context.find_one_and_replace({ likes: 1 }, return_document: :after)
778
+ end
779
+
780
+ it "returns the first matching document" do
781
+ expect(result).to eq(depeche)
782
+ end
783
+
784
+ it "returns the updated document" do
785
+ expect(result.name).to be_nil
786
+ expect(result.likes).to eq(1)
787
+ end
788
+ end
789
+
790
+ context 'when a collation is specified on the criteria', if: collation_supported? do
791
+
792
+ let(:criteria) do
793
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
794
+ end
795
+
796
+ let(:context) do
797
+ described_class.new(criteria)
798
+ end
799
+
800
+ let!(:result) do
801
+ context.find_one_and_replace({ likes: 1 }, return_document: :after)
802
+ end
803
+
804
+ it "returns the first matching document" do
805
+ expect(result).to eq(depeche)
806
+ end
807
+
808
+ it "returns the updated document" do
809
+ expect(result.likes).to eq(1)
810
+ expect(result.name).to be_nil
811
+ end
812
+ end
813
+ end
814
+
815
+ context "when the selector does not match" do
816
+
817
+ let(:criteria) do
818
+ Band.where(name: "DEPECHE MODE")
819
+ end
820
+
821
+ let(:context) do
822
+ described_class.new(criteria)
823
+ end
824
+
825
+ let(:result) do
826
+ context.find_one_and_replace(name: 'FKA Twigs')
827
+ end
828
+
829
+ it "returns nil" do
830
+ expect(result).to be_nil
831
+ end
832
+ end
833
+ end
834
+
545
835
  describe "#find_one_and_update" do
546
836
 
547
837
  let!(:depeche) do
@@ -650,10 +940,84 @@ describe Mongoid::Contextual::Mongo do
650
940
  end
651
941
  end
652
942
 
653
- context "when removing" do
943
+ context 'when a collation is specified on the criteria', if: collation_supported? do
654
944
 
655
945
  let(:criteria) do
656
- Band.where(name: "Depeche Mode")
946
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
947
+ end
948
+
949
+ let(:context) do
950
+ described_class.new(criteria)
951
+ end
952
+
953
+ let!(:result) do
954
+ context.find_one_and_update({ "$inc" => { likes: 1 }}, return_document: :after)
955
+ end
956
+
957
+ it "returns the first matching document" do
958
+ expect(result).to eq(depeche)
959
+ end
960
+
961
+ it "returns the updated document" do
962
+ expect(result.likes).to eq(1)
963
+ end
964
+ end
965
+ end
966
+
967
+ context "when the selector does not match" do
968
+
969
+ let(:criteria) do
970
+ Band.where(name: "Placebo")
971
+ end
972
+
973
+ let(:context) do
974
+ described_class.new(criteria)
975
+ end
976
+
977
+ let(:result) do
978
+ context.find_one_and_update("$inc" => { likes: 1 })
979
+ end
980
+
981
+ it "returns nil" do
982
+ expect(result).to be_nil
983
+ end
984
+ end
985
+ end
986
+
987
+ describe "#find_one_and_delete" do
988
+
989
+ let!(:depeche) do
990
+ Band.create(name: "Depeche Mode")
991
+ end
992
+
993
+ let(:criteria) do
994
+ Band.where(name: "Depeche Mode")
995
+ end
996
+
997
+ let(:context) do
998
+ described_class.new(criteria)
999
+ end
1000
+
1001
+ let!(:result) do
1002
+ context.find_one_and_delete
1003
+ end
1004
+
1005
+ context 'when the selector matches a document' do
1006
+
1007
+ it "returns the first matching document" do
1008
+ expect(result).to eq(depeche)
1009
+ end
1010
+
1011
+ it "deletes the document from the database" do
1012
+ expect {
1013
+ depeche.reload
1014
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
1015
+ end
1016
+
1017
+ context 'when a collation is specified on the criteria', if: collation_supported? do
1018
+
1019
+ let(:criteria) do
1020
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
657
1021
  end
658
1022
 
659
1023
  let(:context) do
@@ -676,7 +1040,7 @@ describe Mongoid::Contextual::Mongo do
676
1040
  end
677
1041
  end
678
1042
 
679
- context "when the selector does not match" do
1043
+ context 'when the selector does not match a document' do
680
1044
 
681
1045
  let(:criteria) do
682
1046
  Band.where(name: "Placebo")
@@ -687,7 +1051,7 @@ describe Mongoid::Contextual::Mongo do
687
1051
  end
688
1052
 
689
1053
  let(:result) do
690
- context.find_one_and_update("$inc" => { likes: 1 })
1054
+ context.find_one_and_delete
691
1055
  end
692
1056
 
693
1057
  it "returns nil" do
@@ -721,6 +1085,17 @@ describe Mongoid::Contextual::Mongo do
721
1085
  it "returns the first matching document" do
722
1086
  expect(context.send(method)).to eq(depeche_mode)
723
1087
  end
1088
+
1089
+ context 'when the criteria has a collation', if: collation_supported? do
1090
+
1091
+ let(:criteria) do
1092
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
1093
+ end
1094
+
1095
+ it "returns the first matching document" do
1096
+ expect(context.send(method)).to eq(depeche_mode)
1097
+ end
1098
+ end
724
1099
  end
725
1100
 
726
1101
  context "when using .desc" do
@@ -1715,26 +2090,31 @@ describe Mongoid::Contextual::Mongo do
1715
2090
 
1716
2091
  describe '#pipeline' do
1717
2092
 
1718
- context 'when the criteria has a selector' do
2093
+ context 'when the criteria has a selector', if: non_legacy_server? do
2094
+
2095
+ before do
2096
+ Artist.index(name: "text")
2097
+ Artist.create_indexes
2098
+ end
1719
2099
 
1720
2100
  let(:criteria) do
1721
- Band.where(name: "New Order")
2101
+ Artist.text_search("New Order")
1722
2102
  end
1723
2103
 
1724
2104
  let(:context) do
1725
2105
  described_class.new(criteria)
1726
2106
  end
1727
2107
 
1728
- let(:matches_operators) do
1729
- context.send(:pipeline, 'name').select { |o| o['$match'] }
2108
+ let(:pipeline_match) do
2109
+ context.send(:pipeline, :some_field).first['$match']
1730
2110
  end
1731
2111
 
1732
2112
  it 'creates a pipeline with the selector as one of the $match criteria' do
1733
- expect(matches_operators).to include('$match' => criteria.selector)
2113
+ expect(pipeline_match).to include({ :'$text' => { :'$search' => "New Order" } })
1734
2114
  end
1735
2115
 
1736
2116
  it 'creates a pipeline with the $exists operator as one of the $match criteria' do
1737
- expect(matches_operators).to include('$match' => { 'name' => { '$exists' => true } })
2117
+ expect(pipeline_match).to include({ 'some_field' => { '$exists' => true } })
1738
2118
  end
1739
2119
  end
1740
2120
  end