sr-couchy 0.0.2
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/README.textile +77 -0
- data/Rakefile +46 -0
- data/bin/couchy +80 -0
- data/couchy.gemspec +58 -0
- data/lib/couchy.rb +21 -0
- data/lib/couchy/database.rb +129 -0
- data/lib/couchy/server.rb +89 -0
- data/spec/couchy_spec.rb +71 -0
- data/spec/database_spec.rb +417 -0
- data/spec/fixtures/attachments/test.html +11 -0
- data/spec/fixtures/views/lib.js +3 -0
- data/spec/fixtures/views/test_view/lib.js +3 -0
- data/spec/fixtures/views/test_view/only-map.js +4 -0
- data/spec/fixtures/views/test_view/test-map.js +3 -0
- data/spec/fixtures/views/test_view/test-reduce.js +3 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +5 -0
- data/test/couchy_test.rb +13 -0
- data/test/database_test.rb +193 -0
- data/test/server_test.rb +211 -0
- data/test/test_helper.rb +10 -0
- data/vendor/addressable/.gitignore +7 -0
- data/vendor/addressable/CHANGELOG +51 -0
- data/vendor/addressable/LICENSE +20 -0
- data/vendor/addressable/README +24 -0
- data/vendor/addressable/Rakefile +51 -0
- data/vendor/addressable/lib/addressable/idna.rb +4867 -0
- data/vendor/addressable/lib/addressable/uri.rb +2212 -0
- data/vendor/addressable/lib/addressable/version.rb +35 -0
- data/vendor/addressable/spec/addressable/idna_spec.rb +196 -0
- data/vendor/addressable/spec/addressable/uri_spec.rb +3827 -0
- data/vendor/addressable/spec/data/rfc3986.txt +3419 -0
- data/vendor/addressable/tasks/clobber.rake +2 -0
- data/vendor/addressable/tasks/gem.rake +62 -0
- data/vendor/addressable/tasks/git.rake +40 -0
- data/vendor/addressable/tasks/metrics.rake +22 -0
- data/vendor/addressable/tasks/rdoc.rake +29 -0
- data/vendor/addressable/tasks/rubyforge.rake +89 -0
- data/vendor/addressable/tasks/spec.rake +107 -0
- data/vendor/addressable/website/index.html +107 -0
- metadata +113 -0
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
data/test/couchy_test.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
describe 'Couchy#new' do
|
4
|
+
it 'creates a new Server with the given server URI' do
|
5
|
+
Couchy::Server.expects(:new).with('uri')
|
6
|
+
Couchy.new('uri')
|
7
|
+
end
|
8
|
+
|
9
|
+
specify 'uri default to http://localhost:5984/' do
|
10
|
+
server = Couchy.new
|
11
|
+
server.uri.to_s.should.equal 'http://localhost:5984/'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
describe 'Database' do
|
4
|
+
before(:each) do
|
5
|
+
@server = stub('server', :get => '', :post => '', :put => '', :delete => '')
|
6
|
+
@database = Couchy::Database.new(@server, TestDatabase)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'has an accessor on its name' do
|
10
|
+
@database.name.should.equal TestDatabase
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has an accessor on the server instance' do
|
14
|
+
@database.server.should.equal @server
|
15
|
+
end
|
16
|
+
|
17
|
+
specify '#base64 removes new lines to workaround <https://issues.apache.org/jira/browse/COUCHDB-19>' do
|
18
|
+
@database.send(:base64, 'foo').should.equal 'Zm9v'
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'Encoding attachments of a document' do
|
22
|
+
setup do
|
23
|
+
Couchy::Database.class_eval { public :encode_attachments_of }
|
24
|
+
@server.stubs(:base64).returns('')
|
25
|
+
@database = Couchy::Database.new(@server, TestDatabase)
|
26
|
+
@attachments = { 'foo' => { 'type' => 'text/plain', 'data' => 'some text' },
|
27
|
+
'bar' => { 'type' => 'text/plain', 'data' => 'same here' }}
|
28
|
+
@doc = {:foo => 'bar', '_attachments' => @attachments}
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns the doc as is if there is no attachment' do
|
32
|
+
@database.encode_attachments_of(:foo => 'bar').should.equal(:foo => 'bar')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'encodes the data of each attachment in base64' do
|
36
|
+
@database.expects(:base64).with('some text').returns('')
|
37
|
+
@database.expects(:base64).with('same here').returns('')
|
38
|
+
@database.encode_attachments_of(@doc)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the document with the attachments encoded' do
|
42
|
+
doc = @database.encode_attachments_of(@doc)
|
43
|
+
doc['_attachments']['foo']['data'].should.equal 'c29tZSB0ZXh0'
|
44
|
+
doc['_attachments']['bar']['data'].should.equal 'c2FtZSBoZXJl'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'Deleting itselfs' do
|
49
|
+
it 'DELETE $database_name' do
|
50
|
+
@server.expects(:delete).with(TestDatabase)
|
51
|
+
@database.delete!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'Getting a list of documents' do
|
56
|
+
it 'GET $database_name/_all_docs' do
|
57
|
+
@server.expects(:get).with(TestDatabase + '/_all_docs', {})
|
58
|
+
@database.documents
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'uses given parameters' do
|
62
|
+
@server.expects(:get).with(TestDatabase + '/_all_docs', :startkey => 'somedoc', :count => 3)
|
63
|
+
@database.documents(:startkey => 'somedoc', :count => 3)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'Getting a document' do
|
68
|
+
it 'GET $database_name/$document_id' do
|
69
|
+
@server.expects(:get).with("#{TestDatabase}/foobar")
|
70
|
+
@database.get('foobar')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'escapes the given document id' do
|
74
|
+
CGI.expects(:escape).with('foobar')
|
75
|
+
@database.get('foobar')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'Saving a document' do
|
80
|
+
it 'encodes attachments of the given document' do
|
81
|
+
doc = {:foo => 'bar'}
|
82
|
+
@database.expects(:encode_attachments_of).with(doc).returns({})
|
83
|
+
@database.save(doc)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'POST the document to $database_name when no document id is specified' do
|
87
|
+
doc = {:foo => 'bar'}
|
88
|
+
@server.expects(:post).with(TestDatabase, doc)
|
89
|
+
@database.save(doc)
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'When a document id was specified' do
|
93
|
+
it 'PUT the document to $database_name/$document_id' do
|
94
|
+
doc = {'_id' => 'mydocid', 'foo' => 'bar'}
|
95
|
+
@server.expects(:put).with("#{TestDatabase}/#{doc['_id']}", doc)
|
96
|
+
@database.save(doc)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'escapes the given document id' do
|
100
|
+
CGI.expects(:escape).with('mydocid')
|
101
|
+
@database.save('_id' => 'mydocid')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'Bulk saving a bunch of documents' do
|
107
|
+
it 'POST the documents to $database_name/_bulk_docs' do
|
108
|
+
@server.expects(:post).with("#{TestDatabase}/_bulk_docs", :docs => ['doc1', 'doc2'])
|
109
|
+
@database.bulk_save(['doc1', 'doc2'])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'Fetching an attachment' do
|
114
|
+
it 'GET $database_name/$document_id/$attachment_id' do
|
115
|
+
@server.expects(:get).with("#{TestDatabase}/my-doc/foo", anything)
|
116
|
+
@database.fetch_attachment('my-doc', 'foo')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'escapes the document id and the attachement id' do
|
120
|
+
CGI.expects(:escape).with('my-doc')
|
121
|
+
CGI.expects(:escape).with('foo')
|
122
|
+
@database.fetch_attachment('my-doc', 'foo')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'Deleting a document' do
|
127
|
+
describe 'When given the document id and the revision' do
|
128
|
+
it 'DELETE $database_name/$document_id?rev=$revision' do
|
129
|
+
@server.expects(:delete).with("#{TestDatabase}/mydocid", :rev => 2800624930)
|
130
|
+
@database.delete('mydocid', 2800624930)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'escapes the document id' do
|
134
|
+
CGI.expects(:escape).with('mydocid')
|
135
|
+
@database.delete('mydocid', 2800624930)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'When given an Hash representing a document' do
|
140
|
+
it 'raises ArgumentError if the doc doesnt have an _id' do
|
141
|
+
lambda { @database.delete('foo' => 'bar') }.should.raise(ArgumentError)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'raises ArgumentError if the doc doesnt have a _rev' do
|
145
|
+
lambda { @database.delete('_id' => 'foo') }.should.raise(ArgumentError)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'DELETE $database_name/$document_id?rev=$revision' do
|
149
|
+
@server.expects(:delete).with("#{TestDatabase}/mydocid", :rev => 2800624930)
|
150
|
+
@database.delete('_id' => 'mydocid', '_rev' => 2800624930)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'escapes the document id' do
|
154
|
+
CGI.expects(:escape).with('mydocid')
|
155
|
+
@database.delete('_id' => 'mydocid', '_rev' => 286633)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'raises ArgumentError if the given argument is neither a document id nor a document' do
|
160
|
+
lambda { @database.delete(:fooo) }.should.raise(ArgumentError)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe 'Creating a temporary view' do
|
165
|
+
it 'POST $database_name/_temp_view with the given fonction' do
|
166
|
+
@server.expects(:post).with(TestDatabase + '/_temp_view', 'js function', anything)
|
167
|
+
@database.temp_view('js function')
|
168
|
+
end
|
169
|
+
|
170
|
+
it "sets the request's Content-Type to application/json" do
|
171
|
+
@server.expects(:post).with(anything, anything,
|
172
|
+
has_entries(:headers => {'Content-Type' => 'application/json'}))
|
173
|
+
@database.temp_view('foo')
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'uses the given parameters' do
|
177
|
+
@server.expects(:post).with(anything, 'foo', has_entries(:startkey => 'foo'))
|
178
|
+
@database.temp_view('foo', :startkey => 'foo')
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe 'Getting a view' do
|
183
|
+
it 'GET $database_name/_view/$view_name' do
|
184
|
+
@server.expects(:get).with("#{TestDatabase}/_view/my-view", {})
|
185
|
+
@database.view('my-view')
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'uses the given parameters' do
|
189
|
+
@server.expects(:get).with(anything, :count => 100)
|
190
|
+
@database.view('my-view', :count => 100)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/test/server_test.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
describe 'Server' do
|
4
|
+
setup do
|
5
|
+
@server = Couchy::Server.new('http://localhost:5984/')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'has an accessor on its uri' do
|
9
|
+
server = Couchy::Server.new('foo')
|
10
|
+
server.uri.to_s.should.equal 'foo'
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'Various utility methods' do
|
14
|
+
setup do
|
15
|
+
Couchy::Server.class_eval { public :uri_for, :json, :stringify_keys_and_jsonify_values }
|
16
|
+
@server = Couchy::Server.new('http://foo.org/')
|
17
|
+
end
|
18
|
+
|
19
|
+
specify '#json parse the given json string with the given options' do
|
20
|
+
JSON.expects(:parse).with('foo', :bar => :spam)
|
21
|
+
@server.send(:json, 'foo', :bar => :spam)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#uri_for' do
|
25
|
+
setup do
|
26
|
+
@uri = stub('server uri joined with given path', :query_values= => '')
|
27
|
+
@server.uri.stubs(:join).returns(@uri)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'joins the given path with the URI of the server' do
|
31
|
+
@server.uri.expects(:join).with('bar/spam')
|
32
|
+
@server.uri_for('bar/spam')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'stringifys keys and jsonifys values of the given parameters' do
|
36
|
+
@server.expects(:stringify_keys_and_jsonify_values).with(:is => 'awesome').returns({})
|
37
|
+
@server.uri_for('group/home', {:is => 'awesome'})
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'sets the query to the given parameters' do
|
41
|
+
params = {:foo => 'bar'}
|
42
|
+
@uri.expects(:query_values=).with('stringified keys')
|
43
|
+
@server.stubs(:stringify_keys_and_jsonify_values).with(params).returns('stringified keys')
|
44
|
+
@server.uri_for('dj/premier', params)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'do not set the query if no parameters' do
|
48
|
+
@uri.expects(:query_values=).never
|
49
|
+
@server.uri_for('primo')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns the resulting URI as a string' do
|
53
|
+
@uri.expects(:to_s).returns('resulting uri as a string')
|
54
|
+
@server.uri_for('supa/star').should.equal 'resulting uri as a string'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#stringify_keys_and_jsonify_values' do
|
59
|
+
it 'stringifys keys' do
|
60
|
+
@server.stringify_keys_and_jsonify_values(:foo => 'bar').should.equal('foo' => 'bar')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'jsonifys value if key is "key"' do
|
64
|
+
@server.stringify_keys_and_jsonify_values(:key => {'foo' => 'bar'}).should.
|
65
|
+
equal('key' => '{"foo":"bar"}')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'jsonifys value if key is "startkey"' do
|
69
|
+
@server.stringify_keys_and_jsonify_values(:startkey => {'foo' => 'bar'}).should.
|
70
|
+
equal('startkey' => '{"foo":"bar"}')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'jsonifys value if key is "endkey"' do
|
74
|
+
@server.stringify_keys_and_jsonify_values(:endkey => {'foo' => 'bar'}).should.
|
75
|
+
equal('endkey' => '{"foo":"bar"}')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'HTTP requests utility methods' do
|
81
|
+
describe 'GET' do
|
82
|
+
it "appends the given path to the server's URI" do
|
83
|
+
@server.stubs(:json)
|
84
|
+
RestClient.expects(:get).with('http://localhost:5984/foo/bar')
|
85
|
+
@server.get('foo/bar')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'appends the given parameters as the query string' do
|
89
|
+
@server.stubs(:json)
|
90
|
+
RestClient.expects(:get).with('http://localhost:5984/foo?bar=spam')
|
91
|
+
@server.get('foo', :bar => 'spam')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'parses the server response as json with :max_nesting set to false' do
|
95
|
+
RestClient.stubs(:get).returns('some json')
|
96
|
+
@server.expects(:json).with('some json', :max_nesting => false).returns([])
|
97
|
+
@server.get('give_me_some_json')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'do not parse the result as json if :no_json is specified' do
|
101
|
+
RestClient.stubs(:get)
|
102
|
+
@server.expects(:json).never
|
103
|
+
@server.get('foo', :no_json => true)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'POST' do
|
108
|
+
setup do
|
109
|
+
@server.stubs(:json)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "appends the given path to server's URI" do
|
113
|
+
RestClient.expects(:post).with('http://localhost:5984/a/b', nil, anything)
|
114
|
+
@server.post('a/b')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'appends the given parameters as the query string' do
|
118
|
+
RestClient.expects(:post).with('http://localhost:5984/foo?bar=spam', nil, anything)
|
119
|
+
@server.post('foo', nil, :bar => 'spam')
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'jsonify the given body and post it' do
|
123
|
+
body = {:foo => 'bar'}
|
124
|
+
body.expects(:to_json).returns('some json')
|
125
|
+
RestClient.expects(:post).with(anything, 'some json', anything)
|
126
|
+
@server.post('foo', body)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'passes given headers to RestClient' do
|
130
|
+
RestClient.expects(:post).with(anything, anything, {'Content-Type' => 'application/json'})
|
131
|
+
@server.post('foo', nil, :headers => {'Content-Type' => 'application/json'})
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe 'PUT' do
|
136
|
+
setup do
|
137
|
+
@server.stubs(:json)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "appends the given path to the server's URI" do
|
141
|
+
RestClient.expects(:put).with('http://localhost:5984/a/b', anything)
|
142
|
+
@server.put('a/b')
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'jsonify and PUT the given body' do
|
146
|
+
body = {:foo => 'bar'}
|
147
|
+
body.expects(:to_json).returns('some json')
|
148
|
+
RestClient.expects(:put).with(anything, 'some json')
|
149
|
+
@server.put('foo', body)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'DELETE' do
|
154
|
+
it "appends the given path to the server's URI" do
|
155
|
+
@server.stubs(:json).returns('')
|
156
|
+
RestClient.expects(:delete).with('http://localhost:5984/a/b')
|
157
|
+
@server.delete('a/b')
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'appends the given parameters as the query string' do
|
161
|
+
@server.stubs(:json)
|
162
|
+
RestClient.expects(:delete).with('http://localhost:5984/foo/bar?a=b')
|
163
|
+
@server.delete('foo/bar', :a => :b)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'Getting a list of all the databases' do
|
169
|
+
it 'GET _all_dbs' do
|
170
|
+
@server.expects(:get).with('_all_dbs')
|
171
|
+
@server.databases
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'Getting a database' do
|
176
|
+
it 'creates a new Database object with the given name and itselfs' do
|
177
|
+
Couchy::Database.expects(:new).with(@server, 'mydb')
|
178
|
+
@server.database('mydb')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'returns a Database object' do
|
182
|
+
@server.database('mydb').should.be.an.instance_of Couchy::Database
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'Getting info on the server' do
|
187
|
+
it 'GET the server URI' do
|
188
|
+
@server.expects(:get).with('/')
|
189
|
+
@server.info
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'Restarting the server' do
|
194
|
+
it 'POST _restart' do
|
195
|
+
@server.expects(:post).with('_restart')
|
196
|
+
@server.restart!
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe 'Creating a new database' do
|
201
|
+
it 'PUT to database_name' do
|
202
|
+
@server.expects(:put).with('mydb')
|
203
|
+
@server.create_db('mydb')
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'returns a Database object' do
|
207
|
+
@server.stubs(:put)
|
208
|
+
@server.create_db('mydb').should.be.an.instance_of Couchy::Database
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|