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.
- checksums.yaml +4 -4
- data/lib/mongoid_monkey.rb +5 -13
- data/lib/patches/atomic.rb +5 -0
- data/lib/patches/big_decimal.rb +24 -21
- data/lib/patches/db_commands.rb +98 -28
- data/lib/patches/instrument.rb +27 -24
- data/lib/patches/reorder.rb +8 -5
- data/lib/version.rb +1 -1
- data/spec/app/models/account.rb +4 -0
- data/spec/app/models/address.rb +7 -0
- data/spec/app/models/draft.rb +7 -0
- data/spec/app/models/person.rb +11 -0
- data/spec/app/models/user.rb +6 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/unit/db_commands/mongoid3_indexes_spec.rb +408 -0
- data/spec/unit/db_commands/mongoid3_tasks_spec.rb +112 -0
- data/spec/unit/db_commands/mongoid4_indexes_spec.rb +527 -0
- data/spec/unit/db_commands/mongoid4_tasks_spec.rb +163 -0
- data/spec/unit/db_commands/moped_database_spec.rb +62 -0
- data/spec/unit/db_commands/moped_indexes_spec.rb +85 -0
- metadata +23 -3
- data/spec/unit/db_commands_spec.rb +0 -1086
@@ -0,0 +1,408 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
if Mongoid::VERSION =~ /\A3\./
|
4
|
+
|
5
|
+
describe Mongoid::Indexes do
|
6
|
+
|
7
|
+
describe ".included" do
|
8
|
+
|
9
|
+
let(:klass) do
|
10
|
+
Class.new do
|
11
|
+
include Mongoid::Indexes
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "adds an index_options accessor" do
|
16
|
+
klass.should respond_to(:index_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "defaults index_options to empty hash" do
|
20
|
+
klass.index_options.should eq({})
|
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
|
+
collection.indexes.reject{ |doc| doc["name"] == "_id_" }.should 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
|
+
indexes.reject{ |doc| doc["name"] == "_id_" }.should 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
|
+
klass.collection.indexes[_type: 1].should_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
|
+
indexes[_type: 1].should_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
|
+
it "adds the _type index" do
|
135
|
+
klass.index_options[_type: 1].should eq(
|
136
|
+
{ unique: false, background: true }
|
137
|
+
)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe ".index" do
|
143
|
+
|
144
|
+
let(:klass) do
|
145
|
+
Class.new do
|
146
|
+
include Mongoid::Document
|
147
|
+
field :a, as: :authentication_token
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "when indexing a field that is aliased" do
|
152
|
+
|
153
|
+
before do
|
154
|
+
klass.index({ authentication_token: 1 }, { unique: true })
|
155
|
+
end
|
156
|
+
|
157
|
+
let(:options) do
|
158
|
+
klass.index_options[a: 1]
|
159
|
+
end
|
160
|
+
|
161
|
+
it "sets the index with unique options" do
|
162
|
+
options.should eq(unique: true)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "when providing unique options" do
|
167
|
+
|
168
|
+
before do
|
169
|
+
klass.index({ name: 1 }, { unique: true })
|
170
|
+
end
|
171
|
+
|
172
|
+
let(:options) do
|
173
|
+
klass.index_options[name: 1]
|
174
|
+
end
|
175
|
+
|
176
|
+
it "sets the index with unique options" do
|
177
|
+
options.should eq(unique: true)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "when providing a drop_dups option" do
|
182
|
+
|
183
|
+
before do
|
184
|
+
klass.index({ name: 1 }, { drop_dups: true })
|
185
|
+
end
|
186
|
+
|
187
|
+
let(:options) do
|
188
|
+
klass.index_options[name: 1]
|
189
|
+
end
|
190
|
+
|
191
|
+
it "sets the index with dropDups options" do
|
192
|
+
options.should eq(dropDups: true)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when providing a sparse option" do
|
197
|
+
|
198
|
+
before do
|
199
|
+
klass.index({ name: 1 }, { sparse: true })
|
200
|
+
end
|
201
|
+
|
202
|
+
let(:options) do
|
203
|
+
klass.index_options[name: 1]
|
204
|
+
end
|
205
|
+
|
206
|
+
it "sets the index with sparse options" do
|
207
|
+
options.should eq(sparse: true)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "when providing a name option" do
|
212
|
+
|
213
|
+
before do
|
214
|
+
klass.index({ name: 1 }, { name: "index_name" })
|
215
|
+
end
|
216
|
+
|
217
|
+
let(:options) do
|
218
|
+
klass.index_options[name: 1]
|
219
|
+
end
|
220
|
+
|
221
|
+
it "sets the index with name options" do
|
222
|
+
options.should eq(name: "index_name")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context "when providing database options" do
|
227
|
+
|
228
|
+
before do
|
229
|
+
klass.index({ name: 1 }, { database: "mongoid_index_alt" })
|
230
|
+
end
|
231
|
+
|
232
|
+
let(:options) do
|
233
|
+
klass.index_options[name: 1]
|
234
|
+
end
|
235
|
+
|
236
|
+
it "sets the index with background options" do
|
237
|
+
options.should eq(database: "mongoid_index_alt")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "when providing a background option" do
|
242
|
+
|
243
|
+
before do
|
244
|
+
klass.index({ name: 1 }, { background: true })
|
245
|
+
end
|
246
|
+
|
247
|
+
let(:options) do
|
248
|
+
klass.index_options[name: 1]
|
249
|
+
end
|
250
|
+
|
251
|
+
it "sets the index with background options" do
|
252
|
+
options.should eq(background: true)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "when providing a compound index" do
|
257
|
+
|
258
|
+
before do
|
259
|
+
klass.index({ name: 1, title: -1 })
|
260
|
+
end
|
261
|
+
|
262
|
+
let(:options) do
|
263
|
+
klass.index_options[name: 1, title: -1]
|
264
|
+
end
|
265
|
+
|
266
|
+
it "sets the compound key index" do
|
267
|
+
options.should be_empty
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context "when providing a geospacial index" do
|
272
|
+
|
273
|
+
before do
|
274
|
+
klass.index({ location: "2d" }, { min: -200, max: 200, bits: 32 })
|
275
|
+
end
|
276
|
+
|
277
|
+
let(:options) do
|
278
|
+
klass.index_options[location: "2d"]
|
279
|
+
end
|
280
|
+
|
281
|
+
it "sets the geospacial index" do
|
282
|
+
options.should eq({ min: -200, max: 200, bits: 32 })
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context "when providing a geo haystack index" do
|
287
|
+
|
288
|
+
before do
|
289
|
+
klass.index({ location: "geoHaystack" }, { min: -200, max: 200, bucket_size: 0.5 })
|
290
|
+
end
|
291
|
+
|
292
|
+
let(:options) do
|
293
|
+
klass.index_options[location: "geoHaystack"]
|
294
|
+
end
|
295
|
+
|
296
|
+
it "sets the geo haystack index" do
|
297
|
+
options.should eq({ min: -200, max: 200, bucketSize: 0.5 })
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context "when providing a Spherical Geospatial index" do
|
302
|
+
|
303
|
+
before do
|
304
|
+
klass.index({ location: "2dsphere" })
|
305
|
+
end
|
306
|
+
|
307
|
+
let(:options) do
|
308
|
+
klass.index_options[location: "2dsphere"]
|
309
|
+
end
|
310
|
+
|
311
|
+
it "sets the spherical geospatial index" do
|
312
|
+
options.should be_empty
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "when providing a hashed index" do
|
317
|
+
|
318
|
+
before do
|
319
|
+
klass.index({ a: "hashed" })
|
320
|
+
end
|
321
|
+
|
322
|
+
let(:options) do
|
323
|
+
klass.index_options[a: "hashed"]
|
324
|
+
end
|
325
|
+
|
326
|
+
it "sets the hashed index" do
|
327
|
+
options.should be_empty
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "when providing a text index" do
|
332
|
+
|
333
|
+
before do
|
334
|
+
klass.index({ content: "text" })
|
335
|
+
end
|
336
|
+
|
337
|
+
let(:options) do
|
338
|
+
klass.index_options[content: "text"]
|
339
|
+
end
|
340
|
+
|
341
|
+
it "sets the text index" do
|
342
|
+
options.should be_empty
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
context "when providing a compound text index" do
|
347
|
+
|
348
|
+
before do
|
349
|
+
klass.index({ content: "text", title: "text" }, { weights: { content: 1, title: 2 } })
|
350
|
+
end
|
351
|
+
|
352
|
+
let(:options) do
|
353
|
+
klass.index_options[content: "text", title: "text"]
|
354
|
+
end
|
355
|
+
|
356
|
+
it "sets the compound text index" do
|
357
|
+
options.should eq(weights: { content: 1, title: 2 })
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context "when providing an expire_after_seconds option" do
|
362
|
+
|
363
|
+
before do
|
364
|
+
klass.index({ name: 1 }, { expire_after_seconds: 3600 })
|
365
|
+
end
|
366
|
+
|
367
|
+
let(:options) do
|
368
|
+
klass.index_options[name: 1]
|
369
|
+
end
|
370
|
+
|
371
|
+
it "sets the index with sparse options" do
|
372
|
+
options.should eq(expireAfterSeconds: 3600)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context "when providing an invalid option" do
|
377
|
+
|
378
|
+
it "raises an error" do
|
379
|
+
expect {
|
380
|
+
klass.index({ name: 1 }, { invalid: true })
|
381
|
+
}.to raise_error(Mongoid::Errors::InvalidIndex)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context "when providing an invalid spec" do
|
386
|
+
|
387
|
+
context "when the spec is not a hash" do
|
388
|
+
|
389
|
+
it "raises an error" do
|
390
|
+
expect {
|
391
|
+
klass.index(:name)
|
392
|
+
}.to raise_error(Mongoid::Errors::InvalidIndex)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context "when the spec key is invalid" do
|
397
|
+
|
398
|
+
it "raises an error" do
|
399
|
+
expect {
|
400
|
+
klass.index({ name: "something" })
|
401
|
+
}.to raise_error(Mongoid::Errors::InvalidIndex)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
if Mongoid::VERSION =~ /\A3\./
|
4
|
+
|
5
|
+
describe Rails::Mongoid 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(Rails::Mongoid).to receive(:logger).and_return(logger)
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:pattern) do
|
18
|
+
"spec/app/models/**/*.rb"
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".create_indexes" do
|
22
|
+
|
23
|
+
let!(:klass) do
|
24
|
+
User
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:indexes) do
|
28
|
+
Rails::Mongoid.create_indexes(pattern)
|
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 ".remove_indexes" do
|
89
|
+
|
90
|
+
let!(:klass) do
|
91
|
+
User
|
92
|
+
end
|
93
|
+
|
94
|
+
let(:indexes) do
|
95
|
+
klass.collection.indexes
|
96
|
+
end
|
97
|
+
|
98
|
+
before :each do
|
99
|
+
Rails::Mongoid.create_indexes(pattern)
|
100
|
+
Rails::Mongoid.remove_indexes(pattern)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "removes indexes from klass" do
|
104
|
+
expect(indexes.reject{ |doc| doc["name"] == "_id_" }).to be_empty
|
105
|
+
end
|
106
|
+
|
107
|
+
it "leaves _id index untouched" do
|
108
|
+
expect(indexes.select{ |doc| doc["name"] == "_id_" }).to_not be_empty
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|