mongoid 7.0.4 → 7.0.10

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 (100) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +1 -0
  5. data/README.md +3 -2
  6. data/Rakefile +26 -0
  7. data/lib/mongoid.rb +2 -1
  8. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  9. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  10. data/lib/mongoid/association/proxy.rb +1 -1
  11. data/lib/mongoid/atomic.rb +13 -3
  12. data/lib/mongoid/atomic/paths/embedded.rb +1 -1
  13. data/lib/mongoid/attributes.rb +28 -20
  14. data/lib/mongoid/attributes/dynamic.rb +15 -14
  15. data/lib/mongoid/clients/sessions.rb +20 -4
  16. data/lib/mongoid/config/environment.rb +21 -8
  17. data/lib/mongoid/criteria.rb +7 -1
  18. data/lib/mongoid/criteria/modifiable.rb +13 -2
  19. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  20. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  21. data/lib/mongoid/criteria/queryable/extensions/time.rb +1 -1
  22. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  23. data/lib/mongoid/criteria/queryable/key.rb +67 -8
  24. data/lib/mongoid/criteria/queryable/mergeable.rb +5 -4
  25. data/lib/mongoid/criteria/queryable/selectable.rb +3 -4
  26. data/lib/mongoid/criteria/queryable/selector.rb +9 -31
  27. data/lib/mongoid/extensions/hash.rb +4 -2
  28. data/lib/mongoid/extensions/regexp.rb +1 -1
  29. data/lib/mongoid/extensions/string.rb +2 -2
  30. data/lib/mongoid/fields.rb +2 -1
  31. data/lib/mongoid/matchable.rb +14 -15
  32. data/lib/mongoid/matchable/all.rb +4 -3
  33. data/lib/mongoid/matchable/default.rb +71 -24
  34. data/lib/mongoid/matchable/regexp.rb +2 -2
  35. data/lib/mongoid/persistable/pushable.rb +11 -2
  36. data/lib/mongoid/persistence_context.rb +6 -6
  37. data/lib/mongoid/positional.rb +1 -1
  38. data/lib/mongoid/query_cache.rb +24 -11
  39. data/lib/mongoid/validatable/macros.rb +1 -1
  40. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  41. data/lib/mongoid/version.rb +2 -1
  42. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  43. data/spec/README.md +18 -0
  44. data/spec/app/models/delegating_patient.rb +16 -0
  45. data/spec/integration/app_spec.rb +192 -0
  46. data/spec/integration/associations/embedded_spec.rb +62 -0
  47. data/spec/integration/criteria/date_field_spec.rb +41 -0
  48. data/spec/integration/criteria/time_with_zone_spec.rb +32 -0
  49. data/spec/integration/document_spec.rb +22 -0
  50. data/spec/integration/matchable_spec.rb +680 -0
  51. data/spec/lite_spec_helper.rb +15 -5
  52. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  53. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  54. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  55. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  56. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +105 -0
  57. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  58. data/spec/mongoid/attributes/dynamic_spec.rb +153 -0
  59. data/spec/mongoid/attributes_spec.rb +19 -7
  60. data/spec/mongoid/clients/factory_spec.rb +2 -2
  61. data/spec/mongoid/clients/options_spec.rb +4 -4
  62. data/spec/mongoid/clients/sessions_spec.rb +20 -7
  63. data/spec/mongoid/clients/transactions_spec.rb +36 -15
  64. data/spec/mongoid/clients_spec.rb +2 -2
  65. data/spec/mongoid/contextual/atomic_spec.rb +20 -10
  66. data/spec/mongoid/contextual/geo_near_spec.rb +12 -2
  67. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  68. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  69. data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
  70. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
  71. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  72. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  73. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  74. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  75. data/spec/mongoid/criteria/queryable/key_spec.rb +48 -6
  76. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +762 -0
  77. data/spec/mongoid/criteria/queryable/selectable_spec.rb +5 -224
  78. data/spec/mongoid/criteria/queryable/selector_spec.rb +37 -0
  79. data/spec/mongoid/criteria_spec.rb +7 -2
  80. data/spec/mongoid/document_fields_spec.rb +88 -0
  81. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  82. data/spec/mongoid/indexable_spec.rb +6 -4
  83. data/spec/mongoid/matchable/default_spec.rb +10 -3
  84. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  85. data/spec/mongoid/matchable_spec.rb +2 -2
  86. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  87. data/spec/mongoid/query_cache_spec.rb +62 -8
  88. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  89. data/spec/mongoid/scopable_spec.rb +2 -1
  90. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  91. data/spec/mongoid/tasks/database_spec.rb +1 -1
  92. data/spec/mongoid/validatable/uniqueness_spec.rb +33 -6
  93. data/spec/spec_helper.rb +4 -37
  94. data/spec/support/child_process_helper.rb +76 -0
  95. data/spec/support/cluster_config.rb +158 -0
  96. data/spec/support/constraints.rb +201 -30
  97. data/spec/support/expectations.rb +17 -3
  98. data/spec/support/spec_config.rb +12 -4
  99. metadata +490 -454
  100. metadata.gz.sig +0 -0
