mongoid 7.0.12 → 7.0.13

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