dpla-couchrest 1.2.1.pre.dpla

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +176 -0
  6. data/README.md +66 -0
  7. data/Rakefile +23 -0
  8. data/THANKS.md +21 -0
  9. data/VERSION +1 -0
  10. data/couchrest.gemspec +36 -0
  11. data/examples/word_count/markov +38 -0
  12. data/examples/word_count/views/books/chunked-map.js +3 -0
  13. data/examples/word_count/views/books/united-map.js +1 -0
  14. data/examples/word_count/views/markov/chain-map.js +6 -0
  15. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  16. data/examples/word_count/views/word_count/count-map.js +6 -0
  17. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  18. data/examples/word_count/word_count.rb +46 -0
  19. data/examples/word_count/word_count_query.rb +40 -0
  20. data/examples/word_count/word_count_views.rb +26 -0
  21. data/history.txt +214 -0
  22. data/init.rb +1 -0
  23. data/lib/couchrest.rb +146 -0
  24. data/lib/couchrest/attributes.rb +89 -0
  25. data/lib/couchrest/commands/generate.rb +71 -0
  26. data/lib/couchrest/commands/push.rb +103 -0
  27. data/lib/couchrest/database.rb +402 -0
  28. data/lib/couchrest/design.rb +91 -0
  29. data/lib/couchrest/document.rb +105 -0
  30. data/lib/couchrest/helper/attachments.rb +29 -0
  31. data/lib/couchrest/helper/pager.rb +103 -0
  32. data/lib/couchrest/helper/streamer.rb +60 -0
  33. data/lib/couchrest/helper/upgrade.rb +51 -0
  34. data/lib/couchrest/middlewares/logger.rb +263 -0
  35. data/lib/couchrest/monkeypatches.rb +25 -0
  36. data/lib/couchrest/rest_api.rb +166 -0
  37. data/lib/couchrest/server.rb +92 -0
  38. data/lib/couchrest/support/inheritable_attributes.rb +107 -0
  39. data/spec/.gitignore +1 -0
  40. data/spec/couchrest/couchrest_spec.rb +197 -0
  41. data/spec/couchrest/database_spec.rb +914 -0
  42. data/spec/couchrest/design_spec.rb +206 -0
  43. data/spec/couchrest/document_spec.rb +400 -0
  44. data/spec/couchrest/helpers/pager_spec.rb +115 -0
  45. data/spec/couchrest/helpers/streamer_spec.rb +134 -0
  46. data/spec/couchrest/rest_api_spec.rb +241 -0
  47. data/spec/couchrest/server_spec.rb +35 -0
  48. data/spec/fixtures/attachments/README +3 -0
  49. data/spec/fixtures/attachments/couchdb.png +0 -0
  50. data/spec/fixtures/attachments/test.html +11 -0
  51. data/spec/fixtures/views/lib.js +3 -0
  52. data/spec/fixtures/views/test_view/lib.js +3 -0
  53. data/spec/fixtures/views/test_view/only-map.js +4 -0
  54. data/spec/fixtures/views/test_view/test-map.js +3 -0
  55. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  56. data/spec/spec.opts +5 -0
  57. data/spec/spec_helper.rb +46 -0
  58. data/utils/remap.rb +27 -0
  59. data/utils/subset.rb +30 -0
  60. metadata +212 -0
