mongoid 7.0.12 → 7.0.13

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.
@@ -59,4 +59,118 @@ describe 'embedded associations' do
59
59
  end
60
60
  end
61
61
  end
62
+
63
+ context 'without default order' do
64
+ let(:congress) do
65
+ EmmCongress.create!
66
+ end
67
+
68
+ let(:legislator) do
69
+ EmmLegislator.create!(congress: congress, a: 1)
70
+ end
71
+
72
+ shared_examples_for 'an embedded association' do
73
+ it 'adds child documents to parent association object' do
74
+ legislator
75
+ congress.legislators._target.should == [legislator]
76
+ end
77
+
78
+ it 'adds child documents to parent association object criteria' do
79
+ legislator
80
+ congress.legislators.criteria.documents.should == [legislator]
81
+ end
82
+
83
+ it 'populates documents on parent association object' do
84
+ congress.legislators.documents.should == [legislator]
85
+ end
86
+
87
+ it 'returns created child when referencing embedded association' do
88
+ congress.legislators.should == [legislator]
89
+ end
90
+
91
+ it 'returns created child when referencing Criteria created from embedded association' do
92
+ congress.legislators.all.should be_a(Mongoid::Criteria)
93
+ congress.legislators.all.to_a.should == [legislator]
94
+ end
95
+ end
96
+
97
+ context 'when association was not previously referenced' do
98
+ before do
99
+ legislator
100
+ end
101
+
102
+ it_behaves_like 'an embedded association'
103
+ end
104
+
105
+ context 'when association was previously referenced' do
106
+ before do
107
+ # This query must be before the product is created
108
+ congress.legislators.where(a: 1).first
109
+
110
+ legislator
111
+ end
112
+
113
+ it_behaves_like 'an embedded association'
114
+ end
115
+ end
116
+
117
+ context 'with default order' do
118
+ let(:manufactory) do
119
+ EmmManufactory.create!
120
+ end
121
+
122
+ let(:product) do
123
+ EmmProduct.create!(manufactory: manufactory, name: 'Car')
124
+ end
125
+
126
+ shared_examples_for 'adds child documents to parent association' do
127
+ it 'adds child documents to parent association' do
128
+ manufactory.products._target.should == [product]
129
+ end
130
+ end
131
+
132
+ shared_examples_for 'an embedded association' do
133
+ it 'adds child documents to parent association object' do
134
+ product
135
+ manufactory.products._target.should == [product]
136
+ end
137
+
138
+ it 'adds child documents to parent association object criteria' do
139
+ product
140
+ manufactory.products.criteria.documents.should == [product]
141
+ end
142
+
143
+ it 'populates documents on parent association object' do
144
+ manufactory.products.documents.should == [product]
145
+ end
146
+
147
+ it 'returns created child when referencing embedded association' do
148
+ manufactory.products.should == [product]
149
+ end
150
+
151
+ it 'returns created child when referencing Criteria created from embedded association' do
152
+ manufactory.products.all.should be_a(Mongoid::Criteria)
153
+ manufactory.products.all.to_a.should == [product]
154
+ end
155
+ end
156
+
157
+ context 'when association is not loaded' do
158
+ before do
159
+ product
160
+ end
161
+
162
+ it_behaves_like 'an embedded association'
163
+ end
164
+
165
+ context 'when association is loaded' do
166
+ before do
167
+ # This query must be before the product is created
168
+ manufactory.products.where(name: "Car").first
169
+
170
+ product
171
+ end
172
+
173
+ it_behaves_like 'an embedded association'
174
+ end
175
+ end
62
176
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "shared", "lib"))
5
6
 
6
7
  require "mongoid"
7
8
 
@@ -12,6 +13,7 @@ require "mongoid"
12
13
  require 'pp'
13
14
 
14
15
  require 'support/spec_config'
16
+ require 'mrss/lite_constraints'
15
17
  require "support/session_registry"
16
18
 
17
19
  unless SpecConfig.instance.ci?
@@ -44,7 +46,7 @@ RSpec.configure do |config|
44
46
  config.add_formatter(RSpec::Core::Formatters::JsonFormatter, File.join(File.dirname(__FILE__), '../tmp/rspec.json'))
45
47
  end
46
48
 
47
- if SpecConfig.instance.ci?
49
+ if SpecConfig.instance.ci? && !%w(1 true yes).include?(ENV['INTERACTIVE']&.downcase)
48
50
  timeout = if SpecConfig.instance.app_tests?
49
51
  # Allow 5 minutes per test for the app tests, since they install
50
52
  # gems for Rails applications which can take a long time.
@@ -61,6 +63,8 @@ RSpec.configure do |config|
61
63
  end
62
64
  end
63
65
  end
