mongoid 7.0.0.beta → 7.0.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 (86) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +21 -0
  5. data/lib/mongoid.rb +1 -1
  6. data/lib/mongoid/association/embedded/batchable.rb +39 -13
  7. data/lib/mongoid/association/many.rb +4 -0
  8. data/lib/mongoid/association/referenced/has_many.rb +2 -0
  9. data/lib/mongoid/association/referenced/has_many/enumerable.rb +38 -7
  10. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -2
  11. data/lib/mongoid/association/referenced/syncable.rb +1 -1
  12. data/lib/mongoid/association/touchable.rb +1 -1
  13. data/lib/mongoid/atomic.rb +3 -3
  14. data/lib/mongoid/atomic/modifiers.rb +12 -8
  15. data/lib/mongoid/attributes.rb +20 -12
  16. data/lib/mongoid/attributes/dynamic.rb +2 -2
  17. data/lib/mongoid/changeable.rb +1 -1
  18. data/lib/mongoid/clients.rb +2 -0
  19. data/lib/mongoid/clients/sessions.rb +113 -0
  20. data/lib/mongoid/clients/storage_options.rb +1 -0
  21. data/lib/mongoid/composable.rb +1 -0
  22. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  23. data/lib/mongoid/contextual/atomic.rb +6 -3
  24. data/lib/mongoid/contextual/geo_near.rb +1 -1
  25. data/lib/mongoid/contextual/map_reduce.rb +6 -2
  26. data/lib/mongoid/contextual/memory.rb +25 -2
  27. data/lib/mongoid/contextual/mongo.rb +33 -14
  28. data/lib/mongoid/copyable.rb +2 -2
  29. data/lib/mongoid/criteria.rb +1 -0
  30. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
  31. data/lib/mongoid/criteria/queryable/mergeable.rb +3 -1
  32. data/lib/mongoid/errors.rb +1 -0
  33. data/lib/mongoid/errors/invalid_session_use.rb +24 -0
  34. data/lib/mongoid/extensions.rb +0 -4
  35. data/lib/mongoid/extensions/hash.rb +5 -2
  36. data/lib/mongoid/factory.rb +14 -5
  37. data/lib/mongoid/fields.rb +2 -2
  38. data/lib/mongoid/indexable.rb +4 -4
  39. data/lib/mongoid/matchable/and.rb +1 -1
  40. data/lib/mongoid/matchable/elem_match.rb +9 -3
  41. data/lib/mongoid/persistable.rb +2 -2
  42. data/lib/mongoid/persistable/creatable.rb +4 -2
  43. data/lib/mongoid/persistable/deletable.rb +4 -2
  44. data/lib/mongoid/persistable/destroyable.rb +1 -5
  45. data/lib/mongoid/persistable/updatable.rb +2 -2
  46. data/lib/mongoid/persistable/upsertable.rb +2 -1
  47. data/lib/mongoid/persistence_context.rb +5 -4
  48. data/lib/mongoid/query_cache.rb +5 -3
  49. data/lib/mongoid/reloadable.rb +1 -1
  50. data/lib/mongoid/serializable.rb +1 -1
  51. data/lib/mongoid/shardable.rb +1 -1
  52. data/lib/mongoid/tasks/database.rb +3 -2
  53. data/lib/mongoid/threaded.rb +38 -0
  54. data/lib/mongoid/traversable.rb +1 -1
  55. data/lib/mongoid/version.rb +1 -1
  56. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -0
  57. data/spec/app/models/band.rb +1 -0
  58. data/spec/app/models/shipment_address.rb +1 -0
  59. data/spec/mongoid/association/macros_spec.rb +20 -0
  60. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +15 -0
  61. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +229 -0
  62. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  63. data/spec/mongoid/atomic_spec.rb +17 -17
  64. data/spec/mongoid/attributes_spec.rb +38 -2
  65. data/spec/mongoid/clients/sessions_spec.rb +325 -0
  66. data/spec/mongoid/contextual/memory_spec.rb +19 -0
  67. data/spec/mongoid/contextual/mongo_spec.rb +133 -0
  68. data/spec/mongoid/copyable_spec.rb +34 -0
  69. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +43 -0
  70. data/spec/mongoid/criteria/queryable/selectable_spec.rb +32 -3
  71. data/spec/mongoid/extensions/hash_spec.rb +18 -1
  72. data/spec/mongoid/factory_spec.rb +11 -0
  73. data/spec/mongoid/interceptable_spec.rb +3 -1
  74. data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
  75. data/spec/mongoid/persistable/deletable_spec.rb +19 -0
  76. data/spec/mongoid/persistable/destroyable_spec.rb +19 -0
  77. data/spec/mongoid/persistable/savable_spec.rb +2 -2
  78. data/spec/mongoid/persistable/updatable_spec.rb +2 -2
  79. data/spec/mongoid/persistable_spec.rb +31 -16
  80. data/spec/mongoid/persistence_context_spec.rb +14 -0
  81. data/spec/mongoid/positional_spec.rb +10 -10
  82. data/spec/mongoid/query_cache_spec.rb +2 -16
  83. data/spec/mongoid/shardable_spec.rb +32 -12
  84. data/spec/spec_helper.rb +74 -0
  85. metadata +456 -446
  86. metadata.gz.sig +0 -0
