mongoid_monkey 0.1.2 → 0.1.3

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.
@@ -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