66
+
67
+ config.extend(Mrss::LiteConstraints)
64
68
  end
65
69
 
66
70
  # require all shared examples
@@ -242,6 +242,97 @@ describe Mongoid::Attributes do
242
242
  end
243
243
  end
244
244
 
245
+ context "when the field was not explicitly defined" do
246
+
247
+ context "when excluding with only and the field was not excluded" do
248
+
249
+ let(:from_db) do
250
+ Person.only(:_id).first
251
+ end
252
+
253
+ it "raises an error" do
254
+ expect {
255
+ from_db[:undefined_field]
256
+ }.to raise_error(ActiveModel::MissingAttributeError)
257
+ end
258
+ end
259
+
260
+ context "when excluding with without and the field was excluded" do
261
+
262
+ let(:from_db) do
263
+ Person.without(:title).first
264
+ end
265
+
266
+ it "raises an error" do
267
+ expect {
268
+ from_db[:title]
269
+ }.to raise_error(ActiveModel::MissingAttributeError)
270
+ end
271
+ end
272
+
273
+ context "when excluding with without and the field was not excluded" do
274
+
275
+ let(:from_db) do
276
+ Person.without(:title).first
277
+ end
278
+
279
+ it "returns nil" do
280
+ from_db[:undefined_field].should be nil
281
+ end
282
+ end
283
+ end
284
+
285
+ context 'when projecting with #only' do
286
+ let!(:person) do
287
+ Person.create(title: 'sir', name: { first_name: 'Jose', language: { name: 'es' } })
288
+ end
289
+
290
+ context 'when projecting an embedded association' do
291
+ let(:from_db) do
292
+ Person.only(:name).first
293
+ end
294
+
295
+ context 'when retrieving a field of the association using the dot notation' do
296
+
297
+ it 'retrieves the field' do
298
+ pending 'MONGOID-5032, fixed in 7.3'
299
+
300
+ expect(from_db['name.first_name']).to eq 'Jose'
301
+ end
302
+ end
303
+
304
+ context 'when retrieving a field of a nested association using the dot notation' do
305
+ it 'retrieves the field' do
306
+ pending 'MONGOID-5032, fixed in 7.3'
307
+
308
+ expect(from_db['name.language.name']).to eq 'es'
309
+ end
310
+ end
311
+ end
312
+
313
+ context 'when projecting a sub-association of an embedded association' do
314
+ let(:from_db) do
315
+ Person.only('name.language').first
316
+ end
317
+
318
+ context 'when retrieving a field under the projected sub-association' do
319
+ it 'retrieves the field' do
320
+ pending 'MONGOID-5032, fixed in 7.3'
321
+
322
+ expect(from_db['name.language.name']).to eq 'es'
323
+ end
324
+ end
325
+
326
+ context 'when retrieving a non-projected field' do
327
+ it 'raises MissingAttributeError' do
328
+ expect do
329
+ from_db['name.first_name']
330
+ end.to raise_error(ActiveModel::MissingAttributeError)
331
+ end
332
+ end
333
+ end
334
+ end
335
+
245
336
  context "when the attribute does not exist" do
246
337
 
247
338
  before do
@@ -326,6 +417,67 @@ describe Mongoid::Attributes do
326
417
  expect(terms).to eq(true)
327
418
  end
328
419
  end
420
+
421
+ context 'when the field is not explicitly defined' do
422
+ let(:bar) { Bar.new }
423
+
424
+ before do
425
+ bar['missing_field'] = 42
426
+ end
427
+
428
+ it 'writes the value into attributes' do
429
+ bar.attributes.should == {'_id' => bar.id, 'missing_field' => 42}
430
+ end
431
+
432
+ it 'makes the attribute accessible via []' do
433
+ bar['missing_field'].should == 42
434
+ end
435
+
436
+ context 'when writing fields on a document with projection' do
437
+
438
+ let!(:person) do
439
+ Person.create(title: "sir")
440
+ end
441
+
442
+ context "when excluding with only and the field was not excluded" do
443
+
444
+ let(:from_db) do
445
+ Person.only(:_id).first
446
+ end
447
+
448
+ it "raises an error" do
449
+ expect {
450
+ from_db[:undefined_field] = 'x'
451
+ }.to raise_error(ActiveModel::MissingAttributeError)
452
+ end
453
+ end
454
+
455
+ context "when excluding with without and the field was excluded" do
456
+
457
+ let(:from_db) do
458
+ Person.without(:title).first
459
+ end
460
+
461
+ it "raises an error" do
462
+ expect {
463
+ from_db[:title] = 'x'
464
+ }.to raise_error(ActiveModel::MissingAttributeError)
465
+ end
466
+ end
467
+
468
+ context "when excluding with without and the field was not excluded" do
469
+
470
+ let(:from_db) do
471
+ Person.without(:title).first
472
+ end
473
+
474
+ it "writes the value" do
475
+ from_db[:undefined_field] = 'x'
476
+ from_db[:undefined_field].should == 'x'
477
+ end
478
+ end
479
+ end
480
+ end
329
481
  end
