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.
@@ -1,10 +1,9 @@
1
1
  module Cushion
2
2
  class Design < Document
3
- def view(view_name, query={})
4
- view_name = view_name.to_s
5
- view_slug = "#{name}/#{view_name}"
6
- defaults = (self['views'][view_name] && self['views'][view_name]["couchrest-defaults"]) || {}
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
@@ -1,59 +1,92 @@
1
1
  module Cushion
2
- class Response < Hash
3
- def initialize(keys = {})
4
- keys.each do |k,v|
5
- self[k.to_s] = v
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
- super(key.to_s, value)
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
- super(key.to_s)
36
+ @attributes[key.to_s]
15
37
  end
16
- end
17
-
18
- class Document < Response
19
- attr_accessor :database
20
38
 
21
- class << self
22
- def use_database(db)
23
- @database = db
24
- end
39
+ def delete(key)
40
+ @attributes.delete(key.to_s)
41
+ end
25
42
 
26
- def database
27
- @database
28
- end
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
- # Returns true if this document has never been saved
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
- # Saves this document to the database.
82
+ # Save this document. TODO: Change attachments to stubs on save?
45
83
  def save
46
- result = database.save_doc(self)
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 from the database.
87
+ # Deletes this document.
55
88
  def destroy
56
- result = database.delete_doc(id, rev)
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
- # Reloads this document from the database.
65
- def reload
66
- result = database.open_doc(id)
67
- initialize(result)
68
- self
69
- end
70
-
71
- # Copies the document to a new id. If +dest_id+ currently exists then
72
- # +dest_rev+ must be provided.
73
- def copy(dest_id, dest_rev = nil)
74
- result = database.copy_doc(id, dest_id, :dest_rev => dest_rev)
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
- # Moves the document to a new id. If +dest_id+ currently exists then
79
- # +dest_rev+ must be provided.
80
- def move(dest_id, dest_rev = nil)
81
- result = database.move_doc(id, dest_id, rev, :dest_rev => dest_rev)
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 an IO object.
91
- def open_attachment(filename)
92
- database.open_attachment(id, filename)
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
- # Attaches a file to this document under +filename+.
96
- def save_attachment(filename, data, options={})
97
- result = database.save_attachment(id, rev, filename, data, options)
98
- self[:_rev] = result['rev']
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
- # Deletes the attachment identified by +filename+.
103
- def delete_attachment(filename)
104
- result = database.delete_attachment(id, rev, filename)
105
- self[:_rev] = result['rev']
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
- # Renames an attachment. +oldname+ is the name of the existing attachment
110
- # and +newname+ is the desired name.
111
- def rename_attachment(oldname, newname)
112
- result = database.rename_attachment(id, rev, oldname, newname)
113
- self[:_rev] = result['rev']
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
@@ -4,10 +4,10 @@ module Cushion
4
4
  class Server
5
5
  attr_accessor :uri, :uuid_batch_count
6
6
 
7
- # Initialize a Cushion::Server to the uri at +server+.
8
- def initialize(server = DEFAULT_COUCH_HOST, uuid_batch_count = 1000)
9
- @uri = server
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
- begin
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(self, name)
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 a Tempfile.
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
@@ -1,9 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/helpers'
2
2
 
3
3
  describe Cushion do
4
-
5
4
  it "should instantiate a Cushion::Server" do
6
5
  Cushion.new.should.be.a.kind_of Cushion::Server
7
6
  end
8
-
9
7
  end
@@ -1,7 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helpers'
2
2
 