@@ -20,6 +20,7 @@ class Band
20
20
 
21
21
  embeds_many :records, cascade_callbacks: true
22
22
  embeds_many :notes, as: :noteable, cascade_callbacks: true, validate: false
23
+ embeds_many :labels
23
24
  embeds_one :label, cascade_callbacks: true
24
25
 
25
26
  has_many :same_name, class_name: 'Agent', inverse_of: :same_name
@@ -1,2 +1,3 @@
1
1
  class ShipmentAddress < Address
2
+ field :shipping_name, localize: true
2
3
  end
@@ -20,6 +20,26 @@ describe Mongoid::Association::Macros do
20
20
  klass.validators.clear
21
21
  end
22
22
 
23
+ describe 'Model loading' do
24
+
25
+ let(:model_associations) do
26
+ class TestModel
27
+ include Mongoid::Document
28
+ field :associations
29
+ end
30
+ end
31
+
32
+ after do
33
+ Object.send(:remove_const, :TestModel)
34
+ end
35
+
36
+ it 'prohibits the use of :associations as an attribute' do
37
+ expect {
38
+ model_associations
39
+ }.to raise_exception(Mongoid::Errors::InvalidField)
40
+ end
41
+ end
42
+
23
43
  describe ".embedded_in" do
24
44
 
25
45
  it "defines the macro" do
@@ -91,6 +91,15 @@ describe Mongoid::Association::Referenced::HasMany::Eager do
91
91
  end
92
92
  end
93
93
  end
94
+
95
+ it "does not query when accessing the base on each document" do
96
+ persons = Person.all.includes(:drugs).to_a
97
+ expect_query(0) do
98
+ persons.each do |person|
99
+ person.drugs.collect(&:person)
100
+ end
101
+ end
102
+ end
94
103
  end
95
104
 
96
105
  context "when the relation is not polymorphic" do
@@ -120,6 +129,12 @@ describe Mongoid::Association::Referenced::HasMany::Eager do
120
129
  eager.posts.first.title = "New title"
121
130
  end
122
131
  end
132
+
133
+ it "does not query when accessing the base on each document" do
134
+ expect_query(0) do
135
+ eager.posts.collect(&:person)
136
+ end
137
+ end
123
138
  end
124
139
 
125
140
  context "when the eager load has not returned documents" do
@@ -189,6 +189,12 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
189
189
  it "returns the added documents" do
190
190
  expect(added).to eq([ post ])
191
191
  end
192
+
193
+ it "sets the base on the new document" do
194
+ expect_query(0) do
195
+ added.collect(&:person)
196
+ end
197
+ end
192
198
  end
193
199
  end
194
200
 
@@ -622,6 +628,22 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
622
628
  it "becomes loaded" do
623
629
  expect(enumerable).to be__loaded
624
630
  end
631
+
632
+ context 'when the base relation is accessed from each document' do
633
+
634
+ let(:persons) do
635
+ described_class.new(criteria).collect(&:person)
636
+ end
637
+
638
+ before do
639
+ Post.create(person_id: person.id)
640
+ Post.create(person_id: person.id)
641
+ end
642
+
643
+ it 'sets the base relation from the criteria' do
644
+ expect(persons.uniq.size).to eq(1)
645
+ end
646
+ end
625
647
  end
626
648
 
627
649
  context "when only an array target exists" do
@@ -928,6 +950,60 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
928
950
  end
929
951
  end
930
952
  end