330
482
 
331
483
  describe "#_id" do
@@ -890,6 +1042,50 @@ describe Mongoid::Attributes do
890
1042
  expect(person.age_before_type_cast).to eq("old")
891
1043
  end
892
1044
  end
1045
+
1046
+ context 'when reading fields on a document with projection' do
1047
+
1048
+ let!(:person) do
1049
+ Person.create(title: "sir")
1050
+ end
1051
+
1052
+ context "when excluding with only and the field was not excluded" do
1053
+
1054
+ let(:from_db) do
1055
+ Person.only(:_id).first
1056
+ end
1057
+
1058
+ it "raises an error" do
1059
+ expect {
1060
+ from_db.read_attribute(:undefined_field)
1061
+ }.to raise_error(ActiveModel::MissingAttributeError)
1062
+ end
1063
+ end
1064
+
1065
+ context "when excluding with without and the field was excluded" do
1066
+
1067
+ let(:from_db) do
1068
+ Person.without(:title).first
1069
+ end
1070
+
1071
+ it "raises an error" do
1072
+ expect {
1073
+ from_db.read_attribute(:title)
1074
+ }.to raise_error(ActiveModel::MissingAttributeError)
1075
+ end
1076
+ end
1077
+
1078
+ context "when excluding with without and the field was not excluded" do
1079
+
1080
+ let(:from_db) do
1081
+ Person.without(:title).first
1082
+ end
1083
+
1084
+ it "returns nil" do
1085
+ from_db.read_attribute(:undefined_field).should be nil
1086
+ end
1087
+ end
1088
+ end
893
1089
  end
894
1090
 
895
1091
  describe "#attribute_present?" do
@@ -1395,6 +1591,51 @@ describe Mongoid::Attributes do
1395
1591
  expect(dictionary.description).to eq('foo')
1396
1592
  end
1397
1593
  end
1594
+
1595
+ context 'when writing fields on a document with projection' do
1596
+
1597
+ let!(:person) do
1598
+ Person.create(title: "sir")
1599
+ end
1600
+
1601
+ context "when excluding with only and the field was not excluded" do
1602
+
1603
+ let(:from_db) do
1604
+ Person.only(:_id).first
1605
+ end
1606
+
1607
+ it "raises an error" do
1608
+ expect {
1609
+ from_db.write_attribute(:undefined_field, 'x')
1610
+ }.to raise_error(ActiveModel::MissingAttributeError)
1611
+ end
1612
+ end
1613
+
1614
+ context "when excluding with without and the field was excluded" do
1615
+
1616
+ let(:from_db) do
1617
+ Person.without(:title).first
1618
+ end
1619
+
1620
+ it "raises an error" do
1621
+ expect {
1622
+ from_db.write_attribute(:title, 'x')
1623
+ }.to raise_error(ActiveModel::MissingAttributeError)
1624
+ end
1625
+ end
1626
+
1627
+ context "when excluding with without and the field was not excluded" do
1628
+
1629
+ let(:from_db) do
1630
+ Person.without(:title).first
1631
+ end
1632
+
1633
+ it "writes the value" do
1634
+ from_db.write_attribute(:undefined_field, 'x')
1635
+ from_db.read_attribute(:undefined_field).should == 'x'
1636
+ end
1637
+ end
1638
+ end
1398
1639
  end
1399
1640
 
1400
1641
  describe "#typed_value_for" do
@@ -653,12 +653,25 @@ describe Mongoid::Contextual::Atomic do
653
653
  context.set(name: "Recoil")
654
654
  end
655
655
 
656
- it "sets existing fields" do
657
- expect(depeche_mode.reload.name).to eq("Recoil")
656
+ shared_examples 'writes as expected' do
657
+ it "sets existing fields" do
658
+ expect(depeche_mode.reload.name).to eq("Recoil")
659
+ end
660
+
661
+ it "sets non existent fields" do
662
+ expect(smiths.reload.name).to eq("Recoil")
663
+ end
658
664
  end
659
665
 
660
- it "sets non existent fields" do
661
- expect(smiths.reload.name).to eq("Recoil")
666
+ include_examples 'writes as expected'
667
+
668
+ context 'when fields being set have been projected out' do
669
+
670
+ let(:criteria) do
671
+ Band.only(:genres)
672
+ end
673
+
674
+ include_examples 'writes as expected'
662
675
  end
663
676
  end
664
677