couchdb 0.1.0
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/LICENSE +20 -0
- data/README.rdoc +47 -0
- data/Rakefile +48 -0
- data/lib/couchdb.rb +12 -0
- data/lib/couchdb/collection.rb +121 -0
- data/lib/couchdb/database.rb +57 -0
- data/lib/couchdb/design.rb +57 -0
- data/lib/couchdb/design/view.rb +37 -0
- data/lib/couchdb/document.rb +127 -0
- data/lib/couchdb/row.rb +22 -0
- data/lib/couchdb/server.rb +42 -0
- data/spec/acceptance/database_spec.rb +56 -0
- data/spec/acceptance/document_spec.rb +78 -0
- data/spec/acceptance/server_spec.rb +43 -0
- data/spec/acceptance/views_spec.rb +49 -0
- data/spec/lib/couchdb/collection_spec.rb +121 -0
- data/spec/lib/couchdb/database_spec.rb +138 -0
- data/spec/lib/couchdb/design/view_spec.rb +89 -0
- data/spec/lib/couchdb/design_spec.rb +99 -0
- data/spec/lib/couchdb/document_spec.rb +322 -0
- data/spec/lib/couchdb/row_spec.rb +56 -0
- data/spec/lib/couchdb/server_spec.rb +87 -0
- data/spec/spec_helper.rb +5 -0
- metadata +137 -0
data/lib/couchdb/row.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module CouchDB
|
3
|
+
|
4
|
+
# The Row class acts as a wrapper for a CouchDB view result row.
|
5
|
+
class Row
|
6
|
+
|
7
|
+
attr_reader :database
|
8
|
+
attr_reader :id
|
9
|
+
attr_reader :key
|
10
|
+
attr_reader :value
|
11
|
+
|
12
|
+
def initialize(database, attributes = { })
|
13
|
+
@database, @id, @key, @value, @document = database, *attributes.values_at("id", "key", "value", "doc")
|
14
|
+
end
|
15
|
+
|
16
|
+
def document
|
17
|
+
Document.new @database, @document
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module CouchDB
|
3
|
+
|
4
|
+
# The Server class provides methods to retrieve informations and statistics
|
5
|
+
# of a CouchDB server.
|
6
|
+
class Server
|
7
|
+
|
8
|
+
attr_reader :host
|
9
|
+
attr_reader :port
|
10
|
+
|
11
|
+
def initialize(host = "localhost", port = 5984)
|
12
|
+
@host, @port = host, port
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
other.is_a?(self.class) && @host == other.host && @port == other.port
|
17
|
+
end
|
18
|
+
|
19
|
+
def information
|
20
|
+
Transport::JSON.request :get, url + "/", :expected_status_code => 200
|
21
|
+
end
|
22
|
+
|
23
|
+
def statistics
|
24
|
+
Transport::JSON.request :get, url + "/_stats", :expected_status_code => 200
|
25
|
+
end
|
26
|
+
|
27
|
+
def database_names
|
28
|
+
Transport::JSON.request :get, url + "/_all_dbs", :expected_status_code => 200
|
29
|
+
end
|
30
|
+
|
31
|
+
def uuids(count = 1)
|
32
|
+
response = Transport::JSON.request :get, url + "/_uuids", :expected_status_code => 200, :parameters => { :count => count }
|
33
|
+
response["uuids"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def url
|
37
|
+
"http://#{@host}:#{@port}"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe CouchDB::Database do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@server = CouchDB::Server.new
|
7
|
+
@database = described_class.new @server, "test"
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "create!" do
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
@database.delete_if_exists!
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create the database" do
|
17
|
+
@database.create!
|
18
|
+
@database.exists?.should be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "delete!" do
|
24
|
+
|
25
|
+
before :each do
|
26
|
+
@database.create_if_missing!
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should delete the database" do
|
30
|
+
@database.delete!
|
31
|
+
@database.exists?.should be_false
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "information" do
|
37
|
+
|
38
|
+
before :each do
|
39
|
+
@database.create_if_missing!
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return information about the database" do
|
43
|
+
@database.information.should be_instance_of(Hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "documents" do
|
49
|
+
|
50
|
+
it "should return a collection" do
|
51
|
+
@database.documents.should be_instance_of(CouchDB::Collection)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe CouchDB::Document do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@server = CouchDB::Server.new
|
7
|
+
@database = CouchDB::Database.new @server, "test"
|
8
|
+
@database.delete_if_exists!
|
9
|
+
@database.create_if_missing!
|
10
|
+
|
11
|
+
@document = described_class.new @database, "_id" => "test_document_1", "test" => "test value"
|
12
|
+
@document.save
|
13
|
+
end
|
14
|
+
|
15
|
+
after :each do
|
16
|
+
@document.destroy
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "load" do
|
20
|
+
|
21
|
+
it "should load the document's properties" do
|
22
|
+
@document["test"] = nil
|
23
|
+
@document.load
|
24
|
+
@document["test"].should == "test value"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "save" do
|
30
|
+
|
31
|
+
context "on a new model" do
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
begin
|
35
|
+
@document.load
|
36
|
+
@document.destroy
|
37
|
+
rescue described_class::NotFoundError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should create the document" do
|
42
|
+
lambda do
|
43
|
+
@document.save
|
44
|
+
end.should change(@document, :new?).from(true).to(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context "on an existing model" do
|
50
|
+
|
51
|
+
it "should update the document" do
|
52
|
+
lambda do
|
53
|
+
@document["test"] = "another test value"
|
54
|
+
@document.save
|
55
|
+
end.should change(@document, :rev)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "destroy" do
|
63
|
+
|
64
|
+
it "should destroy the document" do
|
65
|
+
lambda do
|
66
|
+
@document.destroy
|
67
|
+
end.should change(@document, :exists?).from(true).to(false)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should set the document's state to new" do
|
71
|
+
lambda do
|
72
|
+
@document.destroy
|
73
|
+
end.should change(@document, :new?).from(false).to(true)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe CouchDB::Server do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@server = described_class.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "information" do
|
10
|
+
|
11
|
+
it "should return some information about the server" do
|
12
|
+
@server.information.should == { "couchdb" => "Welcome", "version" => "1.0.1" }
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "statistics" do
|
18
|
+
|
19
|
+
it "should return some statistics about the server" do
|
20
|
+
@server.statistics.should be_instance_of(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "database_names" do
|
26
|
+
|
27
|
+
it "should return the names of all databases" do
|
28
|
+
@server.database_names.should be_instance_of(Array)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "uuids" do
|
34
|
+
|
35
|
+
it "should return the given number of generated uuids" do
|
36
|
+
uuids = @server.uuids 4
|
37
|
+
uuids.should be_instance_of(Array)
|
38
|
+
uuids.size.should == 4
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
|
2
|
+
|
3
|
+
describe "views" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@server = CouchDB::Server.new
|
7
|
+
@database = CouchDB::Database.new @server, "test"
|
8
|
+
@database.delete_if_exists!
|
9
|
+
@database.create_if_missing!
|
10
|
+
|
11
|
+
@document_one = CouchDB::Document.new @database, "_id" => "test_document_1", "category" => "one"
|
12
|
+
@document_one.save
|
13
|
+
@document_two = CouchDB::Document.new @database, "_id" => "test_document_2", "category" => "two"
|
14
|
+
@document_two.save
|
15
|
+
|
16
|
+
@design = CouchDB::Design.new @database, "design_1"
|
17
|
+
@view = CouchDB::Design::View.new @design, "view_1",
|
18
|
+
"function(document) { emit([ document['category'], document['_id'] ]); }"
|
19
|
+
@design.save
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "collection" do
|
23
|
+
|
24
|
+
it "should return a collection including the right rows" do
|
25
|
+
collection = @view.collection :startkey => [ "one", nil ], :endkey => [ "one", { } ]
|
26
|
+
collection.size.should == 1
|
27
|
+
collection[0].id.should == "test_document_1"
|
28
|
+
collection[0].key.should == [ "one", "test_document_1" ]
|
29
|
+
collection[0].value.should be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return a collection including the right documents" do
|
33
|
+
collection = @view.collection :startkey => [ "one", nil ], :endkey => [ "one", { } ]
|
34
|
+
collection.documents.should include(@document_one)
|
35
|
+
collection.documents.should_not include(@document_two)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "all documents collection" do
|
41
|
+
|
42
|
+
it "should return a collection with all documents of the database" do
|
43
|
+
collection = @database.documents
|
44
|
+
collection.size.should == 3 # two documents plus the design
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
|
2
|
+
|
3
|
+
describe CouchDB::Collection do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
Transport::JSON.stub(:request)
|
7
|
+
@database = mock CouchDB::Database
|
8
|
+
|
9
|
+
@collection = described_class.new @database, "http://host:1234/test/_all_docs"
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "initialize" do
|
13
|
+
|
14
|
+
it "should set the database" do
|
15
|
+
@collection.database.should == @database
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set the url" do
|
19
|
+
@collection.url.should == "http://host:1234/test/_all_docs"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "total_count" do
|
25
|
+
|
26
|
+
before :each do
|
27
|
+
Transport::JSON.stub(:request).and_return({ "total_rows" => 1 })
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "without a previously performed fetch" do
|
31
|
+
|
32
|
+
it "should perform a meta fetch (with a limit of zero)" do
|
33
|
+
Transport::JSON.should_receive(:request).with(
|
34
|
+
:get,
|
35
|
+
"http://host:1234/test/_all_docs",
|
36
|
+
:parameters => { :limit => 0 },
|
37
|
+
:encode_parameters => true,
|
38
|
+
:expected_status_code => 200
|
39
|
+
).and_return({ "total_rows" => 1 })
|
40
|
+
@collection.total_count
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return the total count" do
|
44
|
+
@collection.total_count.should == 1
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with a previously performed fetch" do
|
50
|
+
|
51
|
+
before :each do
|
52
|
+
@collection.first # perform the fetch
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not perform another fetch" do
|
56
|
+
Transport::JSON.should_not_receive(:request)
|
57
|
+
@collection.total_count
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return the total count" do
|
61
|
+
@collection.total_count.should == 1
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "first" do
|
69
|
+
|
70
|
+
before :each do
|
71
|
+
@row_hash = mock Hash
|
72
|
+
Transport::JSON.stub(:request).and_return({
|
73
|
+
"total_rows" => 1,
|
74
|
+
"rows" => [ @row_hash ]
|
75
|
+
})
|
76
|
+
@row = mock CouchDB::Row
|
77
|
+
CouchDB::Row.stub(:new).and_return(@row)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should initialize the row with the row hash" do
|
81
|
+
CouchDB::Row.should_receive(:new).with(@database, @row_hash).and_return(@row)
|
82
|
+
@collection.first
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return the first element of the fetched result" do
|
86
|
+
@collection.first.should == @row
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should update the total count" do
|
90
|
+
@collection.first
|
91
|
+
@collection.total_count.should == 1
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "documents" do
|
97
|
+
|
98
|
+
before :each do
|
99
|
+
@document = mock CouchDB::Document
|
100
|
+
@row = mock CouchDB::Row, :document => @document
|
101
|
+
@collection.stub(:map).and_yield(@row).and_return([ @document ])
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should add the include docs options" do
|
105
|
+
@collection.documents.first
|
106
|
+
@collection.options.should include(:include_docs => true)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should map the rows to documents" do
|
110
|
+
@collection.should_receive(:map).and_yield(@row).and_return([ @document ])
|
111
|
+
@collection.documents.first
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should return the selected row's document" do
|
115
|
+
document = @collection.documents.first
|
116
|
+
document.should == @document
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
|
2
|
+
|
3
|
+
describe CouchDB::Database do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
Transport::JSON.stub(:request)
|
7
|
+
@server = mock CouchDB::Server, :url => "http://host:1234", :database_names => [ "test" ]
|
8
|
+
|
9
|
+
@database = CouchDB::Database.new @server, "test"
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "==" do
|
13
|
+
|
14
|
+
it "should be true when comparing two equal databases" do
|
15
|
+
@database.should == described_class.new(@server, "test")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be false when comparing two different databases" do
|
19
|
+
@database.should_not == described_class.new(@server, "different")
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "===" do
|
25
|
+
|
26
|
+
it "should be true when comparing a database object with itself" do
|
27
|
+
@database.should === @database
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be false when comparing a database object with another database object" do
|
31
|
+
@database.should_not === described_class.new(@server, "test")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "create!" do
|
37
|
+
|
38
|
+
it "should request the create of the database" do
|
39
|
+
Transport::JSON.should_receive(:request).with(
|
40
|
+
:put,
|
41
|
+
"http://host:1234/test",
|
42
|
+
:expected_status_code => 201
|
43
|
+
)
|
44
|
+
@database.create!
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "create_if_missing!" do
|
50
|
+
|
51
|
+
before :each do
|
52
|
+
@database.stub(:create!)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not call create! if the database exists" do
|
56
|
+
@database.stub(:exists?).and_return(true)
|
57
|
+
@database.should_not_receive(:create!)
|
58
|
+
@database.create_if_missing!
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should call create! if the database not exists" do
|
62
|
+
@database.stub(:exists?).and_return(false)
|
63
|
+
@database.should_receive(:create!)
|
64
|
+
@database.create_if_missing!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "delete!" do
|
70
|
+
|
71
|
+
it "should delete the database" do
|
72
|
+
Transport::JSON.should_receive(:request).with(
|
73
|
+
:delete,
|
74
|
+
"http://host:1234/test",
|
75
|
+
:expected_status_code => 200
|
76
|
+
)
|
77
|
+
@database.delete!
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "delete_if_exists!" do
|
83
|
+
|
84
|
+
before :each do
|
85
|
+
@database.stub(:delete!)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should call delete! if the database exists" do
|
89
|
+
@database.stub(:exists?).and_return(true)
|
90
|
+
@database.should_receive(:delete!)
|
91
|
+
@database.delete_if_exists!
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not call delete! if the database not exists" do
|
95
|
+
@database.stub(:exists?).and_return(false)
|
96
|
+
@database.should_not_receive(:delete!)
|
97
|
+
@database.delete_if_exists!
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "information" do
|
103
|
+
|
104
|
+
it "should request database information" do
|
105
|
+
Transport::JSON.should_receive(:request).with(
|
106
|
+
:get,
|
107
|
+
"http://host:1234/test",
|
108
|
+
:expected_status_code => 200
|
109
|
+
).and_return("result")
|
110
|
+
@database.information.should == "result"
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "exists?" do
|
116
|
+
|
117
|
+
it "should be true" do
|
118
|
+
@database.exists?.should be_true
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should be false if no database with the given name exists" do
|
122
|
+
database = described_class.new @server, "invalid"
|
123
|
+
database.exists?.should be_false
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "documents" do
|
129
|
+
|
130
|
+
it "should return a collection" do
|
131
|
+
collection = @database.documents
|
132
|
+
collection.should be_instance_of(CouchDB::Collection)
|
133
|
+
collection.url.should == "http://host:1234/test/_all_docs"
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|