mongoid_monkey 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,527 @@
1
+ require "spec_helper"
2
+
3
+ if Mongoid::VERSION =~ /\A4\./
4
+
5
+ describe Mongoid::Indexable do
6
+
7
+ describe ".included" do
8
+
9
+ let(:klass) do
10
+ Class.new do
11
+ include Mongoid::Indexable
12
+ end
13
+ end
14
+
15
+ it "adds an index_specifications accessor" do
16
+ expect(klass).to respond_to(:index_specifications)
17
+ end
18
+
19
+ it "defaults index_specifications to empty array" do
20
+ expect(klass.index_specifications).to be_empty
21
+ end
22
+ end
23
+
24
+ describe ".remove_indexes" do
25
+
26
+ context "when no database specific options exist" do
27
+
28
+ let(:klass) do
29
+ Person
30
+ end
31
+
32
+ let(:collection) do
33
+ klass.collection
34
+ end
35
+
36
+ before do
37
+ klass.create_indexes
38
+ klass.remove_indexes
39
+ end
40
+
41
+ it "removes the indexes" do
42
+ expect(collection.indexes.reject{ |doc| doc["name"] == "_id_" }).to be_empty
43
+ end
44
+ end
45
+
46
+ context "when database specific options exist" do
47
+
48
+ let(:klass) do
49
+ Class.new do
50
+ include Mongoid::Document
51
+ store_in collection: "test_db_remove"
52
+ index({ test: 1 }, { database: "mia_2" })
53
+ index({ name: 1 }, { background: true })
54
+ end
55
+ end
56
+
57
+ before do
58
+ klass.create_indexes
59
+ klass.remove_indexes
60
+ end
61
+
62
+ let(:indexes) do
63
+ klass.with(database: "mia_2").collection.indexes
64
+ end
65
+
66
+ it "creates the indexes" do
67
+ expect(indexes.reject{ |doc| doc["name"] == "_id_" }).to be_empty
68
+ end
69
+ end
70
+ end
71
+
72
+ describe ".create_indexes" do
73
+
74
+ context "when no database options are specified" do
75
+
76
+ let(:klass) do
77
+ Class.new do
78
+ include Mongoid::Document
79
+ store_in collection: "test_class"
80
+ index({ _type: 1 }, unique: false, background: true)
81
+ end
82
+ end
83
+
84
+ before do
85
+ klass.create_indexes
86
+ end
87
+
88
+ it "creates the indexes" do
89
+ expect(klass.collection.indexes[_type: 1]).to_not be_nil
90
+ end
91
+ end
92
+
93
+ context "when database options are specified" do
94
+
95
+ let(:klass) do
96
+ Class.new do
97
+ include Mongoid::Document
98
+ store_in collection: "test_db_indexes"
99
+ index({ _type: 1 }, { database: "mia_1" })
100
+ end
101
+ end
102
+
103
+ before do
104
+ klass.create_indexes
105
+ end
106
+
107
+ let(:indexes) do
108
+ klass.with(database: "mia_1").collection.indexes
109
+ end
110
+
111
+ it "creates the indexes" do
112
+ expect(indexes[_type: 1]).to_not be_nil
113
+ end
114
+ end
115
+ end
116
+
117
+ describe ".add_indexes" do
118
+
119
+ context "when indexes have not been added" do
120
+
121
+ let(:klass) do
122
+ Class.new do
123
+ include Mongoid::Document
124
+ def self.hereditary?
125
+ true
126
+ end
127
+ end
128
+ end
129
+
130
+ before do
131
+ klass.add_indexes
132
+ end
133
+
134
+ let(:spec) do
135
+ klass.index_specification(_type: 1)
136
+ end
137
+
138
+ it "adds the _type index" do
139
+ expect(spec.options).to eq(unique: false, background: true)
140
+ end
141
+ end
142
+ end
143
+
144
+ describe ".index" do
145
+
146
+ let(:klass) do
147
+ Class.new do
148
+ include Mongoid::Document
149
+ field :a, as: :authentication_token
150
+ end
151
+ end
152
+
153
+ context "when indexing a field that is aliased" do
154
+
155
+ before do
156
+ klass.index({ authentication_token: 1 }, unique: true)
157
+ end
158
+
159
+ let(:options) do
160
+ klass.index_specification(a: 1).options
161
+ end
162
+
163
+ it "sets the index with unique options" do
164
+ expect(options).to eq(unique: true)
165
+ end
166
+ end
167
+
168
+ context "when providing unique options" do
169
+
170
+ before do
171
+ klass.index({ name: 1 }, unique: true)
172
+ end
173
+
174
+ let(:options) do
175
+ klass.index_specification(name: 1).options
176
+ end
177
+
178
+ it "sets the index with unique options" do
179
+ expect(options).to eq(unique: true)
180
+ end
181
+ end
182
+
183
+ context "when providing a drop_dups option" do
184
+
185
+ before do
186
+ klass.index({ name: 1 }, drop_dups: true)
187
+ end
188
+
189
+ let(:options) do
190
+ klass.index_specification(name: 1).options
191
+ end
192
+
193
+ it "sets the index with dropDups options" do
194
+ expect(options).to eq(dropDups: true)
195
+ end
196
+ end
197
+
198
+ context "when providing a sparse option" do
199
+
200
+ before do
201
+ klass.index({ name: 1 }, sparse: true)
202
+ end
203
+
204
+ let(:options) do
205
+ klass.index_specification(name: 1).options
206
+ end
207
+
208
+ it "sets the index with sparse options" do
209
+ expect(options).to eq(sparse: true)
210
+ end
211
+ end
212
+
213
+ context "when providing a name option" do
214
+
215
+ before do
216
+ klass.index({ name: 1 }, name: "index_name")
217
+ end
218
+
219
+ let(:options) do
220
+ klass.index_specification(name: 1).options
221
+ end
222
+
223
+ it "sets the index with name options" do
224
+ expect(options).to eq(name: "index_name")
225
+ end
226
+ end
227
+
228
+ context "when providing database options" do
229
+
230
+ before do
231
+ klass.index({ name: 1 }, database: "mongoid_index_alt")
232
+ end
233
+
234
+ let(:options) do
235
+ klass.index_specification(name: 1).options
236
+ end
237
+
238
+ it "sets the index with background options" do
239
+ expect(options).to eq(database: "mongoid_index_alt")
240
+ end
241
+ end
242
+
243
+ context "when providing a background option" do
244
+
245
+ before do
246
+ klass.index({ name: 1 }, background: true)
247
+ end
248
+
249
+ let(:options) do
250
+ klass.index_specification(name: 1).options
251
+ end
252
+
253
+ it "sets the index with background options" do
254
+ expect(options).to eq(background: true)
255
+ end
256
+ end
257
+
258
+ context "when providing a compound index" do
259
+
260
+ before do
261
+ klass.index({ name: 1, title: -1 })
262
+ end
263
+
264
+ let(:options) do
265
+ klass.index_specification(name: 1, title: -1).options
266
+ end
267
+
268
+ it "sets the compound key index" do
269
+ expect(options).to be_empty
270
+ end
271
+ end
272
+
273
+ context "when providing multiple inverse compound indexes" do
274
+
275
+ before do
276
+ klass.index({ name: 1, title: -1 })
277
+ klass.index({ title: -1, name: 1 })
278
+ end
279
+
280
+ let(:first_spec) do
281
+ klass.index_specification(name: 1, title: -1)
282
+ end
283
+
284
+ let(:second_spec) do
285
+ klass.index_specification(title: -1, name: 1)
286
+ end
287
+
288
+ it "does not overwrite the index options" do
289
+ expect(first_spec).to_not eq(second_spec)
290
+ end
291
+ end
292
+
293
+ context "when providing multiple compound indexes with different order" do
294
+
295
+ before do
296
+ klass.index({ name: 1, title: -1 })
297
+ klass.index({ name: 1, title: 1 })
298
+ end
299
+
300
+ let(:first_spec) do
301
+ klass.index_specification(name: 1, title: -1)
302
+ end
303
+
304
+ let(:second_spec) do
305
+ klass.index_specification(name: 1, title: 1)
306
+ end
307
+
308
+ it "does not overwrite the index options" do
309
+ expect(first_spec).to_not eq(second_spec)
310
+ end
311
+ end
312
+
313
+ context "when providing a geospacial index" do
314
+
315
+ before do
316
+ klass.index({ location: "2d" }, { min: -200, max: 200, bits: 32 })
317
+ end
318
+
319
+ let(:options) do
320
+ klass.index_specification(location: "2d").options
321
+ end
322
+
323
+ it "sets the geospacial index" do
324
+ expect(options).to eq({ min: -200, max: 200, bits: 32 })
325
+ end
326
+ end
327
+
328
+ context "when providing a geo haystack index" do
329
+
330
+ before do
331
+ klass.index({ location: "geoHaystack" }, { min: -200, max: 200, bucket_size: 0.5 })
332
+ end
333
+
334
+ let(:options) do
335
+ klass.index_specification(location: "geoHaystack").options
336
+ end
337
+
338
+ it "sets the geo haystack index" do
339
+ expect(options).to eq({ min: -200, max: 200, bucketSize: 0.5 })
340
+ end
341
+ end
342
+
343
+ context "when providing a Spherical Geospatial index" do
344
+
345
+ before do
346
+ klass.index({ location: "2dsphere" })
347
+ end
348
+
349
+ let(:options) do
350
+ klass.index_specification(location: "2dsphere").options
351
+ end
352
+
353
+ it "sets the spherical geospatial index" do
354
+ expect(options).to be_empty
355
+ end
356
+ end
357
+
358
+ context "when providing a text index" do
359
+
360
+ context "when the index is a single field" do
361
+
362
+ before do
363
+ klass.index({ description: "text" })
364
+ end
365
+
366
+ let(:options) do
367
+ klass.index_specification(description: "text").options
368
+ end
369
+
370
+ it "allows the set of the text index" do
371
+ expect(options).to be_empty
372
+ end
373
+ end
374
+
375
+ context "when the index is multiple fields" do
376
+
377
+ before do
378
+ klass.index({ description: "text", name: "text" })
379
+ end
380
+
381
+ let(:options) do
382
+ klass.index_specification(description: "text", name: "text").options
383
+ end
384
+
385
+ it "allows the set of the text index" do
386
+ expect(options).to be_empty
387
+ end
388
+ end
389
+
390
+ context "when the index is all string fields" do
391
+
392
+ before do
393
+ klass.index({ "$**" => "text" })
394
+ end
395
+
396
+ let(:options) do
397
+ klass.index_specification(:"$**" => "text").options
398
+ end
399
+
400
+ it "allows the set of the text index" do
401
+ expect(options).to be_empty
402
+ end
403
+ end
404
+
405
+ context "when providing a default language" do
406
+
407
+ before do
408
+ klass.index({ description: "text" }, default_language: "english")
409
+ end
410
+
411
+ let(:options) do
412
+ klass.index_specification(description: "text").options
413
+ end
414
+
415
+ it "allows the set of the text index" do
416
+ expect(options).to eq(default_language: "english")
417
+ end
418
+ end
419
+
420
+ context "when providing a name" do
421
+
422
+ before do
423
+ klass.index({ description: "text" }, name: "text_index")
424
+ end
425
+
426
+ let(:options) do
427
+ klass.index_specification(description: "text").options
428
+ end
429
+
430
+ it "allows the set of the text index" do
431
+ expect(options).to eq(name: "text_index")
432
+ end
433
+ end
434
+ end
435
+
436
+ context "when providing a hashed index" do
437
+
438
+ before do
439
+ klass.index({ a: "hashed" })
440
+ end
441
+
442
+ let(:options) do
443
+ klass.index_specification(a: "hashed").options
444
+ end
445
+
446
+ it "sets the hashed index" do
447
+ expect(options).to be_empty
448
+ end
449
+ end
450
+
451
+ context "when providing a text index" do
452
+
453
+ before do
454
+ klass.index({ content: "text" })
455
+ end
456
+
457
+ let(:options) do
458
+ klass.index_specification(content: "text").options
459
+ end
460
+
461
+ it "sets the text index" do
462
+ expect(options).to be_empty
463
+ end
464
+ end
465
+
466
+ context "when providing a compound text index" do
467
+
468
+ before do
469
+ klass.index({ content: "text", title: "text" }, { weights: { content: 1, title: 2 } })
470
+ end
471
+
472
+ let(:options) do
473
+ klass.index_specification(content: "text", title: "text").options
474
+ end
475
+
476
+ it "sets the compound text index" do
477
+ expect(options).to eq(weights: { content: 1, title: 2 })
478
+ end
479
+ end
480
+
481
+ context "when providing an expire_after_seconds option" do
482
+
483
+ before do
484
+ klass.index({ name: 1 }, { expire_after_seconds: 3600 })
485
+ end
486
+
487
+ let(:options) do
488
+ klass.index_specification(name: 1).options
489
+ end
490
+
491
+ it "sets the index with sparse options" do
492
+ expect(options).to eq(expireAfterSeconds: 3600)
493
+ end
494
+ end
495
+
496
+ context "when providing an invalid option" do
497
+
498
+ it "raises an error" do
499
+ expect {
500
+ klass.index({ name: 1 }, { invalid: true })
501
+ }.to raise_error(Mongoid::Errors::InvalidIndex)
502
+ end
503
+ end
504
+
505
+ context "when providing an invalid spec" do
506
+
507
+ context "when the spec is not a hash" do
508
+
509
+ it "raises an error" do
510
+ expect {
511
+ klass.index(:name)
512
+ }.to raise_error(Mongoid::Errors::InvalidIndex)
513
+ end
514
+ end
515
+
516
+ context "when the spec key is invalid" do
517
+
518
+ it "raises an error" do
519
+ expect {
520
+ klass.index({ name: "something" })
521
+ }.to raise_error(Mongoid::Errors::InvalidIndex)
522
+ end
523
+ end
524
+ end
525
+ end
526
+ end
527
+ end
@@ -0,0 +1,163 @@
1
+ require "spec_helper"
2
+
3
+ if Mongoid::VERSION =~ /\A4\./
4
+
5
+ describe Mongoid::Tasks::Database do
6
+
7
+ let(:logger) do
8
+ double("logger").tap do |log|
9
+ allow(log).to receive(:info)
10
+ end
11
+ end
12
+
13
+ before do
14
+ allow(Mongoid::Tasks::Database).to receive(:logger).and_return(logger)
15
+ end
16
+
17
+ let(:models) do
18
+ [ User, Account, Address, Draft ]
19
+ end
20
+
21
+ describe ".create_indexes" do
22
+
23
+ let!(:klass) do
24
+ User
25
+ end
26
+
27
+ let(:indexes) do
28
+ Mongoid::Tasks::Database.create_indexes(models)
29
+ end
30
+
31
+ context "with ordinary Rails models" do
32
+
33
+ it "creates the indexes for the models" do
34
+ expect(klass).to receive(:create_indexes).once
35
+ indexes
36
+ end
37
+ end
38
+
39
+ context "with a model without indexes" do
40
+
41
+ let(:klass) do
42
+ Account
43
+ end
44
+
45
+ it "does nothing" do
46
+ expect(klass).to receive(:create_indexes).never
47
+ indexes
48
+ end
49
+ end
50
+
51
+ context "when an exception is raised" do
52
+
53
+ it "is not swallowed" do
54
+ expect(klass).to receive(:create_indexes).and_raise(ArgumentError)
55
+ expect { indexes }.to raise_error(ArgumentError)
56
+ end
57
+ end
58
+
59
+ context "when index is defined on embedded model" do
60
+
61
+ let!(:klass) do
62
+ Address
63
+ end
64
+
65
+ before do
66
+ klass.index(street: 1)
67
+ end
68
+
69
+ it "does nothing, but logging" do
70
+ expect(klass).to receive(:create_indexes).never
71
+ indexes
72
+ end
73
+ end
74
+
75
+ context "when index is defined on self-embedded (cyclic) model" do
76
+
77
+ let(:klass) do
78
+ Draft
79
+ end
80
+
81
+ it "creates the indexes for the models" do
82
+ expect(klass).to receive(:create_indexes).once
83
+ indexes
84
+ end
85
+ end
86
+ end
87
+
88
+ describe ".undefined_indexes" do
89
+
90
+ before(:each) do
91
+ Mongoid::Tasks::Database.create_indexes(models)
92
+ end
93
+
94
+ let(:indexes) do
95
+ Mongoid::Tasks::Database.undefined_indexes(models)
96
+ end
97
+
98
+ it "returns the removed indexes" do
99
+ expect(indexes).to be_empty
100
+ end
101
+
102
+ context "with extra index on model collection" do
103
+
104
+ before(:each) do
105
+ User.collection.indexes.create(account_expires: 1)
106
+ end
107
+
108
+ let(:names) do
109
+ indexes[User].map{ |index| index['name'] }
110
+ end
111
+
112
+ it "should have single index returned" do
113
+ expect(names).to eq(['account_expires_1'])
114
+ end
115
+ end
116
+ end
117
+
118
+ describe ".remove_undefined_indexes" do
119
+
120
+ let(:indexes) do
121
+ User.collection.indexes
122
+ end
123
+
124
+ before(:each) do
125
+ Mongoid::Tasks::Database.create_indexes(models)
126
+ indexes.create(account_expires: 1)
127
+ Mongoid::Tasks::Database.remove_undefined_indexes(models)
128
+ end
129
+
130
+ let(:removed_indexes) do
131
+ Mongoid::Tasks::Database.undefined_indexes(models)
132
+ end
133
+
134
+ it "returns the removed indexes" do
135
+ expect(removed_indexes).to be_empty
136
+ end
137
+ end
138
+
139
+ describe ".remove_indexes" do
140
+
141
+ let!(:klass) do
142
+ User
143
+ end
144
+
145
+ let(:indexes) do
146
+ klass.collection.indexes
147
+ end
148
+
149
+ before :each do
150
+ Mongoid::Tasks::Database.create_indexes(models)
151
+ Mongoid::Tasks::Database.remove_indexes(models)
152
+ end
153
+
154
+ it "removes indexes from klass" do
155
+ expect(indexes.reject{ |doc| doc["name"] == "_id_" }).to be_empty
156
+ end
157
+
158
+ it "leaves _id index untouched" do
159
+ expect(indexes.select{ |doc| doc["name"] == "_id_" }).to_not be_empty
160
+ end
161
+ end
162
+ end
163
+ end