@@ -0,0 +1,115 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Pager do
4
+ before(:all) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ @pager = CouchRest::Pager.new(@db)
10
+ @docs = []
11
+ 100.times do |i|
12
+ @docs << ({:number => (i % 10)})
13
+ end
14
+ @db.bulk_save(@docs)
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 "paging all docs" do
29
+ it "should yield total_docs / limit times" do
30
+ n = 0
31
+ @pager.all_docs(10) do |doc|
32
+ n += 1
33
+ end
34
+ n.should == 10
35
+ end
36
+ it "should yield each docrow group without duplicate docs" do
37
+ docids = {}
38
+ @pager.all_docs(10) do |docrows|
39
+ docrows.each do |row|
40
+ docids[row['id']].should be_nil
41
+ docids[row['id']] = true
42
+ end
43
+ end
44
+ docids.keys.length.should == 100
45
+ end
46
+ it "should yield each docrow group" do
47
+ @pager.all_docs(10) do |docrows|
48
+ doc = @db.get(docrows[0]['id'])
49
+ doc['number'].class.should == Fixnum
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "Pager with a view and docs" do
55
+ before(:all) do
56
+ @db.save_doc({
57
+ '_id' => '_design/magic',
58
+ 'views' => {
59
+ 'number' => {
60
+ 'map' => 'function(doc){emit(doc.number,null)}'
61
+ }
62
+ }
63
+ })
64
+ end
65
+
66
+ it "should have docs" do
67
+ @docs.length.should == 100
68
+ @db.documents['rows'].length.should == 101
69
+ end
70
+
71
+ it "should have a view" do
72
+ @db.view('magic/number', :limit => 10)['rows'][0]['key'].should == 0
73
+ end
74
+
75
+ it "should yield once per key" do
76
+ results = {}
77
+ @pager.key_reduce('magic/number', 20) do |k,vs|
78
+ results[k] = vs.length
79
+ end
80
+ results[0].should == 10
81
+ results[3].should == 10
82
+ end
83
+
84
+ it "with a small step size should yield once per key" do
85
+ results = {}
86
+ @pager.key_reduce('magic/number', 7) do |k,vs|
87
+ results[k] = vs.length
88
+ end
89
+ results[0].should == 10
90
+ results[3].should == 10
91
+ results[9].should == 10
92
+ end
93
+ it "with a large step size should yield once per key" do
94
+ results = {}
95
+ @pager.key_reduce('magic/number', 1000) do |k,vs|
96
+ results[k] = vs.length
97
+ end
98
+ results[0].should == 10
99
+ results[3].should == 10
100
+ results[9].should == 10
101
+ end
102
+ it "with a begin and end should only yield in the range (and leave out the lastkey)" do
103
+ results = {}
104
+ @pager.key_reduce('magic/number', 1000, 4, 7) do |k,vs|
105
+ results[k] = vs.length
106
+ end
107
+ results[0].should be_nil
108
+ results[4].should == 10
109
+ results[6].should == 10
110
+ results[7].should be_nil
111
+ results[8].should be_nil
112
+ results[9].should be_nil
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,134 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Streamer do
4
+ before(:all) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ @streamer = CouchRest::Streamer.new()
10
+ @docs = (1..1000).collect{|i| {:integer => i, :string => i.to_s}}
11
+ @db.bulk_save(@docs)
12
+ @db.save_doc({
13
+ "_id" => "_design/first",
14
+ :views => {
15
+ :test => {
16
+ :map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"
17
+ }
18
+ }
19
+ })
20
+ end
21
+
22
+ it "should raise error on #view as deprecated" do
23
+ lambda { @streamer.view }.should raise_error(/deprecated/)
24
+ end
25
+
26
+ it "should GET each row in a view" do
27
+ count = 0
28
+ header = @streamer.get("#{@db.root}/_all_docs") do |row|
29
+ count += 1
30
+ end
31
+ count.should == 1001
32
+ header.should == {"total_rows" => 1001, "offset" => 0}
33
+ end
34
+
35
+ it "should GET each row in a view with params" do
36
+ count = 0
37
+ header = @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=5") do |row|
38
+ count += 1
39
+ end
40
+ count.should == 5
41
+ header.should == {"total_rows" => 1001, "offset" => 0}
42
+ end
43
+
44
+ it "should GET no rows in a view with limit=0" do
45
+ count = 0
46
+ header = @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
47
+ count += 1
48
+ end
49
+ count.should == 0
50
+ header.should == {"total_rows" => 1001, "offset" => 0}
51
+ end
52
+
53
+ it "should raise an exception if it receives malformed data" do
54
+ IO.stub(:popen) do |cmd, block|
55
+ class F
56
+ def initialize
57
+ @lines = [
58
+ '{"total_rows": 123, "offset": "0", "rows": [',
59
+ '{"foo": 1},',
60
+ '{"foo": 2},',
61
+ ]
62
+ end
63
+
64
+ def gets
65
+ @lines.shift
66
+ end
67
+ end
68
+
69
+ f = F.new
70
+ block.call f
71
+
72
+ IO.unstub(:popen)
73
+ IO.popen 'true' do; end
74
+ end
75
+
76
+ count = 0
77
+ expect do
78
+ @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
79
+ count += 1
80
+ end
81
+ end.should raise_error(MultiJson::DecodeError)
82
+ end
83
+
84
+ it "should raise an exception if the couch connection fails" do
85
+ IO.stub(:popen) do |cmd, block|
86
+ class F
87
+ def initialize
88
+ @lines = [
89
+ '{"total_rows": 123, "offset": "0", "rows": [',
90
+ '{"foo": 1},',
91
+ '{"foo": 2},',
92
+ ]
93
+ end
94
+
95
+ def gets
96
+ @lines.shift
97
+ end
98
+ end
99
+
100
+ block.call F.new
101
+
102
+ IO.unstub(:popen)
103
+ IO.popen 'false' do; end
104
+ end
105
+
106
+ count = 0
107
+
108
+ expect do
109
+ @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
110
+ count += 1
111
+ end
112
+ end.should raise_error(RestClient::ServerBrokeConnection)
113
+
114
+ count.should == 2
115
+ end
116
+
117
+ it "should POST for each row in a view" do
118
+ # First grab a pair of IDs
119
+ ids = []
120
+ @streamer.get("#{@db.root}/_design/first/_view/test?limit=2") do |row|
121
+ ids << row['id']
122
+ end
123
+ count = 0
124
+ @streamer.post("#{@db.root}/_all_docs?include_docs=true", :keys => ids) do |row|
125
+ count += 1
126
+ end
127
+ count.should == 2
128
+ end
129
+
130
+ it "should escape quotes" do
131
+ @streamer.send(:escape_quotes, "keys: [\"sams's test\"]").should eql("keys: [\\\"sams's test\\\"]")
132
+ end
133
+
134
+ end
@@ -0,0 +1,241 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::RestAPI do
4
+
5
+ describe "class methods" do
6
+
7
+ subject { CouchRest }
8
+
9
+ let(:request) { RestClient::Request }
10
+ let(:simple_response) { "{\"ok\":true}" }
11
+ let(:parser) { MultiJson }
12
+ let(:parser_opts) { {:max_nesting => false} }
13
+
14
+ it "should exist" do
15
+ should respond_to :get
16
+ should respond_to :put
17
+ should respond_to :post
18
+ should respond_to :copy
19
+ should respond_to :delete
20
+ should respond_to :head
21
+ end
22
+
23
+ it "should provide default headers" do
24
+ should respond_to :default_headers
25
+ CouchRest.default_headers.should be_a(Hash)
26
+ end
27
+
28
+
29
+ describe :get do
30
+ it "should send basic request" do
31
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
32
+ request.should_receive(:execute).with(req).and_return(simple_response)
33
+ parser.should_receive(:decode).with(simple_response, parser_opts)
34
+ CouchRest.get('foo')
35
+ end
36
+
37
+ it "should never modify options" do
38
+ options = {:timeout => 1000}
39
+ options.freeze
40
+ request.should_receive(:execute).and_return(simple_response)
41
+ parser.should_receive(:decode)
42
+ expect { CouchRest.get('foo', options) }.to_not raise_error
43
+ end
44
+
45
+
46
+ it "should accept 'content_type' header" do
47
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers.merge(:content_type => :foo)}
48
+ request.should_receive(:execute).with(req).and_return(simple_response)
49
+ parser.should_receive(:decode).with(simple_response, parser_opts)
50
+ CouchRest.get('foo', :content_type => :foo)
51
+ end
52
+
53
+ it "should accept 'accept' header" do
54
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers.merge(:accept => :foo)}
55
+ request.should_receive(:execute).with(req).and_return(simple_response)
56
+ parser.should_receive(:decode).with(simple_response, parser_opts)
57
+ CouchRest.get('foo', :accept => :foo)
58
+ end
59
+
60
+ it "should forward RestClient options" do
61
+ req = {:url => 'foo', :method => :get, :timeout => 1000, :headers => CouchRest.default_headers}
62
+ request.should_receive(:execute).with(req).and_return(simple_response)
63
+ parser.should_receive(:decode).with(simple_response, parser_opts)
64
+ CouchRest.get('foo', :timeout => 1000)
65
+ end
66
+
67
+ it "should forward parser options" do
68
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
69
+ request.should_receive(:execute).with(req).and_return(simple_response)
70
+ parser.should_receive(:decode).with(simple_response, parser_opts.merge(:random => 'foo'))
71
+ CouchRest.get('foo', :random => 'foo')
72
+ end
73
+
74
+ it "should accept raw option" do
75
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
76
+ request.should_receive(:execute).with(req).and_return(simple_response)
77
+ parser.should_not_receive(:decode)
78
+ CouchRest.get('foo', :raw => true).should eql(simple_response)
79
+ end
80
+
81
+ it "should allow override of method (not that you'd want to!)" do
82
+ req = {:url => 'foo', :method => :fubar, :headers => CouchRest.default_headers}
83
+ request.should_receive(:execute).with(req).and_return(simple_response)
84
+ parser.should_receive(:decode).with(simple_response, parser_opts)
85
+ CouchRest.get('foo', :method => :fubar)
86
+ end
87
+
88
+ it "should allow override of url (not that you'd want to!)" do
89
+ req = {:url => 'foobardom', :method => :get, :headers => CouchRest.default_headers}
90
+ request.should_receive(:execute).with(req).and_return(simple_response)
91
+ parser.should_receive(:decode).with(simple_response, parser_opts)
92
+ CouchRest.get('foo', :url => 'foobardom')
93
+ end
94
+
95
+
96
+ it "should forward an exception if raised" do
97
+ request.should_receive(:execute).and_raise(RestClient::Exception)
98
+ expect { CouchRest.get('foo') }.to raise_error(RestClient::Exception)
99
+ end
100
+
101
+ context 'when decode_json_objects is true' do
102
+ class TestObject
103
+ def self.json_create(args)
104
+ new
105
+ end
106
+ end
107
+
108
+ before(:each) do
109
+ CouchRest.decode_json_objects = true
110
+ end
111
+
112
+ after(:each) do
113
+ CouchRest.decode_json_objects = false
114
+ end
115
+
116
+ it 'should return the response as a Ruby object' do
117
+ CouchRest.put "#{COUCHHOST}/#{TESTDB}/test", JSON.create_id => TestObject.to_s
118
+
119
+ CouchRest.get("#{COUCHHOST}/#{TESTDB}/test").class.should eql(TestObject)
120
+ end
121
+ end
122
+ end
123
+
124
+ describe :post do
125
+ it "should send basic request" do
126
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
127
+ request.should_receive(:execute).with(req).and_return(simple_response)
128
+ parser.should_receive(:encode).with('data').and_return('data')
129
+ parser.should_receive(:decode).with(simple_response, parser_opts)
130
+ CouchRest.post('foo', 'data')
131
+ end
132
+
133
+ it "should send basic request" do
134
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
135
+ request.should_receive(:execute).with(req).and_return(simple_response)
136
+ parser.should_receive(:encode).with('data').and_return('data')
137
+ parser.should_receive(:decode).with(simple_response, parser_opts)
138
+ CouchRest.post('foo', 'data')
139
+ end
140
+
141
+ it "should send raw request" do
142
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
143
+ request.should_receive(:execute).with(req).and_return(simple_response)
144
+ parser.should_not_receive(:encode)
145
+ parser.should_receive(:decode).with(simple_response, parser_opts)
146
+ CouchRest.post('foo', 'data', :raw => true)
147
+ end
148
+
149
+ it "should not encode nil request" do
150
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers}
151
+ request.should_receive(:execute).with(req).and_return(simple_response)
152
+ parser.should_not_receive(:encode)
153
+ parser.should_receive(:decode).with(simple_response, parser_opts)
154
+ CouchRest.post('foo', nil)
155
+ end
156
+
157
+ it "should send raw request automatically if file provided" do
158
+ f = File.open(FIXTURE_PATH + '/attachments/couchdb.png')
159
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => f}
160
+ request.should_receive(:execute).with(req).and_return(simple_response)
161
+ parser.should_not_receive(:encode)
162
+ parser.should_receive(:decode).with(simple_response, parser_opts)
163
+ CouchRest.post('foo', f)
164
+ f.close
165
+ end
166
+
167
+ it "should send raw request automatically if Tempfile provided" do
168
+ f = Tempfile.new('couchrest')
169
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => f}
170
+ request.should_receive(:execute).with(req).and_return(simple_response)
171
+ parser.should_not_receive(:encode)
172
+ parser.should_receive(:decode).with(simple_response, parser_opts)
173
+ CouchRest.post('foo', f)
174
+ f.close
175
+ end
176
+
177
+ it "should use as_couch_json method if available" do
178
+ h = {'foo' => 'bar'}
179
+ doc = CouchRest::Document.new(h)
180
+ doc.should_receive(:as_couch_json).and_return(h)
181
+ request.should_receive(:execute).and_return(simple_response)
182
+ parser.should_receive(:encode).with(h)
183
+ parser.should_receive(:decode).with(simple_response, parser_opts)
184
+ CouchRest.post('foo', doc)
185
+ end
186
+ end
187
+
188
+
189
+ describe :put do
190
+ # Only test basic as practically same as post
191
+ it "should send basic request" do
192
+ req = {:url => 'foo', :method => :put, :headers => CouchRest.default_headers, :payload => 'data'}
193
+ request.should_receive(:execute).with(req).and_return(simple_response)
194
+ parser.should_receive(:encode).with('data').and_return('data')
195
+ parser.should_receive(:decode).with(simple_response, parser_opts)
196
+ CouchRest.put('foo', 'data')
197
+ end
198
+
199
+ end
200
+
201
+ describe :delete do
202
+ it "should send basic request" do
203
+ req = {:url => 'foo', :method => :delete, :headers => CouchRest.default_headers}
204
+ request.should_receive(:execute).with(req).and_return(simple_response)
205
+ parser.should_receive(:decode).with(simple_response, parser_opts)
206
+ CouchRest.delete('foo')
207
+ end
208
+ end
209
+
210
+ describe :copy do
211
+ it "should send basic request" do
212
+ headers = CouchRest.default_headers.merge(
213
+ 'Destination' => 'fooobar'
214
+ )
215
+ req = {:url => 'foo', :method => :copy, :headers => headers}
216
+ request.should_receive(:execute).with(req).and_return(simple_response)
217
+ parser.should_receive(:decode).with(simple_response, parser_opts)
218
+ CouchRest.copy('foo', 'fooobar')
219
+ end
220
+
221
+ it "should never modify header options" do
222
+ options = {:headers => {:content_type => :foo}}
223
+ options.freeze
224
+ request.should_receive(:execute).and_return(simple_response)
225
+ parser.should_receive(:decode)
226
+ expect { CouchRest.copy('foo', 'foobar', options) }.to_not raise_error
227
+ end
228
+
229
+ end
230
+
231
+ describe :head do
232
+ it "should send basic request" do
233
+ req = {:url => 'foo', :method => :head, :headers => CouchRest.default_headers}
234
+ request.should_receive(:execute).with(req).and_return(simple_response)
235
+ CouchRest.head('foo')
236
+ end
237
+ end
238
+
239
+ end
240
+
241
+ end