mongoid 7.0.6 → 7.0.12

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 (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +1 -1
  5. data/Rakefile +14 -5
  6. data/lib/mongoid.rb +1 -1
  7. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  8. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  9. data/lib/mongoid/association/proxy.rb +1 -1
  10. data/lib/mongoid/atomic.rb +13 -3
  11. data/lib/mongoid/clients/sessions.rb +20 -4
  12. data/lib/mongoid/criteria.rb +7 -1
  13. data/lib/mongoid/criteria/modifiable.rb +2 -1
  14. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  15. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  16. data/lib/mongoid/criteria/queryable/extensions/time.rb +1 -1
  17. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  18. data/lib/mongoid/document.rb +3 -2
  19. data/lib/mongoid/extensions/hash.rb +4 -2
  20. data/lib/mongoid/extensions/regexp.rb +1 -1
  21. data/lib/mongoid/fields.rb +2 -1
  22. data/lib/mongoid/interceptable.rb +3 -1
  23. data/lib/mongoid/matchable/regexp.rb +2 -2
  24. data/lib/mongoid/persistable/pushable.rb +11 -2
  25. data/lib/mongoid/persistence_context.rb +6 -6
  26. data/lib/mongoid/query_cache.rb +61 -18
  27. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  28. data/lib/mongoid/version.rb +1 -1
  29. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  30. data/spec/app/models/customer.rb +11 -0
  31. data/spec/app/models/customer_address.rb +12 -0
  32. data/spec/app/models/delegating_patient.rb +16 -0
  33. data/spec/integration/app_spec.rb +192 -0
  34. data/spec/integration/associations/embedded_spec.rb +62 -0
  35. data/spec/integration/callbacks_models.rb +49 -0
  36. data/spec/integration/callbacks_spec.rb +216 -0
  37. data/spec/integration/criteria/date_field_spec.rb +41 -0
  38. data/spec/integration/document_spec.rb +22 -0
  39. data/spec/lite_spec_helper.rb +12 -4
  40. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  41. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  42. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  43. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  44. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  45. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +105 -0
  46. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  47. data/spec/mongoid/atomic/paths_spec.rb +41 -0
  48. data/spec/mongoid/clients/options_spec.rb +4 -4
  49. data/spec/mongoid/clients/sessions_spec.rb +8 -4
  50. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  51. data/spec/mongoid/clients_spec.rb +2 -2
  52. data/spec/mongoid/contextual/atomic_spec.rb +20 -10
  53. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  54. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  55. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  56. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  57. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  58. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  59. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  60. data/spec/mongoid/criteria_spec.rb +4 -2
  61. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  62. data/spec/mongoid/indexable_spec.rb +6 -4
  63. data/spec/mongoid/matchable/default_spec.rb +1 -1
  64. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  65. data/spec/mongoid/matchable_spec.rb +2 -2
  66. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  67. data/spec/mongoid/query_cache_spec.rb +77 -9
  68. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  69. data/spec/mongoid/scopable_spec.rb +2 -1
  70. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  71. data/spec/mongoid/tasks/database_spec.rb +1 -1
  72. data/spec/shared/LICENSE +20 -0
  73. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  74. data/spec/shared/lib/mrss/cluster_config.rb +211 -0
  75. data/spec/shared/lib/mrss/constraints.rb +330 -0
  76. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  77. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  78. data/spec/shared/lib/mrss/server_version_registry.rb +69 -0
  79. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  80. data/spec/shared/share/Dockerfile.erb +229 -0
  81. data/spec/shared/shlib/distro.sh +73 -0
  82. data/spec/shared/shlib/server.sh +270 -0
  83. data/spec/shared/shlib/set_env.sh +128 -0
  84. data/spec/spec_helper.rb +0 -31
  85. data/spec/support/child_process_helper.rb +76 -0
  86. data/spec/support/cluster_config.rb +3 -3
  87. data/spec/support/constraints.rb +201 -30
  88. data/spec/support/session_registry.rb +50 -0
  89. data/spec/support/spec_config.rb +12 -4
  90. metadata +510 -461
  91. metadata.gz.sig +2 -2
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe 'Queries on Date fields' do
7
+ let(:query) do
8
+ Band.where(founded: arg)
9
+ end
10
+
11
+ let(:selector) { query.selector }
12
+
13
+ shared_examples 'converts to beginning of day in UTC' do
14
+ it 'converts to beginning of day in UTC' do
15
+ selector['founded'].should == arg.dup.beginning_of_day.utc.beginning_of_day
16
+ end
17
+ end
18
+
19
+ context 'using Time' do
20
+ let(:arg) do
21
+ Time.now.freeze
22
+ end
23
+
24
+ it_behaves_like 'converts to beginning of day in UTC'
25
+ end
26
+
27
+ context 'using TimeWithZone' do
28
+ let(:time_zone_name) { 'Pacific Time (US & Canada)' }
29
+ let(:arg) { Time.now.in_time_zone(time_zone_name).freeze }
30
+
31
+ it_behaves_like 'converts to beginning of day in UTC'
32
+ end
33
+
34
+ context 'using DateTime' do
35
+ let(:arg) do
36
+ DateTime.now.freeze
37
+ end
38
+
39
+ it_behaves_like 'converts to beginning of day in UTC'
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Mongoid::Document do
7
+ context 'when including class uses delegate' do
8
+ let(:patient) do
9
+ DelegatingPatient.new(
10
+ email: Email.new(address: 'test@example.com'),
11
+ )
12
+ end
13
+
14
+ it 'works for instance level delegation' do
15
+ patient.address.should == 'test@example.com'
16
+ end
17
+
18
+ it 'works for class level delegation' do
19
+ DelegatingPatient.default_client.should be Mongoid.default_client
20
+ end
21
+ end
22
+ end
@@ -12,6 +12,7 @@ require "mongoid"
12
12
  require 'pp'
13
13
 
14
14
  require 'support/spec_config'
15
+ require "support/session_registry"
15
16
 
16
17
  unless SpecConfig.instance.ci?
17
18
  begin
@@ -44,11 +45,18 @@ RSpec.configure do |config|
44
45
  end
45
46
 
46
47
  if SpecConfig.instance.ci?
47
- # Allow a max of 30 seconds per test.
48
- # Tests should take under 10 seconds ideally but it seems
49
- # we have some that run for more than 10 seconds in CI.
48
+ timeout = if SpecConfig.instance.app_tests?
49
+ # Allow 5 minutes per test for the app tests, since they install
50
+ # gems for Rails applications which can take a long time.
51
+ 300
52
+ else
53
+ # Allow a max of 30 seconds per test.
54
+ # Tests should take under 10 seconds ideally but it seems
55
+ # we have some that run for more than 10 seconds in CI.
56
+ 30
57
+ end
50
58
  config.around(:each) do |example|
51
- TimeoutInterrupt.timeout(30) do
59
+ TimeoutInterrupt.timeout(timeout) do
52
60
  example.run
53
61
  end
54
62
  end
@@ -504,4 +504,54 @@ describe Mongoid::Association::Embedded::EmbeddedIn::Proxy do
504
504
  end
505
505
  end
506
506
  end
507
+
508
+ context "when the same class is embedded multiple times" do
509
+
510
+ let(:customer) do
511
+ Customer.new
512
+ end
513
+
514
+ context "assignment after saving" do
515
+
516
+ it "correctly sets the association for the embedded class" do
517
+ pending 'MONGOID-5039'
518
+
519
+ customer.home_address = CustomerAddress.new
520
+ customer.work_address = CustomerAddress.new
521
+
522
+ expect(customer.home_address._association.store_as).to eq("home_address")
523
+ expect(customer.work_address._association.store_as).to eq("work_address")
524
+
525
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
526
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
527
+
528
+ customer.save!
529
+
530
+ customer.home_address = CustomerAddress.new
531
+ customer.work_address = CustomerAddress.new
532
+
533
+ expect(customer.home_address._association.store_as).to eq("home_address")
534
+ expect(customer.work_address._association.store_as).to eq("work_address")
535
+
536
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
537
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
538
+ end
539
+ end
540
+
541
+ context "inverse assignment" do
542
+
543
+ it "correctly sets the association for the embedded class" do
544
+ pending 'MONGOID-5039'
545
+
546
+ customer.work_address = CustomerAddress.new
547
+ customer.work_address.addressable = customer
548
+
549
+ expect(customer.home_address._association.store_as).to eq("home_address")
550
+ expect(customer.work_address._association.store_as).to eq("work_address")
551
+
552
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
553
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
554
+ end
555
+ end
556
+ end
507
557
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ class EmmCongress
5
+ include Mongoid::Document
6
+
7
+ embeds_many :legislators, class_name: 'EmmLegislator'
8
+
9
+ field :name, type: String
10
+ end
11
+
12
+ class EmmLegislator
13
+ include Mongoid::Document
14
+
15
+ embedded_in :congress, class_name: 'EmmCongress'
16
+
17
+ field :a, type: Integer, default: 0
18
+ field :b, type: Integer, default: 0
19
+ end
20
+
21
+ # Models with associations with :class_name as a :: prefixed string
22
+
23
+ class EmmCcCongress
24
+ include Mongoid::Document
25
+
26
+ embeds_many :legislators, class_name: '::EmmCcLegislator'
27
+
28
+ field :name, type: String
29
+ end
30
+
31
+ class EmmCcLegislator
32
+ include Mongoid::Document
33
+
34
+ embedded_in :congress, class_name: '::EmmCcCongress'
35
+
36
+ field :a, type: Integer, default: 0
37
+ field :b, type: Integer, default: 0
38
+ end
39
+
40
+ class EmmManufactory
41
+ include Mongoid::Document
42
+
43
+ embeds_many :products, order: :id.desc, class_name: 'EmmProduct'
44
+ end
45
+
46
+
47
+ class EmmProduct
48
+ include Mongoid::Document
49
+
50
+ embedded_in :manufactory, class_name: 'EmmManufactory'
51
+
52
+ field :name, type: String
53
+ end
@@ -646,6 +646,16 @@ describe Mongoid::Association::Embedded::EmbedsMany do
646
646
  it 'returns the class name option' do
647
647
  expect(association.klass).to eq(_class)
648
648
  end
649
+
650
+ context 'when the class name is prefixed with ::' do
651
+ let(:options) do
652
+ { class_name: '::OtherEmbeddedObject' }
653
+ end
654
+
655
+ it 'returns the class name option' do
656
+ expect(association.klass).to eq(_class)
657
+ end
658
+ end
649
659
  end
650
660
 
651
661
  context 'when the class_name option is not specified' do
@@ -453,8 +453,6 @@ describe Mongoid::Association::Embedded::EmbedsOne do
453
453
  end
454
454
 
455
455
  it 'returns the inverse in an array' do
456
- pending 'MONGOID-4751'
457
-
458
456
  inverses = association.inverses
459
457
  expect(inverses).to eq([:parent])
460
458
  end
@@ -1754,6 +1754,43 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
1754
1754
  end
1755
1755
  end
1756
1756
 
1757
+ describe "#any?" do
1758
+
1759
+ let(:person) do
1760
+ Person.create
1761
+ end
1762
+
1763
+ context "when nothing exists on the relation" do
1764
+
1765
+ context "when no document is added" do
1766
+
1767
+ let!(:sandwich) do
1768
+ Sandwich.create!
1769
+ end
1770
+
1771
+ it "returns false" do
1772
+ expect(sandwich.meats.any?).to be false
1773
+ end
1774
+ end
1775
+
1776
+ context "when the document is destroyed" do
1777
+
1778
+ before do
1779
+ Meat.create!
1780
+ end
1781
+
1782
+ let!(:sandwich) do
1783
+ Sandwich.create!
1784
+ end
1785
+
1786
+ it "returns false" do
1787
+ sandwich.destroy
1788
+ expect(sandwich.meats.any?).to be false
1789
+ end
1790
+ end
1791
+ end
1792
+ end
1793
+
1757
1794
  context "when documents have been persisted" do
1758
1795
 
1759
1796
  let!(:preference) do
@@ -1843,6 +1880,107 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
1843
1880
  end
1844
1881
  end
1845
1882
 
1883
+ describe "#any?" do
1884
+
1885
+ let(:sandwich) do
1886
+ Sandwich.create
1887
+ end
1888
+
1889
+ context "when nothing exists on the relation" do
1890
+
1891
+ context "when no document is added" do
1892
+
1893
+ let!(:sandwich) do
1894
+ Sandwich.create!
1895
+ end
1896
+
1897
+ it "returns false" do
1898
+ expect(sandwich.meats.any?).to be false
1899
+ end
1900
+ end
1901
+
1902
+ context "when the document is destroyed" do
1903
+
1904
+ before do
1905
+ Meat.create!
1906
+ end
1907
+
1908
+ let!(:sandwich) do
1909
+ Sandwich.create!
1910
+ end
1911
+
1912
+ it "returns false" do
1913
+ sandwich.destroy
1914
+ expect(sandwich.meats.any?).to be false
1915
+ end
1916
+ end
1917
+ end
1918
+
1919
+ context "when appending to a relation and _loaded/_unloaded are empty" do
1920
+
1921
+ let!(:sandwich) do
1922
+ Sandwich.create!
1923
+ end
1924
+
1925
+ before do
1926
+ sandwich.meats << Meat.new
1927
+ end
1928
+
1929
+ it "returns true" do
1930
+ expect(sandwich.meats.any?).to be true
1931
+ end
1932
+ end
1933
+
1934
+ context "when appending to a relation in a transaction" do
1935
+ require_transaction_support
1936
+
1937
+ let!(:sandwich) do
1938
+ Sandwich.create!
1939
+ end
1940
+
1941
+ it "returns true" do
1942
+ sandwich.with_session do |session|
1943
+ session.with_transaction do
1944
+ expect{ sandwich.meats << Meat.new }.to_not raise_error
1945
+ expect(sandwich.meats.any?).to be true
1946
+ end
1947
+ end
1948
+ end
1949
+ end
1950
+
1951
+ context "when documents have been persisted" do
1952
+
1953
+ let!(:meat) do
1954
+ sandwich.meats.create
1955
+ end
1956
+
1957
+ it "returns true" do
1958
+ expect(sandwich.meats.any?).to be true
1959
+ end
1960
+ end
1961
+
1962
+ context "when documents have not been persisted" do
1963
+
1964
+ let!(:meat) do
1965
+ sandwich.meats.build
1966
+ end
1967
+
1968
+ it "returns false" do
1969
+ expect(sandwich.meats.any?).to be true
1970
+ end
1971
+ end
1972
+
1973
+ context "when new documents exist in the database" do
1974
+ before do
1975
+ Meat.create(sandwiches: [sandwich])
1976
+ end
1977
+
1978
+ it "returns true" do
1979
+ expect(sandwich.meats.any?).to be true
1980
+ end
1981
+ end
1982
+ end
1983
+
1846
1984
  [ :create, :create! ].each do |method|
1847
1985
 
1848
1986
  describe "##{method}" do
@@ -2686,7 +2824,8 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2686
2824
  expect(preferences).to eq([ preference_one ])
2687
2825
  end
2688
2826
 
2689
- context 'when providing a collation', if: collation_supported? do
2827
+ context 'when providing a collation' do
2828
+ min_server_version '3.4'
2690
2829
 
2691
2830
  let(:preferences) do
2692
2831
  person.preferences.where(name: "FIRST").collation(locale: 'en_US', strength: 2).to_a
@@ -253,6 +253,111 @@ describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
253
253
  end
254
254
  end
255
255
  end
256
+
257
+ context "when the documents have been loaded" do
258
+ let(:criteria) do
259
+ Post.where(person_id: person.id)
260
+ end
261
+
262
+ let!(:enumerable) do
263
+ described_class.new(criteria)
264
+ end
265
+
266
+ before do
267
+ enumerable.load_all!
268
+ end
269
+
270
+ it "is _loaded" do
271
+ expect(enumerable._loaded?).to be true
272
+ end
273
+
274
+ context "when a block is given" do
275
+ it "returns true when the predicate is true" do
276
+ expect(
277
+ enumerable.any? { |doc| true }
278
+ ).to be true
279
+ end
280
+
281
+ it "returns false when the predicate is false" do
282
+ expect(
283
+ enumerable.any? { |doc| false }
284
+ ).to be false
285
+ end
286
+ end
287
+
288
+ context "when an argument is given" do
289
+ ruby_version_gte '2.5'
290
+
291
+ it "returns true when the argument is true" do
292
+ expect(enumerable.any?(Post)).to be true
293
+ end
294
+
295
+ it "returns false when the argument is false" do
296
+ expect(enumerable.any?(Sandwich)).to be false
297
+ end
298
+ end
299
+
300
+ context "when both an argument and a block are given" do
301
+ ruby_version_gte '2.5'
302
+
303
+ it "gives precedence to the pattern" do
304
+ expect(
305
+ enumerable.any?(Post) { |doc| false }
306
+ ).to be true
307
+ end
308
+ end
309
+ end
310
+
311
+ context "when the documents are not loaded" do
312
+
313
+ let(:criteria) do
314
+ Post.where(person_id: person.id)
315
+ end
316
+
317
+ let!(:enumerable) do
318
+ described_class.new(criteria)
319
+ end
320
+
321
+ it "is not _loaded" do
322
+ expect(enumerable._loaded?).to be false
323
+ end
324
+
325
+ context "when a block is given" do
326
+ it "returns true when the predicate is true" do
327
+ expect(
328
+ enumerable.any? { |doc| true }
329
+ ).to be true
330
+ end
331
+
332
+ it "returns false when the predicate is false" do
333
+ expect(
334
+ enumerable.any? { |doc| false }
335
+ ).to be false
336
+ end
337
+ end
338
+
339
+ context "when an argument is given" do
340
+ ruby_version_gte '2.5'
341
+
342
+ it "returns true when the argument is true" do
343
+ expect(enumerable.any?(Post)).to be true
344
+ end
345
+
346
+ it "returns false when the argument is false" do
347
+ expect(enumerable.any?(Sandwich)).to be false
348
+ end
349
+ end
350
+
351
+ context "when both an argument and a block are given" do
352
+ ruby_version_gte '2.5'
353
+
354
+ it "gives precedence to the pattern" do
355
+ expect(
356
+ enumerable.any?(Post) { |doc| false }
357
+ ).to be true
358
+ end
359
+ end
360
+ end
256
361
  end
257
362
 
258
363
  describe "#clear" do