jchris-couchrest 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/pager.rb ADDED
@@ -0,0 +1,89 @@
1
+ # paginate though 'gcharts/mp3-trk-dom-map' view and save
2
+
3
+ # get 1000 records
4
+ # truncate so that the key of the last record is not included in the page
5
+ # that key will be the first of the next page
6
+ # (if the last key equals the first key, up the page size)
7
+ # group the results by key
8
+ # yield the group
9
+
10
+ require File.dirname(__FILE__) + '/couchrest'
11
+
12
+ module Enumerable
13
+ def group_by
14
+ inject({}) do |grouped, element|
15
+ (grouped[yield(element)] ||= []) << element
16
+ grouped
17
+ end
18
+ end unless [].respond_to?(:group_by)
19
+ end
20
+
21
+ class CouchRest
22
+ class Pager
23
+ attr_accessor :db
24
+ def initialize db
25
+ @db = db
26
+ end
27
+
28
+ def key_reduce(view, count, firstkey = nil, lastkey = nil, &block)
29
+ # start with no keys
30
+ startkey = firstkey
31
+ # lastprocessedkey = nil
32
+ keepgoing = true
33
+
34
+ while keepgoing && viewrows = request_view(view, count, startkey)
35
+ startkey = viewrows.first['key']
36
+ endkey = viewrows.last['key']
37
+
38
+ if (startkey == endkey)
39
+ # we need to rerequest to get a bigger page
40
+ # so we know we have all the rows for that key
41
+ viewrows = @db.view(view, :key => startkey)['rows']
42
+ # we need to do an offset thing to find the next startkey
43
+ # otherwise we just get stuck
44
+ lastdocid = viewrows.last['id']
45
+ fornextloop = @db.view(view, :startkey => startkey, :startkey_docid => lastdocid, :count => 2)['rows']
46
+
47
+ newendkey = fornextloop.last['key']
48
+ if (newendkey == endkey)
49
+ keepgoing = false
50
+ else
51
+ startkey = newendkey
52
+ end
53
+ rows = viewrows
54
+ else
55
+ rows = []
56
+ for r in viewrows
57
+ if (lastkey && r['key'] == lastkey)
58
+ keepgoing = false
59
+ break
60
+ end
61
+ break if (r['key'] == endkey)
62
+ rows << r
63
+ end
64
+ startkey = endkey
65
+ end
66
+
67
+ grouped = rows.group_by{|r|r['key']}
68
+ grouped.each do |k, rs|
69
+ vs = rs.collect{|r|r['value']}
70
+ yield(k,vs)
71
+ end
72
+
73
+ # lastprocessedkey = rows.last['key']
74
+ end
75
+ end
76
+
77
+ def request_view view, count = nil, startkey = nil, endkey = nil
78
+ opts = {}
79
+ opts[:count] = count if count
80
+ opts[:startkey] = startkey if startkey
81
+ opts[:endkey] = endkey if endkey
82
+
83
+ results = @db.view(view, opts)
84
+ rows = results['rows']
85
+ rows unless rows.length == 0
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,94 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe CouchRest::Pager do
4
+ before(:all) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ begin
7
+ @cr.database(TESTDB).delete!
8
+ rescue RestClient::Request::RequestFailed
9
+ end
10
+ begin
11
+ @db = @cr.create_db(TESTDB)
12
+ rescue RestClient::Request::RequestFailed
13
+ end
14
+ @pager = CouchRest::Pager.new(@db)
15
+ end
16
+
17
+ after(:all) do
18
+ begin
19
+ @db.delete!
20
+ rescue RestClient::Request::RequestFailed
21
+ end
22
+ end
23
+
24
+ it "should store the db" do
25
+ @pager.db.should == @db
26
+ end
27
+
28
+ describe "Pager with a view and docs" do
29
+ before(:all) do
30
+ @docs = []
31
+ 100.times do |i|
32
+ @docs << ({:number => (i % 10)})
33
+ end
34
+ @db.bulk_save(@docs)
35
+ @db.save({
36
+ '_id' => '_design/magic',
37
+ 'views' => {
38
+ 'number' => {
39
+ 'map' => 'function(doc){emit(doc.number,null)}'
40
+ }
41
+ }
42
+ })
43
+ end
44
+
45
+ it "should have docs" do
46
+ @docs.length.should == 100
47
+ @db.documents['rows'].length.should == 101
48
+ end
49
+
50
+ it "should have a view" do
51
+ @db.view('magic/number', :count => 10)['rows'][0]['key'].should == 0
52
+ end
53
+
54
+ it "should yield once per key" do
55
+ results = {}
56
+ @pager.key_reduce('magic/number', 20) do |k,vs|
57
+ results[k] = vs.length
58
+ end
59
+ results[0].should == 10
60
+ results[3].should == 10
61
+ end
62
+
63
+ it "with a small step size should yield once per key" do
64
+ results = {}
65
+ @pager.key_reduce('magic/number', 7) do |k,vs|
66
+ results[k] = vs.length
67
+ end
68
+ results[0].should == 10
69
+ results[3].should == 10
70
+ results[9].should == 10
71
+ end
72
+ it "with a large step size should yield once per key" do
73
+ results = {}
74
+ @pager.key_reduce('magic/number', 1000) do |k,vs|
75
+ results[k] = vs.length
76
+ end
77
+ results[0].should == 10
78
+ results[3].should == 10
79
+ results[9].should == 10
80
+ end
81
+ it "with a begin and end should only yield in the range (and leave out the lastkey)" do
82
+ results = {}
83
+ @pager.key_reduce('magic/number', 1000, 4, 7) do |k,vs|
84
+ results[k] = vs.length
85
+ end
86
+ results[0].should be_nil
87
+ results[4].should == 10
88
+ results[6].should == 10
89
+ results[7].should be_nil
90
+ results[8].should be_nil
91
+ results[9].should be_nil
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/../lib/couchrest'
2
+
3
+ COUCHHOST = "http://localhost:5985"
4
+ TESTDB = 'couchrest-test'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jchris-couchrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - J. Chris Anderson
@@ -41,12 +41,15 @@ extra_rdoc_files: []
41
41
  files:
42
42
  - lib/couchrest.rb
43
43
  - lib/database.rb
44
+ - lib/pager.rb
44
45
  - Rakefile
45
46
  - README
46
47
  - script/couchdir
47
48
  - script/couchview
48
49
  - spec/couchrest_spec.rb
49
50
  - spec/database_spec.rb
51
+ - spec/pager_spec.rb
52
+ - spec/spec_helper.rb
50
53
  has_rdoc: false
51
54
  homepage: http://github.com/jchris/couchrest
52
55
  post_install_message: