activerecord-alt-mongo-adapter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,585 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'active_mongo/collection'
4
+ require 'mongo' # for test
5
+
6
+ # global setup ###############################################################
7
+
8
+ Mongo::Connection.new.drop_database('scott')
9
+ ActiveRecord::Base.establish_connection(:adapter => 'mongo', :database => 'scott')
10
+
11
+ # spec ########################################################################
12
+
13
+ describe ActiveMongo do
14
+ before do
15
+ Emp.setup
16
+ Dept.setup
17
+ end
18
+
19
+ it 'EMP: find(:all)' do
20
+ emps = Emp.find(:all).sort_by {|i| i.empno }
21
+ emps.length.should == Emp::DATA.length
22
+
23
+ emps.each_with_index do |emp, i|
24
+ emp.should == Emp::DATA[i]
25
+ end
26
+ end
27
+
28
+ it 'EMP: find multi cond' do
29
+ emps = Emp.find(:all, :conditions => ['job = ? and deptno > ?', 'MANAGER', 10], :order => 'empno')
30
+ expected = Emp::DATA.select {|i| i['job'] == 'MANAGER' and i['deptno'] > 10 }
31
+ emps.length.should == expected.length
32
+ emps.map {|i| i['empno'] }.should == expected.map {|i| i['empno'] }
33
+ end
34
+
35
+ it 'DEPT: find(:all)' do
36
+ depts = Dept.find(:all).sort_by {|i| i.deptno }
37
+ depts.length.should == Dept::DATA.length
38
+
39
+ depts.each_with_index do |dept, i|
40
+ dept.should == Dept::DATA[i]
41
+ end
42
+ end
43
+
44
+ it 'EMP: count' do
45
+ Emp.count.should == Emp::DATA.length
46
+ end
47
+
48
+ it 'DATA: count' do
49
+ Dept.count.should == Dept::DATA.length
50
+ end
51
+
52
+ it 'EMP: count with cond' do
53
+ Emp.count(:conditions => ['job = ?', 'MANAGER']).should == Emp::DATA.select {|i| i['job'] == 'MANAGER' }.length
54
+ end
55
+
56
+ it 'DATA: count with cond' do
57
+ Dept.count(:conditions => ['deptno >= ?', 30]).should == Dept::DATA.select {|i| i['deptno'] >= 30 }.length
58
+ end
59
+
60
+ it 'EMP: order asc' do
61
+ emps = Emp.find(:all, :conditions => {:job => 'MANAGER'}, :order => 'sal')
62
+ expected = Emp::DATA.select {|i| i['job'] == 'MANAGER' }.sort_by {|i| i['sal'] }
63
+ emps.map {|i| i['empno'] }.should == expected.map {|i| i['empno'] }
64
+
65
+ emps = Emp.find(:all, :conditions => {:job => 'SALESMAN'}, :order => 'sal asc')
66
+ expected = Emp::DATA.select {|i| i['job'] == 'SALESMAN' }.sort_by {|i| i['sal'] }
67
+ emps.map {|i| i['empno'] }.should == expected.map {|i| i['empno'] }
68
+ end
69
+
70
+ it 'DATA: order desc' do
71
+ depts = Dept.find(:all, :order => 'deptno desc')
72
+ expected = Dept::DATA.sort_by {|i| i['deptno'] }.reverse
73
+ depts.map {|i| i['deptno'] }.should == expected.map {|i| i['deptno'] }
74
+ end
75
+
76
+ it 'EMP: find limit' do
77
+ emps = Emp.find(:all, :limit => 5)
78
+ emps.length.should == 5
79
+ end
80
+
81
+ it 'DEPT: find limit' do
82
+ depts = Dept.find(:all, :limit => 3)
83
+ depts.length.should == 3
84
+ end
85
+
86
+ it 'EMP: find limit sort' do
87
+ emps = Emp.find(:all, :conditions => {:job => 'MANAGER'}, :limit => 2, :order => 'empno desc')
88
+ expected = Emp::DATA.select {|i| i['job'] == 'MANAGER' }.sort_by {|i| i['empno'] }.reverse.slice(0, 2)
89
+ emps.map {|i| i['empno'] }.should == expected.map {|i| i['empno'] }
90
+ end
91
+
92
+ it 'DEPT: count limit' do
93
+ Dept.count(:limit => 2).should == 2
94
+ end
95
+
96
+ it 'EMP: save' do
97
+ emp = Emp.find(:first, :conditions => ["empno = 7782"])
98
+ emp.should_not be_nil
99
+
100
+ emp.job = 'ANALYST'
101
+ emp.age = 48
102
+ emp.save.should be_true
103
+
104
+ emps = Emp.find(:all, :conditions => ["age = 48"])
105
+ emps.length.should == 1
106
+ emps[0].should_not be_nil
107
+ emps[0].empno.should == 7782
108
+ emps[0]['job'].should == 'ANALYST'
109
+ emps[0].age.should == 48
110
+ end
111
+
112
+ it 'DATA: update all' do
113
+ Dept.update_all('age = 20', ['deptno >= ?', 20])
114
+
115
+ Dept.find(:all).each do |dept|
116
+ if dept.deptno >= 20
117
+ dept.age.should == 20
118
+ end
119
+ end
120
+ end
121
+
122
+ it 'EMP: destroy' do
123
+ emp = Emp.find(:first, :conditions => ['empno = 7566'])
124
+ emp.destroy
125
+
126
+ emps = Emp.find(:all, :order => 'empno')
127
+ expected = Emp::DATA.select {|i| i['empno'] != 7566 }
128
+ emps.length.should == expected.length
129
+
130
+ emps.each_with_index do |emp, i|
131
+ emp.should == expected[i]
132
+ emp.empno.should_not == 7566
133
+ end
134
+ end
135
+
136
+ it 'EMP: destroy all' do
137
+ Emp.destroy_all(['job = ?', 'SALESMAN'])
138
+
139
+ emps = Emp.find(:all, :order => 'empno')
140
+ expected = Emp::DATA.select {|i| i['job'] != 'SALESMAN' }
141
+ emps.length.should == expected.length
142
+
143
+ emps.each_with_index do |emp, i|
144
+ emp.should == expected[i]
145
+ emp.job.should_not == 'SALESMAN'
146
+ end
147
+ end
148
+
149
+ it 'DEPT: delete all' do
150
+ Dept.delete_all(['deptno > 20'])
151
+
152
+ depts = Dept.find(:all, :order => 'deptno')
153
+ expected = Dept::DATA.select {|i| not i['deptno'] > 20 }
154
+ depts.length.should == expected.length
155
+
156
+ depts.each_with_index do |dept, i|
157
+ dept.should == expected[i]
158
+ dept.deptno.should_not > 20
159
+ end
160
+ end
161
+
162
+ it 'EMP: new' do
163
+ emp1 = Emp.new
164
+ emp1.empno = 1
165
+ emp1.foo = 'bar'
166
+ emp1.zoo = 'baz'
167
+ emp1.save.should be_true
168
+
169
+ emp2 = Emp.new
170
+ emp2.empno = 2
171
+ emp2.hoge = 'fuga'
172
+ emp2.hogera = 'hogehoge'
173
+ emp2.save!
174
+
175
+ emps = Emp.find(:all, :order => 'empno')
176
+ emps.length.should == Emp::DATA.length + 2
177
+
178
+ emps.each_with_index do |emp, i|
179
+ case emp.empno
180
+ when 1
181
+ emp = emp.attributes
182
+ emp.delete('id').should_not be_nil
183
+ emp.delete('_id').should_not be_nil
184
+ emp.should == { 'empno' => 1, 'foo' => 'bar', 'zoo' => 'baz' }
185
+ when 2
186
+ emp = emp.attributes
187
+ emp.delete('id').should_not be_nil
188
+ emp.delete('_id').should_not be_nil
189
+ emp.should == { 'empno' => 2, 'hoge' => 'fuga', 'hogera' => 'hogehoge' }
190
+ else
191
+ emp.should == Emp::DATA[i - 2]
192
+ end
193
+ end
194
+ end
195
+
196
+ it 'DEPT: create' do
197
+ Dept.create(
198
+ :deptno => 1,
199
+ :foo => 'bar',
200
+ :zoo => 'baz'
201
+ ).should be_true
202
+
203
+ Dept.create!(
204
+ :deptno => 2,
205
+ :hoge => 'fuga',
206
+ :hogera => 'hogehoge'
207
+ )
208
+
209
+ depts = Dept.find(:all, :order => 'deptno')
210
+ depts.length.should == Dept::DATA.length + 2
211
+
212
+ depts.each_with_index do |dept, i|
213
+ case dept.deptno
214
+ when 1
215
+ dept = dept.attributes
216
+ dept.delete('id').should_not be_nil
217
+ dept.delete('_id').should_not be_nil
218
+ dept.should == { 'deptno' => 1, 'foo' => 'bar', 'zoo' => 'baz' }
219
+ when 2
220
+ dept = dept.attributes
221
+ dept.delete('id').should_not be_nil
222
+ dept.delete('_id').should_not be_nil
223
+ dept.should == { 'deptno' => 2, 'hoge' => 'fuga', 'hogera' => 'hogehoge' }
224
+ else
225
+ dept.should == Dept::DATA[i - 2]
226
+ end
227
+ end
228
+ end
229
+
230
+ it 'EMP: not' do
231
+ emps = Emp.find(:all, :conditions => ['not empno = 7566'], :order => 'empno')
232
+ expected = Emp::DATA.select {|i| i['empno'] != 7566 }
233
+ emps.length.should == expected.length
234
+
235
+ emps.each_with_index do |emp, i|
236
+ emp.should == expected[i]
237
+ emp.empno.should_not == 7566
238
+ end
239
+ end
240
+
241
+ it 'EMP: not ne' do
242
+ emps = Emp.find(:all, :conditions => ['not empno <> 7566'], :order => 'empno')
243
+ expected = Emp::DATA.select {|i| i['empno'] == 7566 }
244
+ emps.length.should == expected.length
245
+
246
+ emps.each_with_index do |emp, i|
247
+ emp.should == expected[i]
248
+ emp.empno.should == 7566
249
+ end
250
+ end
251
+
252
+ it 'EMP: regexp' do
253
+ emps = Emp.find(:all, :conditions => ['job regexp ?', 'LE'], :order => 'empno')
254
+ expected = Emp::DATA.select {|i| i['job'] =~ /LE/ }
255
+ emps.length.should == expected.length
256
+
257
+ emps.each_with_index do |emp, i|
258
+ emp.should == expected[i]
259
+ end
260
+ end
261
+
262
+ it 'EMP: not regexp' do
263
+ emps = Emp.find(:all, :conditions => ['not job regexp ?', 'LE'], :order => 'empno')
264
+ expected = Emp::DATA.select {|i| i['job'] !~ /LE/ }
265
+ emps.length.should == expected.length
266
+
267
+ emps.each_with_index do |emp, i|
268
+ emp.should == expected[i]
269
+ end
270
+ end
271
+
272
+ it 'EMP: find limit offset' do
273
+ emps = Emp.find(:all, :limit => 3, :offset => 5, :order => 'empno')
274
+ expected = Emp::DATA.slice(5..7)
275
+ emps.length.should == expected.length
276
+
277
+ emps.each_with_index do |emp, i|
278
+ emp.should == expected[i]
279
+ end
280
+ end
281
+
282
+ it 'DEPT: find conds' do
283
+ depts = Dept.find(:all, :conditions => ['deptno >= ? and deptno < ?', 20, 40], :order => 'deptno')
284
+ expected = Dept::DATA.select {|i| i['deptno'] >= 20 and i['deptno'] < 40 }
285
+ depts.length.should == expected.length
286
+
287
+ depts.each_with_index do |dept, i|
288
+ dept.should == expected[i]
289
+ end
290
+ end
291
+
292
+ it 'DEPT: find between' do
293
+ depts = Dept.find(:all, :conditions => ['deptno between ? and ?', 20, 40], :order => 'deptno')
294
+ expected = Dept::DATA.select {|i| 20 <= i['deptno'] and i['deptno'] <= 40 }
295
+ depts.length.should == expected.length
296
+
297
+ depts.each_with_index do |dept, i|
298
+ dept.should == expected[i]
299
+ end
300
+ end
301
+
302
+ it 'EMP: find distinct' do
303
+ emps = Emp.find(:all, :select => 'distinct job').sort_by {|i| i['job'] }
304
+ expected = Emp::DATA.map {|i| i['job'] }.sort.uniq
305
+ emps.length.should == expected.length
306
+
307
+ emps.each_with_index do |emp, i|
308
+ emp.job.should == expected[i]
309
+ end
310
+ end
311
+
312
+ it 'EMP: collection' do
313
+ actual = {}
314
+ coll = Emp.collection
315
+
316
+ m =<<-EOS
317
+ function() {
318
+ emit(this.job, 1);
319
+ }
320
+ EOS
321
+
322
+ r =<<-EOS
323
+ function(k, vals) {
324
+ var sum = 0;
325
+
326
+ for(var i in vals) {
327
+ sum += vals[i];
328
+ }
329
+
330
+ return sum;
331
+ }
332
+ EOS
333
+
334
+ coll.map_reduce(m, r).find.each do |i|
335
+ actual[i['_id']] = i['value'].to_i
336
+ end
337
+
338
+ actual.should == {
339
+ 'ANALYST' => 2,
340
+ 'CLERK' => 4,
341
+ 'MANAGER' => 3,
342
+ 'PRESIDENT' => 1,
343
+ 'SALESMAN' => 4
344
+ }
345
+ end
346
+
347
+ it 'EMP: collection with block' do
348
+ actual = {}
349
+
350
+ Emp.collection do |coll|
351
+ m =<<-EOS
352
+ function() {
353
+ emit(this.job, 1);
354
+ }
355
+ EOS
356
+
357
+ r =<<-EOS
358
+ function(k, vals) {
359
+ var sum = 0;
360
+
361
+ for(var i in vals) {
362
+ sum += vals[i];
363
+ }
364
+
365
+ return sum;
366
+ }
367
+ EOS
368
+
369
+ coll.map_reduce(m, r).find.each do |i|
370
+ actual[i['_id']] = i['value'].to_i
371
+ end
372
+ end
373
+
374
+ actual.should == {
375
+ 'ANALYST' => 2,
376
+ 'CLERK' => 4,
377
+ 'MANAGER' => 3,
378
+ 'PRESIDENT' => 1,
379
+ 'SALESMAN' => 4
380
+ }
381
+ end
382
+
383
+ it 'EMP: in' do
384
+ # String
385
+ emps = Emp.find(:all, :conditions => ['job in (?)', ['SALESMAN', 'MANAGER']], :order => 'empno')
386
+ expected = Emp::DATA.select {|i| ['SALESMAN', 'MANAGER'].include?(i['job']) }
387
+ emps.length.should == expected.length
388
+
389
+ emps.each_with_index do |emp, i|
390
+ emp.should == expected[i]
391
+ end
392
+
393
+ # Hash
394
+ emps = Emp.find(:all, :conditions => {:job => ['SALESMAN', 'MANAGER']}, :order => 'empno')
395
+ expected = Emp::DATA.select {|i| ['SALESMAN', 'MANAGER'].include?(i['job']) }
396
+ emps.length.should == expected.length
397
+
398
+ emps.each_with_index do |emp, i|
399
+ emp.should == expected[i]
400
+ end
401
+ end
402
+
403
+ it 'EMP: not in' do
404
+ emps = Emp.find(:all, :conditions => ['job not in (?)', ['SALESMAN', 'MANAGER']], :order => 'empno')
405
+ expected = Emp::DATA.select {|i| not ['SALESMAN', 'MANAGER'].include?(i['job']) }
406
+ emps.length.should == expected.length
407
+
408
+ emps.each_with_index do |emp, i|
409
+ emp.should == expected[i]
410
+ end
411
+ end
412
+
413
+ it 'EMP: mod' do
414
+ emps = Emp.find(:all, :conditions => ['empno mod (?)', [2, 0]], :order => 'empno')
415
+ expected = Emp::DATA.select {|i| (i['empno'] % 2) == 0 }
416
+ emps.length.should == expected.length
417
+
418
+ emps.each_with_index do |emp, i|
419
+ emp.should == expected[i]
420
+ end
421
+ end
422
+
423
+ it 'EMP: not mod' do
424
+ emps = Emp.find(:all, :conditions => ['not empno mod (?)', [2, 0]], :order => 'empno')
425
+ expected = Emp::DATA.select {|i| (i['empno'] % 2) != 0 }
426
+ emps.length.should == expected.length
427
+
428
+ emps.each_with_index do |emp, i|
429
+ emp.should == expected[i]
430
+ end
431
+ end
432
+
433
+ it 'DEPT: exists true' do
434
+ Dept.create(
435
+ :deptno => 1,
436
+ :foo => 'bar',
437
+ :zoo => 'baz'
438
+ ).should be_true
439
+
440
+ Dept.create!(
441
+ :deptno => 2,
442
+ :hoge => 'fuga',
443
+ :hogera => 'hogehoge'
444
+ )
445
+
446
+ depts = Dept.find(:all, :conditions => ['foo exists ?', true])
447
+ depts.length.should == 1
448
+ depts[0].deptno.should == 1
449
+ end
450
+
451
+ it 'DEPT: exists false' do
452
+ Dept.create(
453
+ :deptno => 1,
454
+ :foo => 'bar',
455
+ :zoo => 'baz'
456
+ ).should be_true
457
+
458
+ Dept.create!(
459
+ :deptno => 2,
460
+ :hoge => 'fuga',
461
+ :hogera => 'hogehoge'
462
+ )
463
+
464
+ depts = Dept.find(:all, :conditions => ['foo exists ?', false], :order => 'deptno')
465
+ depts.length.should == Dept::DATA.length + 1
466
+ depts.map {|i| i['deptno'] }.should == [2] + Dept::DATA.map {|i| i['deptno'] }
467
+ end
468
+
469
+ it 'DEPT: not exists' do
470
+ Dept.create(
471
+ :deptno => 1,
472
+ :foo => 'bar',
473
+ :zoo => 'baz'
474
+ ).should be_true
475
+
476
+ Dept.create!(
477
+ :deptno => 2,
478
+ :hoge => 'fuga',
479
+ :hogera => 'hogehoge'
480
+ )
481
+
482
+ depts = Dept.find(:all, :conditions => ['not foo exists ?', true], :order => 'deptno')
483
+ depts.length.should == Dept::DATA.length + 1
484
+ depts.map {|i| i['deptno'] }.should == [2] + Dept::DATA.map {|i| i['deptno'] }
485
+ end
486
+
487
+ it 'examples' do
488
+ emp = Emp.find(:first,
489
+ :conditions => ["job = ? and sal >= ?", "MANAGER", 2800],
490
+ :order => 'sal desc', :limit => 3, :offset => 1)
491
+
492
+ p emp.id #=> 4bb795e8f15d3d0324000006
493
+ emp.age = 30
494
+ emp.save
495
+
496
+ emp_list = Emp.find(:all, :conditions => {:empno => [7654, 7698, 7782]})
497
+
498
+ emp_list.each do |i|
499
+ i.destroy if i.sal < 2000
500
+ end
501
+
502
+ new_emp = Emp.new
503
+ new_emp.empno = 8000
504
+ new_emp.ename = 'YAMADA'
505
+ new_emp.age = 27
506
+ new_emp.save!
507
+ end
508
+
509
+ after do
510
+ Emp.teardown
511
+ Dept.teardown
512
+ end
513
+ end
514
+
515
+ # model #######################################################################
516
+
517
+ class Emp < ActiveRecord::Base
518
+ include ActiveMongo::Collection
519
+
520
+ NAMES = %w(empno ename job mgr hiredate sal comm deptno)
521
+
522
+ DATA = [
523
+ [7369, 'SMITH' , 'CLERK' , 7902, '17-DEC-1980', 800.0, nil, 20],
524
+ [7499, 'ALLEN' , 'SALESMAN' , 7698, '20-FEB-1981', 1600.0, 300.0, 30],
525
+ [7521, 'WARD' , 'SALESMAN' , 7698, '22-FEB-1981', 1250.0, 500.0, 30],
526
+ [7566, 'JONES' , 'MANAGER' , 7839, '2-APR-1981' , 2975.0, nil, 20],
527
+ [7654, 'MARTIN' , 'SALESMAN' , 7698, '28-SEP-1981', 1250.1, 1400.0, 30],
528
+ [7698, 'BLAKE' , 'MANAGER' , 7839, '1-MAY-1981' , 2850.0, nil, 30],
529
+ [7782, 'CLARK' , 'MANAGER' , 7839, '9-JUN-1981' , 2450.0, nil, 10],
530
+ [7788, 'SCOTT' , 'ANALYST' , 7566, '09-DEC-1982', 3000.0, nil, 20],
531
+ [7839, 'KING' , 'PRESIDENT' , nil, '17-NOV-1981', 5000.0, nil, 10],
532
+ [7844, 'TURNER' , 'SALESMAN' , 7698, '8-SEP-1981' , 1500.0, 0.0, 30],
533
+ [7876, 'ADAMS' , 'CLERK' , 7788, '12-JAN-1983', 1100.0, nil, 20],
534
+ [7900, 'JAMES' , 'CLERK' , 7698, '3-DEC-1981' , 950.0, nil, 30],
535
+ [7902, 'FORD' , 'ANALYST' , 7566, '3-DEC-1981' , 3000.0, nil, 20],
536
+ [7934, 'MILLER' , 'CLERK' , 7782, '23-JAN-1982', 1300.0, nil, 10],
537
+ ].map {|i| Hash[*NAMES.zip(i).flatten] }
538
+
539
+ def self.setup
540
+ db = connection.raw_connection
541
+ coll = db.collection(table_name)
542
+ DATA.each {|doc| coll.insert(doc) }
543
+ end
544
+
545
+ def self.teardown
546
+ db = connection.raw_connection
547
+ db.drop_collection(table_name)
548
+ end
549
+
550
+ def ==(obj)
551
+ NAMES.all? do |name|
552
+ self.send(name) == obj[name] and self[name] == obj[name]
553
+ end
554
+ end
555
+ end
556
+
557
+ class Dept < ActiveRecord::Base
558
+ include ActiveMongo::Collection
559
+
560
+ NAMES = %w(deptno dname loc)
561
+
562
+ DATA = [
563
+ [10, 'ACCOUNTING', 'NEW YORK'],
564
+ [20, 'RESEARCH' , 'DALLAS' ],
565
+ [30, 'SALES' , 'CHICAGO' ],
566
+ [40, 'OPERATIONS', 'BOSTON' ],
567
+ ].map {|i| Hash[*NAMES.zip(i).flatten] }
568
+
569
+ def self.setup
570
+ db = connection.raw_connection
571
+ coll = db.collection(table_name)
572
+ DATA.each {|doc| coll.insert(doc) }
573
+ end
574
+
575
+ def self.teardown
576
+ db = connection.raw_connection
577
+ db.drop_collection(table_name)
578
+ end
579
+
580
+ def ==(obj)
581
+ NAMES.all? do |name|
582
+ self.send(name) == obj[name] and self[name] == obj[name]
583
+ end
584
+ end
585
+ end