dpla-couchrest 1.2.1.pre.dpla

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