@@ -45,7 +45,7 @@ describe Mongoid::Indexable do
45
45
  end
46
46
  end
47
47
 
48
- context "when database specific options exist", if: non_legacy_server? do
48
+ context "when database specific options exist" do
49
49
 
50
50
  let(:klass) do
51
51
  Class.new do
@@ -95,7 +95,7 @@ describe Mongoid::Indexable do
95
95
  end
96
96
  end
97
97
 
98
- context "when database options are specified", if: non_legacy_server? do
98
+ context "when database options are specified" do
99
99
 
100
100
  let(:klass) do
101
101
  Class.new do
@@ -133,7 +133,8 @@ describe Mongoid::Indexable do
133
133
  end
134
134
  end
135
135
 
136
- context "when a collation option is specified", if: collation_supported? do
136
+ context "when a collation option is specified" do
137
+ min_server_version '3.4'
137
138
 
138
139
  let(:klass) do
139
140
  Class.new do
@@ -308,7 +309,8 @@ describe Mongoid::Indexable do
308
309
  end
309
310
  end
310
311
 
311
- context "when providing a collation option", if: collation_supported? do
312
+ context "when providing a collation option" do
313
+ min_server_version '3.4'
312
314
 
313
315
  before do
314
316
  klass.index({ name: 1 }, collation: { locale: 'en_US', strength: 2 })
@@ -68,7 +68,7 @@ describe Mongoid::Matchable::Default do
68
68
  context "when the value is a regexp" do
69
69
 
70
70
  it "returns true" do
71
- expect(matcher._matches?(/^Test[3-5]$/)).to be true
71
+ expect(matcher._matches?(/\ATest[3-5]\z/)).to be true
72
72
  end
73
73
  end
74
74
  end
@@ -112,14 +112,21 @@ describe Mongoid::Matchable::Default do
112
112
  described_class.new(["Test1", "Test2", "Test3"])
113
113
  end
114
114
 
115
- context "when the attribute contains the value" do
115
+ context "when the attribute equals the value" do
116
116
 
117
117
  it "returns true" do
118
118
  expect(matcher._matches?(["Test1", "Test2", "Test3"])).to be true
119
119
  end
120
120
  end
121
121
 
122
- context "when the attribute does not contain the value" do
122
+ context "when the value contains same items as attribute but in different order" do
123
+
124
+ it "returns false" do
125
+ expect(matcher._matches?(["Test1", "Test3", "Test2"])).to be false
126
+ end
127
+ end
128
+
129
+ context "when the value is a subset of attribute" do
123
130
 
124
131
  it "returns false" do
125
132
  expect(matcher._matches?(["Test1", "Test2"])).to be false
@@ -15,7 +15,7 @@ describe Mongoid::Matchable::Regexp do
15
15
  context 'when a BSON::Regexp::Raw object is passed' do
16
16
 
17
17
  let(:regexp) do
18
- BSON::Regexp::Raw.new('^Em')
18
+ BSON::Regexp::Raw.new("\\AEm")
19
19
  end
20
20
 
21
21
  it 'compiles the regexp object to a native regexp for the matching' do
@@ -37,7 +37,7 @@ describe Mongoid::Matchable::Regexp do
37
37
  context 'when a native Regexp object is passed' do
38
38
 
39
39
  let(:regexp) do
40
- /^Em/
40
+ /\AEm/
41
41
  end
42
42
 
43
43
  it 'calls super with the native regexp' do
@@ -293,7 +293,7 @@ describe Mongoid::Matchable do
293
293
  context 'when a BSON::Regexp::Raw object is used' do
294
294
 
295
295
  let(:selector) do
296
- { street: BSON::Regexp::Raw.new("^Clarkenwell") }
296
+ { street: BSON::Regexp::Raw.new("\\AClarkenwell") }
297
297
  end
298
298
 
299
299
  it "returns true" do
@@ -304,7 +304,7 @@ describe Mongoid::Matchable do
304
304
  context 'when a native Regexp object is used' do
305
305
 
306
306
  let(:selector) do
307
- { street: /^Clarkenwell/ }
307
+ { street: /\AClarkenwell/ }
308
308
  end
309
309
 
310
310
  it "returns true" do
@@ -4,7 +4,7 @@ describe Mongoid::Persistable::Pushable do
4
4
 
5
5
  describe "#add_to_set" do
6
6
 
7
- context "when the document is a root document" do
7
+ context "when the document is a top level document" do
8
8
 
9
9
  shared_examples_for "a unique pushable root document" do
10
10
 
@@ -62,6 +62,60 @@ describe Mongoid::Persistable::Pushable do
62
62
 
63
63
  it_behaves_like "a unique pushable root document"
64
64
  end
65
+
66
+ context 'when the host model is not saved' do
67
+ context 'when attribute exists' do
68
+ let(:person) do
69
+ Person.new(aliases: [2])
70
+ end
71
+
72
+ it 'records the change' do
73
+ person.add_to_set({aliases: 1})
74
+
75
+ expect(person.aliases).to eq([2, 1])
76
+ end
77
+ end
78
+
79
+ context 'when attribute does not exist' do
80
+ let(:person) do
81
+ Person.new
82
+ end
83
+
84
+ it 'records the change' do
85
+ person.add_to_set({aliases: 1})
86
+
87
+ expect(person.aliases).to eq([1])
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'when the host model is loaded from database' do
93
+ context 'when attribute exists' do
94
+ let(:person) do
95
+ Person.create!(aliases: [2])
96
+ person = Person.last
97
+ end
98
+
99
+ it 'records the change' do
100
+ person.add_to_set({aliases: 1})
101
+
102
+ expect(person.aliases).to eq([2, 1])
103
+ end
104
+ end
105
+
106
+ context 'when attribute does not exist' do
107
+ let(:person) do
108
+ Person.create!
109
+ person = Person.last
110
+ end
111
+
112
+ it 'records the change' do
113
+ person.add_to_set({aliases: 1})
114
+
115
+ expect(person.aliases).to eq([1])
116
+ end
117
+ end
118
+ end
65
119
  end
66
120
 
67
121
  context "when the document is embedded" do
@@ -180,7 +180,8 @@ describe Mongoid::QueryCache do
180
180
  end
181
181
  end
182
182
 
183
- context 'when the first query has a collation', if: collation_supported? do
183
+ context 'when the first query has a collation' do
184
+ min_server_version '3.4'
184
185
 
185
186
  before do
186
187
  Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
@@ -221,6 +222,10 @@ describe Mongoid::QueryCache do
221
222
  end
222
223
 
223
224
  before do
225
+ 10.times do |i|
226
+ game.ratings << Rating.create!(value: i+1)
227
+ end
228
+
224
229
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
225
230
  end
226
231
 
@@ -228,7 +233,9 @@ describe Mongoid::QueryCache do
228
233
 
229
234
  it "uses the cache" do
230
235
  expect_no_queries do
231
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
236
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
237
+ expect(result.length).to eq(2)
238
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
232
239
  end
233
240
  end
234
241
  end
@@ -241,14 +248,23 @@ describe Mongoid::QueryCache do
241
248
  end
242
249
 
243
250
  before do
251
+ 10.times do |i|
252
+ game.ratings << Rating.create!(value: i+1)
253
+ end
254
+
244
255
  game.ratings.where(:value.gt => 5).limit(3).asc(:id).all.to_a
245
256
  end
246
257
 
247
258
  context "when the next query has a limit" do
259
+ # Server versions older than 3.2 also perform a killCursors operation,
260
+ # which causes this test to fail.
261
+ min_server_version '3.2'
248
262
 
249
263
  it "queries again" do
250
264
  expect_query(1) do
251
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
265
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
266
+ expect(result.length).to eq(2)
267
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
252
268
  end
253
269
  end
254
270
  end
@@ -257,7 +273,9 @@ describe Mongoid::QueryCache do
257
273
 
258
274
  it "queries again" do
259
275
  expect_query(1) do
260
- game.ratings.where(:value.gt => 5).asc(:id).to_a
276
+ result = game.ratings.where(:value.gt => 5).asc(:id).to_a
277
+ expect(result.length).to eq(5)
278
+ expect(result.map { |r| r['value'] }).to eq([6, 7, 8, 9, 10])
261
279
  end
262
280
  end
263
281
  end
@@ -270,21 +288,34 @@ describe Mongoid::QueryCache do
270
288
  end
271
289
 
272
290
  before do
291
+ 10.times do |i|
292
+ game.ratings << Rating.create!(value: i+1)
293
+ end
294
+
273
295
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
274
296
  end
275
297
 
276
298
  it "does not query again" do
277
299
  expect_no_queries do
278
- game.ratings.where(:value.gt => 5).asc(:id).first
300
+ result = game.ratings.where(:value.gt => 5).asc(:id).first
301
+ expect(result['value']).to eq(6)
279
302
  end
280
303
  end
281
304
  end
282
305
 
283
306
  context "when limiting the result" do
307
+ before do
308
+ Band.destroy_all
309
+
310
+ 5.times { |i| Band.create!(name: "Band #{i}") }
311
+ Band.all.to_a
312
+ end
284
313
 
285
314
  it "does not query again" do
286
315
  expect_query(0) do
287
- Band.limit(2).all.to_a
316
+ result = Band.limit(2).all.to_a
317
+ expect(result.length).to eq(2)
318
+ expect(result.map { |r| r["name"] }).to eq(["Band 0", "Band 1"])
288
319
  end
289
320
  end
290
321
  end
@@ -292,12 +323,16 @@ describe Mongoid::QueryCache do
292
323
  context "when specifying a different skip value" do
293
324
 
294
325
  before do
295
- Band.limit(2).skip(1).all.to_a
326
+ Band.destroy_all
327
+
328
+ 5.times { |i| Band.create!(name: "Band #{i}") }
296
329
  end
297
330
 
298
331
  it "queries again" do
299
332
  expect_query(1) do
300
- Band.limit(2).skip(3).all.to_a
333
+ result = Band.limit(2).skip(3).all.to_a
334
+ expect(result.length).to eq(2)
335
+ expect(result.map { |r| r["name"] }).to eq(["Band 3", "Band 4"])
301
336
  end
302
337
  end
303
338
  end
@@ -333,6 +368,25 @@ describe Mongoid::QueryCache do
333
368
  end
334
369
  end
335
370
 
371
+ context 'when querying colleciton larger than the batch size' do
372
+ before do
373
+ Band.destroy_all
374
+ 101.times { |i| Band.create!(_id: i) }
375
+ end
376
+
377
+ it 'does not raise an exception when querying multiple times' do
378
+ expect do
379
+ results1 = Band.all.to_a
380
+ expect(results1.length).to eq(101)
381
+ expect(results1.map { |band| band["_id"] }).to eq([*0..100])
382
+
383
+ results2 = Band.all.to_a
384
+ expect(results2.length).to eq(101)
385
+ expect(results2.map { |band| band["_id"] }).to eq([*0..100])
386
+ end.not_to raise_error
387
+ end
388
+ end
389
+
336
390
  context "when query caching is enabled and the batch_size is set" do
337
391
 
338
392
  around(:each) do |example|
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # describe Mongoid::Relations::Proxy do
4
4
  #
5
- # describe '#with', if: non_legacy_server? do
5
+ # describe '#with' do
6
6
  #
7
7
  # let(:circus) do
8
8
  # Circus.new
@@ -227,7 +227,8 @@ describe Mongoid::Scopable do
227
227
 
228
228
  context "when provided a criteria" do
229
229
 
230
- context 'when a collation is defined on the criteria', if: collation_supported? do
230
+ context 'when a collation is defined on the criteria' do
231
+ min_server_version '3.4'
231
232
 
232
233
  before do
233
234
  Band.scope(:tests, ->{ Band.where(name: 'TESTING').collation(locale: 'en_US', strength: 2) })
@@ -45,7 +45,7 @@ shared_context "rails rake task" do
45
45
  end
46
46
  end
47
47
 
48
- describe "db:drop", if: non_legacy_server? do
48
+ describe "db:drop" do
49
49
  include_context "rake task"
50
50
  include_context "rails rake task"
51
51
 
@@ -58,7 +58,7 @@ describe "db:drop", if: non_legacy_server? do
58
58
  end
59
59
  end
60
60
 
61
- describe "db:purge", if: non_legacy_server? do
61
+ describe "db:purge" do
62
62
  include_context "rake task"
63
63
  include_context "rails rake task"
64
64
 
@@ -71,7 +71,7 @@ describe "db:purge", if: non_legacy_server? do
71
71
  end
72
72
  end
73
73
 
74
- describe "db:seed", if: non_legacy_server? do
74
+ describe "db:seed" do
75
75
  include_context "rake task"
76
76
  include_context "rails rake task"
77
77
 
@@ -85,7 +85,7 @@ describe "db:seed", if: non_legacy_server? do
85
85
  end
86
86
  end
87
87
 
88
- describe "db:setup", if: non_legacy_server? do
88
+ describe "db:setup" do
89
89
  include_context "rake task"
90
90
  include_context "rails rake task"
91
91
 
@@ -117,7 +117,7 @@ describe "db:setup", if: non_legacy_server? do
117
117
  end
118
118
  end
119
119
 
120
- describe "db:reset", if: non_legacy_server? do
120
+ describe "db:reset" do
121
121
  include_context "rake task"
122
122
  include_context "rails rake task"
123
123
 
@@ -135,7 +135,7 @@ describe "db:reset", if: non_legacy_server? do
135
135
  end
136
136
  end
137
137
 
138
- describe "db:create", if: non_legacy_server? do
138
+ describe "db:create" do
139
139
  include_context "rake task"
140
140
  include_context "rails rake task"
141
141
 
@@ -144,7 +144,7 @@ describe "db:create", if: non_legacy_server? do
144
144
  end
145
145
  end
146
146
 
147
- describe "db:migrate", if: non_legacy_server? do
147
+ describe "db:migrate" do
148
148
  include_context "rake task"
149
149
  include_context "rails rake task"
150
150
 
@@ -153,7 +153,7 @@ describe "db:migrate", if: non_legacy_server? do
153
153
  end
154
154
  end
155
155
 
156
- describe "db:test:prepare", if: non_legacy_server? do
156
+ describe "db:test:prepare" do
157
157
  include_context "rake task"
158
158
  include_context "rails rake task"
159
159
 
@@ -174,7 +174,7 @@ describe "db:test:prepare", if: non_legacy_server? do
174
174
  end
175
175
  end
176
176
 
177
- describe "db:mongoid:create_indexes", if: non_legacy_server? do
177
+ describe "db:mongoid:create_indexes" do
178
178
  include_context "rake task"
179
179
 
180
180
  it_behaves_like "create_indexes"
@@ -198,7 +198,7 @@ describe "db:mongoid:create_indexes", if: non_legacy_server? do
198
198
  end
199
199
  end
200
200
 
201
- describe "db:mongoid:remove_undefined_indexes", if: non_legacy_server? do
201
+ describe "db:mongoid:remove_undefined_indexes" do
202
202
  include_context "rake task"
203
203
 
204
204
  it "receives remove_undefined_indexes" do
@@ -224,7 +224,7 @@ describe "db:mongoid:remove_undefined_indexes", if: non_legacy_server? do
224
224
  end
225
225
  end
226
226
 
227
- describe "db:mongoid:remove_indexes", if: non_legacy_server? do
227
+ describe "db:mongoid:remove_indexes" do
228
228
  include_context "rake task"
229
229
 
230
230
  it "receives remove_indexes" do
@@ -250,7 +250,7 @@ describe "db:mongoid:remove_indexes", if: non_legacy_server? do
250
250
  end
251
251
  end
252
252
 
253
- describe "db:mongoid:drop", if: non_legacy_server? do
253
+ describe "db:mongoid:drop" do
254
254
  include_context "rake task"
255
255
 
256
256
  it "works" do
@@ -266,7 +266,7 @@ describe "db:mongoid:drop", if: non_legacy_server? do
266
266
  end
267
267
  end
268
268
 
269
- describe "db:mongoid:purge", if: non_legacy_server? do
269
+ describe "db:mongoid:purge" do
270
270
  include_context "rake task"
271
271
 
272
272
  it "receives a purge" do