mongoid 7.0.4 → 7.0.10

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