akdubya-cushion 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +94 -174
- data/lib/cushion.rb +54 -10
- data/lib/cushion/database.rb +294 -203
- data/lib/cushion/design.rb +4 -5
- data/lib/cushion/document.rb +119 -69
- data/lib/cushion/server.rb +9 -13
- data/spec/cushion_spec.rb +0 -2
- data/spec/database_spec.rb +215 -132
- data/spec/document_spec.rb +172 -0
- data/spec/server_spec.rb +52 -66
- metadata +3 -2
data/lib/cushion/design.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
module Cushion
|
2
2
|
class Design < Document
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
database.view(view_slug, defaults.merge(query))
|
3
|
+
# Queries a view rooted at this document. See Database#view.
|
4
|
+
def view(view_name, options = {})
|
5
|
+
slug = "#{name}/#{view_name}"
|
6
|
+
database.view(slug, options)
|
8
7
|
end
|
9
8
|
|
10
9
|
def name
|
data/lib/cushion/document.rb
CHANGED
@@ -1,59 +1,92 @@
|
|
1
1
|
module Cushion
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
class Document
|
3
|
+
attr_accessor :database, :headers
|
4
|
+
|
5
|
+
# Sets the default database for the document class.
|
6
|
+
def self.set_database(db)
|
7
|
+
@database = db
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.database
|
11
|
+
@database
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(atts = {})
|
15
|
+
@attributes = {}
|
16
|
+
@headers = {}
|
17
|
+
merge!(atts)
|
18
|
+
if atts.respond_to?(:headers)
|
19
|
+
atts.headers.each do |h,v|
|
20
|
+
@headers[h] = v
|
21
|
+
end
|
6
22
|
end
|
7
23
|
end
|
8
24
|
|
9
25
|
def []=(key, value)
|
10
|
-
|
26
|
+
@attributes[key.to_s] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge!(atts)
|
30
|
+
atts.each do |k,v|
|
31
|
+
self[k.to_s] = v
|
32
|
+
end
|
11
33
|
end
|
12
|
-
|
34
|
+
|
13
35
|
def [](key)
|
14
|
-
|
36
|
+
@attributes[key.to_s]
|
15
37
|
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class Document < Response
|
19
|
-
attr_accessor :database
|
20
38
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
39
|
+
def delete(key)
|
40
|
+
@attributes.delete(key.to_s)
|
41
|
+
end
|
25
42
|
|
26
|
-
|
27
|
-
|
28
|
-
|
43
|
+
def key?(key)
|
44
|
+
@attributes.key?(key.to_s)
|
45
|
+
end
|
46
|
+
alias_method :has_key?, :key?
|
47
|
+
alias_method :attribute?, :key?
|
48
|
+
|
49
|
+
def database
|
50
|
+
@database || self.class.database
|
29
51
|
end
|
30
52
|
|
31
53
|
def id
|
32
54
|
self[:_id]
|
33
55
|
end
|
34
|
-
|
56
|
+
|
57
|
+
def id?
|
58
|
+
(id && !id.empty?) ? true : false
|
59
|
+
end
|
60
|
+
alias_method :has_id?, :id?
|
61
|
+
|
35
62
|
def rev
|
36
63
|
self[:_rev]
|
37
64
|
end
|
65
|
+
alias_method :etag, :rev
|
66
|
+
|
67
|
+
def rev?
|
68
|
+
(rev && !rev.empty?) ? true : false
|
69
|
+
end
|
70
|
+
alias_method :has_rev?, :rev?
|
38
71
|
|
39
|
-
|
72
|
+
def attachments
|
73
|
+
self[:_attachments] ||= {}
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns true if the document is unsaved.
|
40
77
|
def new_document?
|
41
|
-
!rev
|
78
|
+
!rev?
|
42
79
|
end
|
80
|
+
alias_method :new_doc?, :new_document?
|
43
81
|
|
44
|
-
#
|
82
|
+
# Save this document. TODO: Change attachments to stubs on save?
|
45
83
|
def save
|
46
|
-
|
47
|
-
if result['ok']
|
48
|
-
self[:_rev] = result['rev']
|
49
|
-
self[:_id] = result['id']
|
50
|
-
end
|
51
|
-
result['ok']
|
84
|
+
database.store(self)["ok"]
|
52
85
|
end
|
53
86
|
|
54
|
-
# Deletes this document
|
87
|
+
# Deletes this document.
|
55
88
|
def destroy
|
56
|
-
result = database.
|
89
|
+
result = database.destroy(id, :rev => rev)
|
57
90
|
if result['ok']
|
58
91
|
self[:_rev] = nil
|
59
92
|
self[:_id] = nil
|
@@ -61,57 +94,74 @@ module Cushion
|
|
61
94
|
result['ok']
|
62
95
|
end
|
63
96
|
|
64
|
-
#
|
65
|
-
def
|
66
|
-
result = database.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
97
|
+
# Attach a file to this document.
|
98
|
+
def attach(filename, data, content_type = "application/octet-stream")
|
99
|
+
result = database.attach(id, filename, data, :rev => rev,
|
100
|
+
:headers => { :content_type => content_type })
|
101
|
+
if result['ok']
|
102
|
+
self[:_rev] = result['rev']
|
103
|
+
attachments[filename] = {
|
104
|
+
"stub" => true,
|
105
|
+
"content_type" => content_type,
|
106
|
+
"length" => "<not loaded>"
|
107
|
+
}
|
108
|
+
end
|
75
109
|
result['ok']
|
76
110
|
end
|
77
|
-
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
result
|
111
|
+
|
112
|
+
# Deletes the attachment identified by +filename+.
|
113
|
+
def detach(filename)
|
114
|
+
result = database.destroy(id, filename, :rev => rev)
|
115
|
+
if result['ok']
|
116
|
+
self[:_rev] = result['rev']
|
117
|
+
attachments.delete(filename)
|
118
|
+
end
|
82
119
|
result['ok']
|
83
120
|
end
|
84
|
-
|
85
|
-
# Returns this document's database.
|
86
|
-
def database
|
87
|
-
@database || self.class.database
|
88
|
-
end
|
89
121
|
|
90
|
-
# Opens the attachment identified by +filename+. Returns
|
91
|
-
|
92
|
-
|
122
|
+
# Opens the attachment identified by +filename+. Returns either a String or
|
123
|
+
# a Tempfile, depending on the database setup.
|
124
|
+
def fetch(filename)
|
125
|
+
database.fetch(id, filename)
|
93
126
|
end
|
94
|
-
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
127
|
+
|
128
|
+
# Renames an attachment. +oldname+ is the name of the existing attachment
|
129
|
+
# and +newname+ is the desired name.
|
130
|
+
def rename(oldname, newname)
|
131
|
+
result = database.move_attachment(id, oldname, newname)
|
132
|
+
if result['ok']
|
133
|
+
self[:_rev] = result['rev']
|
134
|
+
attachments[newname] = attachments.delete(oldname)
|
135
|
+
end
|
99
136
|
result['ok']
|
100
137
|
end
|
101
|
-
|
102
|
-
#
|
103
|
-
def
|
104
|
-
|
105
|
-
self
|
138
|
+
|
139
|
+
# Reloads this document.
|
140
|
+
def reload
|
141
|
+
initialize(database.fetch(id))
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
# Copies this document to a new id. If +dest_id+ currently exists then
|
146
|
+
# the +dest_rev+ option must be provided.
|
147
|
+
def copy_to(dest_id, opts = {})
|
148
|
+
result = database.copy(id, dest_id, :dest_rev => opts[:rev])
|
106
149
|
result['ok']
|
107
150
|
end
|
108
151
|
|
109
|
-
#
|
110
|
-
#
|
111
|
-
def
|
112
|
-
result = database.
|
113
|
-
|
152
|
+
# Moves this document to a new id. If +dest_id+ currently exists then
|
153
|
+
# the +dest_rev+ option must be provided.
|
154
|
+
def move_to(dest_id, opts = {})
|
155
|
+
result = database.move(id, dest_id, :rev => rev, :dest_rev => opts[:rev])
|
156
|
+
if result['ok']
|
157
|
+
self[:_rev] = nil
|
158
|
+
self[:_id] = nil
|
159
|
+
end
|
114
160
|
result['ok']
|
115
161
|
end
|
162
|
+
|
163
|
+
def to_json
|
164
|
+
@attributes.to_json
|
165
|
+
end
|
116
166
|
end
|
117
167
|
end
|
data/lib/cushion/server.rb
CHANGED
@@ -4,10 +4,10 @@ module Cushion
|
|
4
4
|
class Server
|
5
5
|
attr_accessor :uri, :uuid_batch_count
|
6
6
|
|
7
|
-
#
|
8
|
-
def initialize(
|
9
|
-
@uri =
|
10
|
-
@uuid_batch_count = uuid_batch_count
|
7
|
+
# Initializes a Cushion::Server.
|
8
|
+
def initialize(options = {})
|
9
|
+
@uri = options[:uri] || DEFAULT_COUCH_HOST
|
10
|
+
@uuid_batch_count = options[:uuid_batch_count] || 1000
|
11
11
|
end
|
12
12
|
|
13
13
|
# Retrieves the server's welcome message.
|
@@ -66,12 +66,7 @@ module Cushion
|
|
66
66
|
# Returns a Cushion::Database.
|
67
67
|
def recreate(name)
|
68
68
|
rdb = db(name)
|
69
|
-
|
70
|
-
rdb.drop
|
71
|
-
rescue RestClient::ResourceNotFound
|
72
|
-
nil
|
73
|
-
end
|
74
|
-
rdb.create
|
69
|
+
rdb.recreate
|
75
70
|
rdb
|
76
71
|
end
|
77
72
|
|
@@ -86,7 +81,7 @@ module Cushion
|
|
86
81
|
# not attempt to create the database if it does not already exist on the
|
87
82
|
# server.
|
88
83
|
def db(name)
|
89
|
-
Cushion::Database.new(
|
84
|
+
Cushion::Database.new(name, :server => self)
|
90
85
|
end
|
91
86
|
alias_method :database, :db
|
92
87
|
|
@@ -171,7 +166,8 @@ module Cushion
|
|
171
166
|
)
|
172
167
|
end
|
173
168
|
|
174
|
-
# Opens the attachment located at +path+. Returns
|
169
|
+
# Opens the attachment located at +path+. Returns an <tt>OpenURI</tt> <tt>IO</tt>
|
170
|
+
# object.
|
175
171
|
def open_attachment(path)
|
176
172
|
open("#{@uri}/#{path}")
|
177
173
|
rescue OpenURI::HTTPError
|
@@ -192,7 +188,7 @@ module Cushion
|
|
192
188
|
|
193
189
|
def parse_response(result)
|
194
190
|
if result.headers[:content_type] == "application/json"
|
195
|
-
JSON.parse(result)
|
191
|
+
Meta.init(JSON.parse(result), result)
|
196
192
|
else
|
197
193
|
result
|
198
194
|
end
|
data/spec/cushion_spec.rb
CHANGED
data/spec/database_spec.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helpers'
|
2
2
|
|
3
|
-
describe "Cushion
|
4
|
-
|
3
|
+
describe "A Cushion database" do
|
5
4
|
before do
|
6
5
|
@db = Cushion.db!('http://127.0.0.1:5984/cushion_test')
|
7
6
|
end
|
@@ -10,143 +9,213 @@ describe "Cushion::Database" do
|
|
10
9
|
@db.drop rescue nil
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
lambda { Cushion::Database.new( :foo, "mydb" ) }.should.raise ArgumentError
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should create and drop a database" do
|
22
|
-
newdb = Cushion.db('http://127.0.0.1:5984/foo_test')
|
23
|
-
newdb.create["ok"].should.be.true
|
24
|
-
newdb.drop["ok"].should.be.true
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should retrieve database info" do
|
28
|
-
@db.info["db_name"].should == "cushion_test"
|
29
|
-
end
|
12
|
+
it "should properly initialize" do
|
13
|
+
badname = Cushion::Database.new("my/database", :server => Cushion.new)
|
14
|
+
badname.name.should == "my%2Fdatabase"
|
15
|
+
lambda { Cushion::Database.new("mydb") }.should.raise ArgumentError
|
16
|
+
end
|
30
17
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
18
|
+
it "should create and drop a database" do
|
19
|
+
newdb = Cushion.db('http://127.0.0.1:5984/foo_test')
|
20
|
+
newdb.create["ok"].should.be.true
|
21
|
+
newdb.drop["ok"].should.be.true
|
22
|
+
end
|
35
23
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
lambda { @db.external(:get, "all_docs") }.should.not.raise
|
40
|
-
end
|
24
|
+
it "should retrieve database info with #info" do
|
25
|
+
@db.info["db_name"].should == "cushion_test"
|
26
|
+
end
|
41
27
|
|
28
|
+
it "should compact a database with #compact" do
|
29
|
+
@db.store("foo" => "bar")
|
30
|
+
@db.compact["ok"].should.be.true
|
42
31
|
end
|
43
32
|
|
44
|
-
|
33
|
+
it "should pass requests to external handlers with #external" do
|
34
|
+
# This is kind of lame, but installing an external handler to run a "real"
|
35
|
+
# external test seems like overkill.
|
36
|
+
lambda { @db.external(:get, "all_docs") }.should.not.raise
|
37
|
+
end
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
it "should save a document with #store" do
|
40
|
+
saved = @db.store("_id" => "123")
|
41
|
+
saved["ok"].should.be.true
|
42
|
+
saved["rev"].should.not.be.nil
|
43
|
+
end
|
49
44
|
|
50
|
-
|
51
|
-
|
45
|
+
describe "when storing documents" do
|
46
|
+
it "should automatically generate an id if none provided" do
|
47
|
+
saved = @db.store("foo" => "bar")
|
52
48
|
saved["ok"].should.be.true
|
53
49
|
saved["rev"].should.not.be.nil
|
54
50
|
end
|
55
51
|
|
56
|
-
it "should
|
57
|
-
|
58
|
-
@db.
|
59
|
-
|
52
|
+
it "should update a document if a rev is supplied" do
|
53
|
+
res = @db.store("_id" => "mydoc", "foo" => "bar")
|
54
|
+
updated = @db.store("_id" => "mydoc", "_rev" => res["rev"], "foo" => "bar")
|
55
|
+
updated["ok"].should.be.true
|
60
56
|
end
|
61
57
|
|
58
|
+
it "should raise a request failed error when trying to update a document without a rev" do
|
59
|
+
@db.store("_id" => "mydoc", "foo" => "bar")
|
60
|
+
lambda { @db.store("_id" => "mydoc", "foo" => "bar") }.should.raise RestClient::RequestFailed
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should save encoded inline attachments" do
|
64
|
+
inline = { "_id" => "inline", "_attachments" => { "foo.txt" => {
|
65
|
+
"content_type" => "text/plain", "data" => "Hello World!" } } }
|
66
|
+
|
67
|
+
@db.store(inline)["ok"].should.be.true
|
68
|
+
inline["_attachments"]["foo.txt"]["data"].should == "SGVsbG8gV29ybGQh"
|
69
|
+
@db.fetch("inline", "foo.txt").should == "Hello World!"
|
70
|
+
end
|
62
71
|
end
|
63
72
|
|
64
|
-
|
73
|
+
it "should retrieve a document with #fetch" do
|
74
|
+
@db.store("_id" => "123")
|
75
|
+
@db.fetch("123")["_id"].should == "123"
|
76
|
+
end
|
65
77
|
|
66
|
-
|
67
|
-
|
68
|
-
@db.
|
78
|
+
describe "when fetching documents" do
|
79
|
+
it "should raise a resource not found error if the doc does not exist" do
|
80
|
+
lambda { @db.fetch("bogus") }.should.raise RestClient::ResourceNotFound
|
69
81
|
end
|
70
82
|
|
71
|
-
it "should
|
72
|
-
|
73
|
-
@db.
|
83
|
+
it "should pass extra parameters to CouchDB" do
|
84
|
+
@db.store("_id" => "123")
|
85
|
+
@db.fetch("123", :revs => true)["_revs"].should.not.be.nil
|
74
86
|
end
|
75
87
|
|
76
|
-
it "should
|
77
|
-
|
78
|
-
|
79
|
-
@db.bulk_delete(docs["rows"].map{ |row| row["doc"] })["ok"].should.be.true
|
80
|
-
@db.info["doc_count"].should == count - 2
|
88
|
+
it "should pass headers to CouchDB" do
|
89
|
+
@db.store("_id" => "123")
|
90
|
+
@db.fetch("123", :headers => { :accept => "text/plain" }).should.be.kind_of String
|
81
91
|
end
|
82
92
|
|
93
|
+
it "should perform a conditional GET" do
|
94
|
+
res = @db.store("_id" => "123")
|
95
|
+
lambda {
|
96
|
+
@db.fetch("123", :etag => res['rev'])
|
97
|
+
}.should.raise RestClient::NotModified
|
98
|
+
end
|
83
99
|
end
|
84
100
|
|
85
|
-
|
101
|
+
it "should return false from #key? if a document is not available" do
|
102
|
+
@db.key?("foo").should.be.false
|
103
|
+
end
|
86
104
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
105
|
+
it "should return false from #key? if an attachment is not available" do
|
106
|
+
@db.key?("foo", "bar.txt").should.be.false
|
107
|
+
end
|
91
108
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
109
|
+
it "should return true from #key? if a document is available" do
|
110
|
+
@db.store("_id" => "foo")
|
111
|
+
@db.key?("foo").should.be.true
|
112
|
+
end
|
97
113
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
114
|
+
it "should return true from #key? if an attachment is available" do
|
115
|
+
@db.store("_id" => "foo", "_attachments" => {
|
116
|
+
"bar.txt" => {
|
117
|
+
"content_type" => "text/plain",
|
118
|
+
"data" => "Hello World!"
|
119
|
+
}})
|
120
|
+
@db.key?("foo", "bar.txt").should.be.true
|
121
|
+
end
|
104
122
|
|
123
|
+
it "should load a Cushion::Document instance with #doc" do
|
124
|
+
@db.store("_id" => "123")
|
125
|
+
@db.doc("123").should.be.kind_of Cushion::Document
|
126
|
+
@db.store("_id" => "_design/123")
|
127
|
+
@db.doc("_design/123").should.be.kind_of Cushion::Design
|
105
128
|
end
|
106
129
|
|
107
|
-
|
130
|
+
it "should delete a document with #destroy" do
|
131
|
+
res = @db.store("_id" => "123")
|
132
|
+
@db.destroy("123", :rev => res["rev"])["ok"].should.be.true
|
133
|
+
end
|
108
134
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
135
|
+
it "should raise a request error if attempting to destroy without a rev" do
|
136
|
+
res = @db.store("_id" => "123")
|
137
|
+
lambda { @db.destroy("123") }.should.raise RestClient::RequestFailed
|
138
|
+
end
|
113
139
|
|
114
|
-
|
115
|
-
|
116
|
-
|
140
|
+
it "should open attachments with #fetch" do
|
141
|
+
@db.store("_id" => "fetchme", "_attachments" => {
|
142
|
+
"foo.txt" => {
|
143
|
+
"content_type" => "text/plain",
|
144
|
+
"data" => "Hello World!"
|
145
|
+
}})
|
146
|
+
@db.fetch("fetchme", "foo.txt").should == "Hello World!"
|
147
|
+
end
|
117
148
|
|
118
|
-
|
119
|
-
|
120
|
-
|
149
|
+
it "should save standalone attachments with #attach" do
|
150
|
+
res = @db.store("_id" => "attachable")
|
151
|
+
@db.attach("attachable", "foo.txt", "Hello World!", :rev => res['rev'],
|
152
|
+
:content_type => "text/plain")["ok"].should.be.true
|
153
|
+
@db.fetch("attachable")["_attachments"]["foo.txt"]["content_type"].should == "text/plain"
|
154
|
+
end
|
121
155
|
|
122
|
-
|
123
|
-
|
156
|
+
describe "when fetching attachments" do
|
157
|
+
it "should return tempfiles if use_tempfiles is set" do
|
158
|
+
@db.use_tempfiles = true
|
159
|
+
@db.store("_id" => "usetemp", "_attachments" => {
|
160
|
+
"foo.txt" => {
|
161
|
+
"content_type" => "text/plain",
|
162
|
+
"data" => "Hello World!"
|
163
|
+
}})
|
164
|
+
@db.fetch("usetemp", "foo.txt").read.should == "Hello World!"
|
124
165
|
end
|
166
|
+
end
|
125
167
|
|
126
|
-
|
127
|
-
|
128
|
-
|
168
|
+
it "should delete attachments with #destroy" do
|
169
|
+
res = @db.store("_id" => "deleteme", "_attachments" => {
|
170
|
+
"foo.txt" => {
|
171
|
+
"content_type" => "text/plain",
|
172
|
+
"data" => "Hello World!"
|
173
|
+
}})
|
174
|
+
@db.destroy("deleteme", "foo.txt", :rev => res['rev'])["ok"].should.be.true
|
175
|
+
end
|
129
176
|
|
177
|
+
it "should bulk save documents with #bulk" do
|
178
|
+
count = @db.info["doc_count"]
|
179
|
+
@db.bulk([{"_id" => "456"},{"_id" => "789"}])["ok"].should.be.true
|
180
|
+
@db.info["doc_count"].should == count + 2
|
130
181
|
end
|
131
182
|
|
132
|
-
|
183
|
+
it "should bulk delete documents" do
|
184
|
+
@db.store("_id" => "123")
|
185
|
+
@db.store("_id" => "456")
|
186
|
+
count = @db.info["doc_count"]
|
187
|
+
docs = @db.all(:keys => ["123", "456"], :include_docs => true)
|
188
|
+
@db.bulk(docs["rows"].map{ |row| row["doc"] }, :delete => true)["ok"].should.be.true
|
189
|
+
@db.info["doc_count"].should == count - 2
|
190
|
+
end
|
133
191
|
|
192
|
+
describe "with views" do
|
134
193
|
before do
|
135
|
-
@db.
|
136
|
-
@db.
|
194
|
+
@db.store("_id" => "gomer", "name" => "gomer pyle")
|
195
|
+
@db.store("_id" => "vince", "name" => "vince carter")
|
137
196
|
@view = {:map => "function(doc){emit(doc.name,null)}"}
|
138
|
-
@db.
|
197
|
+
@db.store("_id" => "_design/foo", "views" => { "bar" => @view })
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should retrieve all documents with #view and #all" do
|
201
|
+
@db.all["total_rows"].should == 3
|
202
|
+
@db.view(:all)["total_rows"].should == 3
|
139
203
|
end
|
140
204
|
|
141
|
-
it "should retrieve
|
142
|
-
@db.
|
205
|
+
it "should retrieve all documents by keys" do
|
206
|
+
@db.all(:keys => ["vince"])["rows"].length.should == 1
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should retrieve docs from temp views with #view and #temp" do
|
210
|
+
@db.temp(@view, :key => "gomer pyle")["rows"].length.should == 1
|
211
|
+
@db.view(:temp, :funcs => @view, :key => "gomer pyle")["rows"].length.should == 1
|
143
212
|
end
|
144
213
|
|
145
214
|
it "should retrieve docs from temp views by keys" do
|
146
|
-
@db.
|
215
|
+
@db.temp(@view, :keys => ["vince carter"])["rows"].length.should == 1
|
147
216
|
end
|
148
217
|
|
149
|
-
it "should retrieve docs from regular views" do
|
218
|
+
it "should retrieve docs from regular views with #view" do
|
150
219
|
@db.view("foo/bar", :key => "gomer pyle")["rows"].length.should == 1
|
151
220
|
end
|
152
221
|
|
@@ -154,68 +223,82 @@ describe "Cushion::Database" do
|
|
154
223
|
@db.view("foo/bar", :keys => ["vince carter"])["rows"].length.should == 1
|
155
224
|
end
|
156
225
|
|
157
|
-
it "should
|
158
|
-
|
226
|
+
it "should perform a conditional GET" do
|
227
|
+
etag = @db.view("foo/bar").etag
|
228
|
+
lambda {
|
229
|
+
@db.view("foo/bar", :etag => etag)
|
230
|
+
}.should.raise RestClient::NotModified
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should retrieve a doc from a show function with #show" do
|
234
|
+
design = @db.fetch("_design/foo")
|
159
235
|
design["shows"] = { "people" => "function(doc, req) { var response = {'code':200, 'headers':{}, 'body':'Hello World'}; return response; }" }
|
160
|
-
@db.
|
236
|
+
@db.store(design)
|
161
237
|
@db.show("foo", "people", "gomer").should == "Hello World"
|
162
238
|
end
|
163
239
|
|
164
|
-
it "should retrieve docs from a list function" do
|
165
|
-
design = @db.
|
240
|
+
it "should retrieve docs from a list function with #list" do
|
241
|
+
design = @db.fetch("_design/foo")
|
166
242
|
design["lists"] = { "people" => "function(head, row, req, row_info) { var response = {'code':200, 'headers':{}, 'body':'x'}; return response; }" }
|
167
|
-
@db.
|
243
|
+
@db.store(design)
|
168
244
|
@db.list("foo", "people", "bar").should == "xxxx"
|
169
245
|
end
|
170
|
-
|
171
246
|
end
|
172
247
|
|
173
|
-
describe "
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
}
|
181
|
-
|
248
|
+
describe "when copying and moving documents" do
|
249
|
+
before do
|
250
|
+
@source = @db.store("_id" => "source", "_attachments" => {
|
251
|
+
"foo.txt" => {
|
252
|
+
"content_type" => "text/plain",
|
253
|
+
"data" => "Hello World!"
|
254
|
+
}
|
255
|
+
})
|
256
|
+
@dest = @db.store("_id" => "dest")
|
257
|
+
end
|
182
258
|
|
183
|
-
|
259
|
+
it "should copy a doc to a new id with #copy" do
|
260
|
+
@db.copy("source", "source_1")["ok"].should.be.true
|
261
|
+
lambda { @db.fetch("source_1") }.should.not.raise
|
184
262
|
end
|
185
263
|
|
186
|
-
it "should
|
187
|
-
|
188
|
-
@db.
|
189
|
-
|
190
|
-
:content_type => "text/plain"
|
191
|
-
)["ok"].should.be.true
|
264
|
+
it "should copy a doc to an existing doc" do
|
265
|
+
@db.copy("source", "dest", :dest_rev => @dest["rev"])["ok"].should.be.true
|
266
|
+
@db.fetch("dest")["_attachments"].should.not.be.nil
|
267
|
+
end
|
192
268
|
|
193
|
-
|
269
|
+
it "should move a doc to a new id with #move" do
|
270
|
+
@db.move("source", "source_1", :rev => @source["rev"])["ok"].should.be.true
|
271
|
+
lambda { @db.fetch("source_1") }.should.not.raise
|
272
|
+
lambda { @db.fetch("source") }.should.raise RestClient::ResourceNotFound
|
194
273
|
end
|
195
274
|
|
196
|
-
it "should
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
"data" => "Hello World!"
|
201
|
-
}
|
202
|
-
})
|
275
|
+
it "should move a doc to an existing doc" do
|
276
|
+
@db.move("source", "dest", :rev => @source["rev"], :dest_rev => @dest["rev"])["ok"].should.be.true
|
277
|
+
@db.fetch("dest")["_attachments"].should.not.be.nil
|
278
|
+
end
|
203
279
|
|
204
|
-
|
280
|
+
it "should copy a file to a new key under the same doc with #copy_attachment" do
|
281
|
+
@db.copy_attachment("source", "foo.txt", "bar.txt")["ok"].should.be.true
|
282
|
+
@db.fetch("source", "bar.txt").should == "Hello World!"
|
205
283
|
end
|
206
284
|
|
207
|
-
it "should
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
}
|
213
|
-
})
|
285
|
+
it "should copy a file to a new key in another doc with #copy_attachment" do
|
286
|
+
@db.copy_attachment("source", "foo.txt", "bar.txt", :dest_id => "dest",
|
287
|
+
:dest_rev => @dest["rev"])["ok"].should.be.true
|
288
|
+
@db.fetch("dest", "bar.txt").should == "Hello World!"
|
289
|
+
end
|
214
290
|
|
215
|
-
|
216
|
-
@db.
|
291
|
+
it "should move a file to a new key under the same doc with #move_attachment" do
|
292
|
+
@db.move_attachment("source", "foo.txt", "bar.txt")["ok"].should.be.true
|
293
|
+
@db.fetch("source", "bar.txt").should == "Hello World!"
|
294
|
+
lambda { @db.fetch("source", "foo.txt") }.should.raise RestClient::ResourceNotFound
|
217
295
|
end
|
218
296
|
|
297
|
+
it "should move a file to a new key in another doc with #move_attachment" do
|
298
|
+
@db.move_attachment("source", "foo.txt", "bar.txt", :dest_id => "dest",
|
299
|
+
:dest_rev => @dest["rev"])["ok"].should.be.true
|
300
|
+
@db.fetch("dest", "bar.txt").should == "Hello World!"
|
301
|
+
lambda { @db.fetch("source", "foo.txt") }.should.raise RestClient::ResourceNotFound
|
302
|
+
end
|
219
303
|
end
|
220
|
-
|
221
304
|
end
|