jchris-couchrest 0.8.0 → 0.8.1

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