953
+
954
+ context 'when the id_sort option is none' do
955
+
956
+ let(:person) do
957
+ Person.create
958
+ end
959
+
960
+ let(:criteria) do
961
+ Post.where(person_id: person.id)
962
+ end
963
+
964
+ let(:enumerable) do
965
+ described_class.new(criteria)
966
+ end
967
+
968
+ let!(:first_post) do
969
+ person.posts.create(title: "One")
970
+ end
971
+
972
+ let!(:second_post) do
973
+ person.posts.create(title: "Two")
974
+ end
975
+
976
+ it 'does not use the sort on id' do
977
+ expect(enumerable.first(id_sort: :none)).to eq(first_post)
978
+ end
979
+ end
980
+
981
+ context 'when the id_sort option is not provided' do
982
+
983
+ let(:person) do
984
+ Person.create
985
+ end
986
+
987
+ let(:criteria) do
988
+ Post.where(person_id: person.id)
989
+ end
990
+
991
+ let(:enumerable) do
992
+ described_class.new(criteria)
993
+ end
994
+
995
+ let!(:first_post) do
996
+ person.posts.create(title: "One")
997
+ end
998
+
999
+ let!(:second_post) do
1000
+ person.posts.create(title: "Two")
1001
+ end
1002
+
1003
+ it 'uses the sort on id' do
1004
+ expect(enumerable.first).to eq(first_post)
1005
+ end
1006
+ end
931
1007
  end
932
1008
 
933
1009
  describe "#include?" do
@@ -1344,6 +1420,60 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
1344
1420
  end
1345
1421
  end
1346
1422
  end
1423
+
1424
+ context 'when the id_sort option is none' do
1425
+
1426
+ let(:person) do
1427
+ Person.create
1428
+ end
1429
+
1430
+ let(:criteria) do
1431
+ Post.where(person_id: person.id)
1432
+ end
1433
+
1434
+ let(:enumerable) do
1435
+ described_class.new(criteria)
1436
+ end
1437
+
1438
+ let!(:first_post) do
1439
+ person.posts.create(title: "One")
1440
+ end
1441
+
1442
+ let!(:second_post) do
1443
+ person.posts.create(title: "Two")
1444
+ end
1445
+
1446
+ it 'does not use the sort on id' do
1447
+ expect(enumerable.last(id_sort: :none)).to eq(first_post)
1448
+ end
1449
+ end
1450
+
1451
+ context 'when the id_sort option is not provided' do
1452
+
1453
+ let(:person) do
1454
+ Person.create
1455
+ end
1456
+
1457
+ let(:criteria) do
1458
+ Post.where(person_id: person.id)
1459
+ end
1460
+
1461
+ let(:enumerable) do
1462
+ described_class.new(criteria)
1463
+ end
1464
+
1465
+ let!(:first_post) do
1466
+ person.posts.create(title: "One")
1467
+ end
1468
+
1469
+ let!(:second_post) do
1470
+ person.posts.create(title: "Two")
1471
+ end
1472
+
1473
+ it 'uses the sort on id' do
1474
+ expect(enumerable.last).to eq(second_post)
1475
+ end
1476
+ end
1347
1477
  end
1348
1478
 
1349
1479
  describe "#kind_of?" do
@@ -1714,4 +1844,103 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
1714
1844
  expect(enumerable).to be__loaded
1715
1845
  end
1716
1846
  end
