mongoid 7.0.6 → 7.0.12

Sign up to get free protection for your applications and to get access to all the features.
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