3
- describe "Cushion::Database" do
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
- describe "Operations" do
14
-
15
- it "should properly initialize a database instance" do
16
- badname = Cushion::Database.new(Cushion.new, "my/database")
17
- badname.name.should == "my%2Fdatabase"
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
- it "should compact a database" do
32
- @db.save_doc("foo" => "bar")
33
- @db.compact["ok"].should.be.true
34
- end
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
- it "should pass requests to external handlers" do
37
- # This is kind of lame, but installing an external handler to run a "real"
38
- # external test seems like overkill.
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
- describe "Saving" do
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
- it "should save a document" do
47
- @db.save_doc("_id" => "123")["ok"].should.be.true
48
- end
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
- it "should automatically generate an id if none provided on save" do
51
- saved = @db.save_doc("foo" => "bar")
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 bulk save documents" do
57
- count = @db.info["doc_count"]
58
- @db.bulk_docs([{"_id" => "456"},{"_id" => "789"}])["ok"].should.be.true
59
- @db.info["doc_count"].should == count + 2
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
- describe "Deleting" do
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
- before do
67
- @db.save_doc("_id" => "123")
68
- @db.save_doc("_id" => "456")
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 delete a document" do
72
- doc = @db.open_doc("123")
73
- @db.delete_doc("123", doc['_rev'])["ok"].should.be.true
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 bulk delete documents" do
77
- count = @db.info["doc_count"]
78
- docs = @db.all_docs(:keys => ["123", "456"], :include_docs => true)
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
- describe "Copying" do
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
- before do
88
- @abc = @db.save_doc("_id" => "abc")
89
- @ghi = @db.save_doc("_id" => "ghi")
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
- it "should copy an existing doc to a new/existing doc" do
93
- res = @db.copy_doc("abc", "def")
94
- res["id"].should == "def"
95
- @db.copy_doc("abc", "def", :dest_rev => res["rev"])["ok"].should.be.true
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
- it "should move an existing doc to a new/existing doc" do
99
- @db.move_doc("abc", "def", @abc["rev"])["ok"].should.be.true
100
- lambda { @db.open_doc("abc") }.should.raise RestClient::ResourceNotFound
101
- doc = @db.open_doc("def")
102
- @db.move_doc("def", "ghi", doc["_rev"], :dest_rev => @ghi["rev"])["ok"].should.be.true
103
- end
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
- describe "Reading" do
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
- before do
110
- @db.save_doc("_id" => "123")
111
- @db.save_doc("_id" => "456")
112
- end
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
- it "should open a document" do
115
- @db.open_doc("123")["_id"].should == "123"
116
- end
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
- it "should load a Cushion::Document" do
119
- @db.doc("123").should.be.kind_of Cushion::Document
120
- end
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
- it "should retrieve all documents" do
123
- @db.all_docs["total_rows"].should == 2
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
- it "should retrieve all documents by keys" do
127
- @db.all_docs(:keys => ["123"])["rows"].length.should == 1
128
- end
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
- describe "Views" do
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.save_doc("_id" => "gomer", "name" => "gomer pyle")
136
- @db.save_doc("_id" => "vince", "name" => "vince carter")
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.save_doc("_id" => "_design/foo", "views" => { "bar" => @view })
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 docs from temp views" do
142
- @db.temp_view(@view, :key => "gomer pyle")["rows"].length.should == 1
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.temp_view(@view, :keys => ["vince carter"])["rows"].length.should == 1
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 retrieve a doc from a show function" do
158
- design = @db.open_doc("_design/foo")
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.save_doc(design)
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.open_doc("_design/foo")
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.save_doc(design)
243
+ @db.store(design)
168
244
  @db.list("foo", "people", "bar").should == "xxxx"
169
245
  end
170
-
171
246
  end
172
247
 
173
- describe "Attachments" do
174
-
175
- it "should save and open inline attachments" do
176
- @db.save_doc("_id" => "inline", "_attachments" => {
177
- "foo.txt" => {
178
- "content_type" => "text/plain",
179
- "data" => "Hello World!"
180
- }
181
- })["ok"].should.be.true
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
- @db.open_attachment("inline", "foo.txt").read.should == "Hello World!"
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 save and open standalone attachments" do
187
- res = @db.save_doc("_id" => "attachable")
188
- @db.save_attachment(res['id'], res['rev'],
189
- "foo.txt", "Hello World!",
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
- @db.open_attachment("attachable", "foo.txt").read.should == "Hello World!"
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 delete attachments" do
197
- res = @db.save_doc("_id" => "deleteme", "_attachments" => {
198
- "foo.txt" => {
199
- "content_type" => "text/plain",
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
- @db.delete_attachment("deleteme", res["rev"], "foo.txt")["ok"].should.be.true
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 rename attachments" do
208
- res = @db.save_doc("_id" => "rename", "_attachments" => {
209
- "foo.txt" => {
210
- "content_type" => "text/plain",
211
- "data" => "Hello World!"
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
- @db.rename_attachment("rename", res["rev"], "foo.txt", "bar.txt")["ok"].should.be.true
216
- @db.open_doc("rename")["_attachments"]["bar.txt"].should.not.be.nil
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