1847
+
1848
+ describe 'setting the same parent object on enumerated children objects' do
1849
+
1850
+ let(:person) do
1851
+ Person.create
1852
+ end
1853
+
1854
+ context 'when a single child is fetched' do
1855
+
1856
+ let!(:post) do
1857
+ person.posts << Post.new
1858
+ person.posts.first
1859
+ end
1860
+
1861
+ it 'does not query the database to access the parent' do
1862
+ expect_query(0) do
1863
+ expect(post.person).to eq(person)
1864
+ end
1865
+ end
1866
+ end
1867
+
1868
+ context 'when a single child is fetched with a scope' do
1869
+
1870
+ let!(:post) do
1871
+ person.posts << Post.new(title: 'open')
1872
+ person.posts.open.first
1873
+ end
1874
+
1875
+ it 'does not query the database to access the parent' do
1876
+ expect_query(0) do
1877
+ expect(post.person).to eq(person)
1878
+ end
1879
+ end
1880
+ end
1881
+
1882
+ context 'when multiple children are fetched' do
1883
+
1884
+ let!(:posts) do
1885
+ person.posts << Post.new
1886
+ person.posts << Post.new
1887
+ person.posts << Post.new
1888
+ person.posts.to_a
1889
+ end
1890
+
1891
+ it 'does not query the database to access the parent' do
1892
+ expect_query(0) do
1893
+ expect(posts.all? { |post| post.person == person }).to be(true)
1894
+ end
1895
+ end
1896
+ end
1897
+
1898
+ context 'when multiple children are fetched with query criteria' do
1899
+
1900
+ let!(:posts) do
1901
+ person.posts << Post.new(title: 'open')
1902
+ person.posts << Post.new(title: 'open')
1903
+ person.posts << Post.new(title: 'not-a-test')
1904
+ person.posts.where(title: 'open').to_a
1905
+ end
1906
+
1907
+ it 'does not query the database to access the parent' do
1908
+ expect_query(0) do
1909
+ expect(posts.all? { |post| post.person == person }).to be(true)
1910
+ end
1911
+ end
1912
+ end
1913
+
1914
+ context 'when multiple children are fetched with a scope' do
1915
+
1916
+ let!(:posts) do
1917
+ person.posts << Post.new(title: 'open')
1918
+ person.posts << Post.new(title: 'open')
1919
+ person.posts << Post.new(title: 'not-a-test')
1920
+ person.posts.open.to_a
1921
+ end
1922
+
1923
+ it 'does not query the database to access the parent' do
1924
+ expect_query(0) do
1925
+ expect(posts.all? { |post| post.person == person }).to be(true)
1926
+ end
1927
+ end
1928
+ end
1929
+
1930
+ context 'when the parent is updated in memory' do
1931
+
1932
+ let!(:posts) do
1933
+ person.posts << Post.new
1934
+ person.posts << Post.new
1935
+ person.username = 'emily'
1936
+ person.posts.to_a
1937
+ end
1938
+
1939
+ it 'does not query the database to access the parent' do
1940
+ expect_query(0) do
1941
+ expect(posts.all? { |post| post.person.username == 'emily' }).to be(true)
1942
+ end
1943
+ end
1944
+ end
1945
+ end
1717
1946
  end
@@ -211,10 +211,10 @@ describe Mongoid::Atomic::Modifiers do
211
211
 
212
212
  it "adds the push all modifiers" do
213
213
  expect(modifiers).to eq(
214
- { "$pushAll" =>
215
- { "addresses" => [
214
+ { "$push" =>
215
+ { "addresses" => { '$each' => [
216
216
  { "street" => "Oxford St" }
217
- ]
217
+ ] }
218
218
  }
219
219
  }
220
220
  )
@@ -238,11 +238,11 @@ describe Mongoid::Atomic::Modifiers do
238
238
 
239
239
  it "adds the push all modifiers" do
240
240
  expect(modifiers).to eq(
241
- { "$pushAll" =>
242
- { "addresses" => [
241
+ { "$push" =>
242
+ { "addresses" => { '$each' => [
243
243
  { "street" => "Hobrechtstr." },
244
244
  { "street" => "Pflugerstr." }
245
- ]
245
+ ] }
246
246
  }
247
247
  }
248
248
  )
@@ -270,10 +270,10 @@ describe Mongoid::Atomic::Modifiers do
270
270
  it "adds the push all modifiers to the conflicts hash" do
271
271
  expect(modifiers).to eq(
272
272
  { "$set" => { "addresses.0.street" => "Bond" },
273
- conflicts: { "$pushAll" =>
274
- { "addresses" => [
273
+ conflicts: { "$push" =>
274
+ { "addresses" => { '$each' => [
275
275
  { "street" => "Oxford St" }
276
- ]
276
+ ] }
277
277
  }
278
278
  }
279
279
  }
@@ -300,10 +300,10 @@ describe Mongoid::Atomic::Modifiers do
300
300
  expect(modifiers).to eq(
301
301
  { "$pullAll" => {
302
302
  "addresses" => { "street" => "Bond St" }},
303
- conflicts: { "$pushAll" =>
304
- { "addresses" => [
303
+ conflicts: { "$push" =>
304
+ { "addresses" => { '$each' => [
305
305
  { "street" => "Oxford St" }
306
- ]
306
+ ]}
307
307
  }
308
308
  }
309
309
  }
@@ -328,12 +328,12 @@ describe Mongoid::Atomic::Modifiers do
328
328
 
329
329
  it "adds the push all modifiers to the conflicts hash" do
330
330
  expect(modifiers).to eq(
331
- { "$pushAll" => {
332
- "addresses.0.locations" => [{ "street" => "Bond St" }]},
333
- conflicts: { "$pushAll" =>
334
- { "addresses" => [
331
+ { "$push" => {
332
+ "addresses.0.locations" => { '$each' => [{ "street" => "Bond St" }] } },
333
+ conflicts: { "$push" =>
334
+ { "addresses" => { '$each' => [
335
335
  { "street" => "Oxford St" }
336
- ]
336
+ ] }
337
337
  }
338
338
  }
339
339
  }
@@ -76,13 +76,13 @@ describe Mongoid::Atomic do
76
76
  person.addresses.build(street: "Oxford St")
77
77
  end
78
78
 
79
- it "returns a $set and $pushAll for modifications" do
79
+ it "returns a $set and $push with $each for modifications" do
80
80
  expect(person.atomic_updates).to eq(
81
81
  {
82
82
  "$set" => { "title" => "Sir" },
83
- "$pushAll" => { "addresses" => [
83
+ "$push" => { "addresses" => { "$each" => [
84
84
  { "_id" => "oxford-st", "street" => "Oxford St" }
85
- ]}
85
+ ] } }
86
86
  }
87
87
  )
88
88
  end
@@ -197,8 +197,8 @@ describe Mongoid::Atomic do
197
197
  "addresses.0.street" => "Bond St"
198
198
  },
199
199
  conflicts: {
200
- "$pushAll" => {
201
- "addresses.0.locations" => [{ "_id" => location.id, "name" => "Home" }]
200
+ "$push" => {
201
+ "addresses.0.locations" => { '$each' => [{ "_id" => location.id, "name" => "Home" }] }
202
202
  }
203
203
  }
204
204
  }
@@ -215,8 +215,8 @@ describe Mongoid::Atomic do
215
215
  "addresses.0.street" => "Bond St"
216
216
  },
217
217
  conflicts: {
218
- "$pushAll" => {
219
- "addresses.0.locations" => [{ "_id" => location.id, "name" => "Home" }]
218
+ "$push" => {
219
+ "addresses.0.locations" => { '$each' => [{ "_id" => location.id, "name" => "Home" }] }
220
220
  }
221
221
  }
222
222
  }
@@ -263,15 +263,15 @@ describe Mongoid::Atomic do
263
263
  "addresses.0.street" => "Bond St"
264
264
  },
265
265
  conflicts: {
266
- "$pushAll" => {
267
- "addresses" => [{
266
+ "$push" => {
267
+ "addresses" => { '$each' => [{
268
268
  "_id" => new_address.id,
269
269
  "street" => "Another",
270
270
  "locations" => [
271
271
  "_id" => location.id,
272
272
  "name" => "Home"
273
273
  ]
274
- }]
274
+ }]}
275
275
  }
276
276
  }
277
277
  }
@@ -310,15 +310,15 @@ describe Mongoid::Atomic do
310
310
  "$set" => {
311
311
  "title" => "Sir"
312
312
  },
313
- "$pushAll" => {
314
- "addresses" => [{
313
+ "$push" => {
314
+ "addresses" => { '$each' => [{
315
315
  "_id" => new_address.id,
316
316
  "street" => "Ipanema",
317
317
  "locations" => [
318
318
  "_id" => location.id,
319
319
  "name" => "Home"
320
320
  ]
321
- }]
321
+ }] }
322
322
  },
323
323
  conflicts: {
324
324
  "$set" => { "addresses.0.street"=>"Bond St" }
@@ -339,21 +339,21 @@ describe Mongoid::Atomic do
339
339
  address.locations.build(name: "Home")
340
340
  end
341
341
 
342
- it "returns the proper $sets and $pushAlls for all levels" do
342
+ it "returns the proper $sets and $pushes for all levels" do
343
343
  expect(person.atomic_updates).to eq(
344
344
  {
345
345
  "$set" => {
346
346
  "title" => "Sir",
347
347
  },
348
- "$pushAll" => {
349
- "addresses" => [{
348
+ "$push" => {
349
+ "addresses" => { '$each' => [{
350
350
  "_id" => address.id,
351
351
  "street" => "Another",
352
352
  "locations" => [
353
353
  "_id" => location.id,
354
354
  "name" => "Home"
355
355
  ]
356
- }]
356
+ }] }
357
357
  }
358
358
  }
359
359
  )