akdubya-cushion 0.6.2 → 0.9.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.
@@ -40,20 +40,23 @@ Fetching documents is just as simple.
40
40
  Store attachments inline or via CouchDB's standalone attachment API. The standalone
41
41
  method accepts both IO objects and strings:
42
42
 
43
- # Inline
43
+ Inline:
44
+
44
45
  db.store("_id" => "hasfiles", ..., "_attachments" => {
45
46
  "foo.txt" => {
46
47
  "content_type" => "text/plain",
47
48
  "data" => "Hello World!"
48
49
  }})
49
50
 
50
- # Standalone
51
+ Standalone:
52
+
51
53
  res = @db.store("_id" => "savemefirst", ...)
52
54
  db.attach("savemefirst", "foo.txt", "Hello World!", :rev => res['rev'],
53
55
  :content_type => "text/plain")
54
56
  # => Foo now contains an attachment hash similar to the above example
55
57
 
56
- # Fetch attachment data
58
+ Fetch attachment data:
59
+
57
60
  db.fetch("savemefirst", "foo.txt") # => "Hello World!"
58
61
 
59
62
  Cushion returns parsed JSON by default. In those cases where you need the raw
@@ -78,39 +81,48 @@ documents at once:
78
81
  db.bulk(docs) # => returns a hash of updated documents
79
82
  db.bulk(docs, :delete => true) # => deletes the selected docs
80
83
 
81
- Documents and attachments may also be copied or moved within the same database.
82
- Some useful examples:
84
+ Documents may be copied within the same database.
83
85
 
84
- # Documents
85
86
  db.copy("mydoc", "new_doc")
86
87
  # => {"ok"=>true, "id"=>"new_doc", "rev"=> ...}
87
- db.move("mydoc", "existing_doc", :rev => ..., :dest_rev => ...)
88
+ db.copy("mydoc", "existing_doc", :dest_rev => ...)
88
89
  # => overwrites the existing doc
89
90
 
90
- # Attachments
91
+ Attachments may also be copied.
92
+
91
93
  db.copy_attachment("mydoc", "foo.txt", "bar.txt")
92
94
  # => copies an attachment within the same doc
93
- db.move_attachment("mydoc", "foo.txt", "bar.txt")
94
- # => renames an attachment; aliased at #rename_attachment
95
+ db.copy_attachment("mydoc", "foo.txt", "bar.txt", :dest_id => 'existing_doc', :dest_rev => ...)
96
+ # => copies an attachment to an existing doc
97
+
98
+ == Creating Views
95
99
 
96
- See the database specs for more copy and move examples.
100
+ == Querying Views
97
101
 
98
- == Views
102
+ Query regular views by passing in the design doc name and view name along with
103
+ an optional hash of parameters.
99
104
 
100
- - creating (design docs)
101
- - querying
102
- - temp views
105
+ db.view("people/by_first_name", :key => "gomer")
106
+ db.view("foo/bar", :keys => ["a", "b", "c"])
107
+ db.view(:all)
108
+
109
+ You may also query the database using temporary views.
110
+
111
+ temp_view = { :map => "function(doc){emit(doc.status,null)}" }
112
+ db.view(:temp, :funcs => temp_view, :key => "verified")
113
+
114
+ Temp view queries are slow, so they should only be used as a convenience during
115
+ development. Whenever possible you should query against saved views.
103
116
 
104
117
  == Servers and Databases
105
118
 
106
119
  The server location defaults to http://127.0.0.1:5984, so you may omit the host
107
120
  when initializing a server if you are satisfied with the default.
108
121
 
109
- NOTE: Some cruft needs cleaning up. Use <tt>Cushion!(dbname, opts)</tt> for
110
- now.
111
-
112
122
  Display various bits of server metadata as follows:
113
123
 
124
+ server = Cushion.server :uri => 'http://myhost:5984'
125
+
114
126
  server.info #=> welcome message
115
127
  server.all_dbs #=> all dbs available
116
128
  server.active_tasks #=> running tasks (e.g., replication or compaction)
@@ -21,7 +21,7 @@ def Cushion!(dbname, opts = {})
21
21
  end
22
22
 
23
23
  module Cushion
24
- VERSION = '0.6.2'
24
+ VERSION = '0.9.0'
25
25
 
26
26
  class << self
27
27
 
@@ -130,7 +130,6 @@ module Cushion
130
130
  attr_accessor :headers
131
131
 
132
132
  def add_header_field(name, value)
133
- #value.gsub!('"', '') if name == :etag ==> CouchDB seems to require the xtra "'s
134
133
  @headers[name] = value
135
134
  end
136
135
 
@@ -234,7 +234,7 @@ module Cushion
234
234
  dest_id = options[:dest_id] || id
235
235
  opts = options[:dest_rev] ? { :rev => options[:dest_rev] } : {}
236
236
  if opts.empty? && (id == dest_id)
237
- opts = { :rev => src.headers[:etag] }
237
+ opts = { :rev => src.headers[:etag].gsub('"', '') }
238
238
  end
239
239
  res = attach(dest_id, new_filename, src, headers.merge(opts))
240
240
  if id == dest_id
@@ -244,42 +244,9 @@ module Cushion
244
244
  end
245
245
  end
246
246
 
247
- # Moves the document at +source+ to a new or existing location at +destination+.
248
- # Set the +dest_rev+ option to overwrite an existing document. Set the
249
- # +headers+ option to pass custom request headers. Example:
250
- #
251
- # db.move("doc1", "doc2", :rev => "1234")
252
- # #=> Moves to a new location
253
- # db.copy("doc1", "doc3", :rev => "1234", :dest_rev => "4567")
254
- # #=> Overwrites an existing doc
255
- #
256
- def move(source, destination, options = {})
257
- headers = options.delete(:headers) || {}
258
- dest_rev = options.delete(:dest_rev)
259
- slug = Cushion.escape_key(source)
260
- path = Cushion.paramify_url("#{slug}", options)
261
- dest = if dest_rev
262
- "#{destination}?rev=#{dest_rev}"
263
- else
264
- destination
265
- end
266
- server.move("#{@name}/#{path}", dest, headers)
267
- end
268
-
269
- # Moves an attachment to a new location. This is presently experimental.
270
- def move_attachment(id, old_filename, new_filename, options = {})
271
- res = copy_attachment(id, old_filename, new_filename, options)
272
- if res["ok"]
273
- destroy(id, old_filename, :rev => res["src_rev"])
274
- else
275
- res
276
- end
277
- end
278
- alias_method :rename_attachment, :move_attachment
279
-
280
247
  # Query a named view. Set +name+ to :all to query CouchDB's all_docs view.
281
248
  # Set +name+ to :temp to query a temp_view. Set the +keys+ option to perform
282
- # a key-based multi-document fetch against any view. Examples
249
+ # a key-based multi-document fetch against any view. Examples:
283
250
  #
284
251
  # temp_view = { :map => "function(doc){emit(doc.status,null)}" }
285
252
  # db.view(:temp, :funcs => temp_view, :key => "verified")
@@ -287,6 +254,11 @@ module Cushion
287
254
  # db.view("foo/bar", :keys => ["a", "b", "c"])
288
255
  # db.view(:all)
289
256
  #
257
+ # You should pass the design doc name and view name as two separate
258
+ # parameters if the design doc name contains slashes:
259
+ #
260
+ # db.view("foo/bar", "baz", :limit => 1)
261
+ #
290
262
  # Set the +headers+ option to pass custom request headers. Set
291
263
  # <code>:etag => some_value</code> to perform a simple if-none-match
292
264
  # conditional GET.
@@ -295,21 +267,32 @@ module Cushion
295
267
  # during development. Whenever possible you should query against saved
296
268
  # views.
297
269
  #
298
- def view(name, options = {})
270
+ def view(name, *args)
271
+ options = args.last.respond_to?(:merge) ? args.pop : {}
272
+
299
273
  keys = options.delete(:keys)
300
274
  headers = options.delete(:headers) || {}
301
275
  if etag = options.delete(:etag)
302
276
  headers.merge!(:if_none_match => "\"#{etag}\"".squeeze("\""))
303
277
  end
304
278
  body = keys ? {:keys => keys} : {}
305
- if name == :all
279
+
280
+ case name
281
+ when :all
306
282
  slug = "_all_docs"
307
- elsif name == :temp
283
+ when :temp
308
284
  slug = "_temp_view"
309
285
  body.merge!(options.delete(:funcs))
310
286
  else
311
- slug = "_view/#{name}"
287
+ if args.any?
288
+ dname = Cushion.escape_key(name)
289
+ vname = args.first
290
+ else
291
+ dname, vname = name.split('/', 2)
292
+ end
293
+ slug = "_design/#{dname}/_view/#{Cushion.escape_key(vname)}"
312
294
  end
295
+
313
296
  path = Cushion.paramify_url(slug, options)
314
297
 
315
298
  if body.any?
@@ -335,11 +318,13 @@ module Cushion
335
318
  # The results are not parsed by default. Set the +headers+ option to pass
336
319
  # custom request headers.
337
320
  #
321
+ # TODO: Need to escape names
322
+ #
338
323
  def show(design, show_template, id, options = {})
339
324
  defaults = { :accept => "text/html;text/plain;*/*" }
340
325
  headers = options.delete(:headers) || {}
341
326
  slug = Cushion.escape_key(id)
342
- path = Cushion.paramify_url("_show/#{design}/#{show_template}/#{slug}", options)
327
+ path = Cushion.paramify_url("_design/#{design}/_show/#{show_template}/#{slug}", options)
343
328
  get(path, defaults.merge(headers))
344
329
  end
345
330
 
@@ -347,12 +332,13 @@ module Cushion
347
332
  # The results are not parsed by default. Set the +headers+ option to pass
348
333
  # custom request headers.
349
334
  #
335
+ # TODO: Need to escape names
350
336
  # TODO: Update for multi-key fetch (CouchDB r750565)
351
337
  #
352
338
  def list(design, list_template, view, options = {})
353
339
  defaults = { :accept => "text/html;text/plain;*/*" }
354
340
  headers = options.delete(:headers) || {}
355
- path = Cushion.paramify_url("_list/#{design}/#{list_template}/#{view}", options)
341
+ path = Cushion.paramify_url("_design/#{design}/_list/#{list_template}/#{view}", options)
356
342
  get(path, defaults.merge(headers))
357
343
  end
358
344
 
@@ -125,17 +125,29 @@ module Cushion
125
125
  database.fetch(id, filename)
126
126
  end
127
127
 
128
- # Renames an attachment. +oldname+ is the name of the existing attachment
128
+ # Copies an attachment. +oldname+ is the name of the existing attachment
129
129
  # and +newname+ is the desired name.
130
- def rename(oldname, newname)
131
- result = database.move_attachment(id, oldname, newname)
130
+ def copy(oldname, newname)
131
+ result = database.copy_attachment(id, oldname, newname)
132
132
  if result['ok']
133
133
  self[:_rev] = result['rev']
134
- attachments[newname] = attachments.delete(oldname)
134
+ attachments[newname] = {
135
+ "stub" => true,
136
+ "content_type" => attachments[oldname]['content_type'],
137
+ "length" => attachments[oldname]['length']
138
+ }
135
139
  end
136
140
  result['ok']
137
141
  end
138
142
 
143
+ # Renames an attachment. +oldname+ is the name of the existing attachment
144
+ # and +newname+ is the desired name.
145
+ def rename(oldname, newname)
146
+ if copy(oldname, newname)
147
+ detach(oldname)
148
+ end
149
+ end
150
+
139
151
  # Reloads this document.
140
152
  def reload
141
153
  initialize(database.fetch(id))
@@ -146,18 +158,7 @@ module Cushion
146
158
  # the +dest_rev+ option must be provided.
147
159
  def copy_to(dest_id, opts = {})
148
160
  result = database.copy(id, dest_id, :dest_rev => opts[:rev])
149
- result['ok']
150
- end
151
-
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
160
- result['ok']
161
+ result['rev']
161
162
  end
162
163
 
163
164
  def to_json
@@ -146,15 +146,6 @@ module Cushion
146
146
  parse_response(RestClient.copy("#{@uri}/#{source}", defaults.merge(headers)))
147
147
  end
148
148
 
149
- # Issues a MOVE request to the CouchDB server, moving a document from +source+
150
- # to +destination+. Returns a parsed response body if the +accept+ option
151
- # is set to 'application/json' (the default), otherwise returns the raw
152
- # RestClient response body.
153
- def move(source, destination, headers = {})
154
- defaults = { :accept => "application/json", 'Destination' => destination }
155
- parse_response(RestClient.move("#{@uri}/#{source}", defaults.merge(headers)))
156
- end
157
-
158
149
  # Issues a generic request to the server +path+ with the method set to +verb+.
159
150
  # Accepts +body+ and +headers+ options.
160
151
  def request(verb, path, params = {})
@@ -82,7 +82,7 @@ describe "A Cushion database" do
82
82
 
83
83
  it "should pass extra parameters to CouchDB" do
84
84
  @db.store("_id" => "123")
85
- @db.fetch("123", :revs => true)["_revs"].should.not.be.nil
85
+ @db.fetch("123", :revs => true)["_revisions"].should.not.be.nil
86
86
  end
87
87
 
88
88
  it "should pass headers to CouchDB" do
@@ -176,7 +176,7 @@ describe "A Cushion database" do
176
176
 
177
177
  it "should bulk save documents with #bulk" do
178
178
  count = @db.info["doc_count"]
179
- @db.bulk([{"_id" => "456"},{"_id" => "789"}])["ok"].should.be.true
179
+ @db.bulk([{"_id" => "456"},{"_id" => "789"}]).length.should == 2
180
180
  @db.info["doc_count"].should == count + 2
181
181
  end
182
182
 
@@ -185,7 +185,7 @@ describe "A Cushion database" do
185
185
  @db.store("_id" => "456")
186
186
  count = @db.info["doc_count"]
187
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
188
+ @db.bulk(docs["rows"].map{ |row| row["doc"] }, :delete => true).length.should == 2
189
189
  @db.info["doc_count"].should == count - 2
190
190
  end
191
191
 
@@ -223,6 +223,10 @@ describe "A Cushion database" do
223
223
  @db.view("foo/bar", :keys => ["vince carter"])["rows"].length.should == 1
224
224
  end
225
225
 
226
+ it "should retrieve docs from regular views with #view and split params" do
227
+ @db.view('foo', 'bar', :key => "gomer pyle")["rows"].length.should == 1
228
+ end
229
+
226
230
  it "should perform a conditional GET" do
227
231
  etag = @db.view("foo/bar").etag
228
232
  lambda {
@@ -245,7 +249,7 @@ describe "A Cushion database" do
245
249
  end
246
250
  end
247
251
 
248
- describe "when copying and moving documents" do
252
+ describe "when copying documents" do
249
253
  before do
250
254
  @source = @db.store("_id" => "source", "_attachments" => {
251
255
  "foo.txt" => {
@@ -257,23 +261,12 @@ describe "A Cushion database" do
257
261
  end
258
262
 
259
263
  it "should copy a doc to a new id with #copy" do
260
- @db.copy("source", "source_1")["ok"].should.be.true
264
+ @db.copy("source", "source_1")['rev'].should.not.be.nil
261
265
  lambda { @db.fetch("source_1") }.should.not.raise
262
266
  end
263
267
 
264
268
  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
268
-
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
273
- end
274
-
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
269
+ @db.copy("source", "dest", :dest_rev => @dest["rev"])['rev'].should.not.be.nil
277
270
  @db.fetch("dest")["_attachments"].should.not.be.nil
278
271
  end
279
272
 
@@ -287,18 +280,5 @@ describe "A Cushion database" do
287
280
  :dest_rev => @dest["rev"])["ok"].should.be.true
288
281
  @db.fetch("dest", "bar.txt").should == "Hello World!"
289
282
  end
290
-
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
295
- end
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
303
283
  end
304
284
  end
@@ -119,6 +119,12 @@ describe "A Cushion Document" do
119
119
  @doc.fetch("foo.txt").should == "hello"
120
120
  end
121
121
 
122
+ it "should copy an attachment with #copy" do
123
+ @doc.copy('foo.txt', 'bar.txt').should.be.true
124
+ @doc.attachments['bar.txt'].should.not.be.nil
125
+ @doc.attachments['bar.txt']['content_type'].should == 'text/plain'
126
+ end
127
+
122
128
  it "should rename an attachment with #rename" do
123
129
  @doc.rename("foo.txt", "bar.txt").should.be.true
124
130
  @doc.attachments["foo.txt"].should.be.nil
@@ -136,7 +142,7 @@ describe "A Cushion Document" do
136
142
  it "should copy itself to a new document with #copy_to" do
137
143
  @doc["foo"] = "bar"
138
144
  @doc.save
139
- @doc.copy_to("newdoc").should.be.true
145
+ @doc.copy_to("newdoc").should.not.be.nil
140
146
  @db.fetch("newdoc")["foo"].should == "bar"
141
147
  end
142
148
 
@@ -144,25 +150,8 @@ describe "A Cushion Document" do
144
150
  res = @db.store("_id" => "otherdoc")
145
151
  @doc["foo"] = "bar"
146
152
  @doc.save
147
- @doc.copy_to("otherdoc", :rev => res['rev']).should.be.true
148
- @db.fetch("otherdoc")["foo"].should == "bar"
149
- end
150
-
151
- it "should move itself to a new document with #move_to" do
152
- @doc.merge!("_id" => "123", "foo" => "bar")
153
- @doc.save
154
- @doc.move_to("newdoc").should.be.true
155
- @db.fetch("newdoc")["foo"].should == "bar"
156
- @db.key?("123").should.be.false
157
- end
158
-
159
- it "should move itself to an existing doc with #move_to" do
160
- @doc.merge!("_id" => "123", "foo" => "bar")
161
- res = @db.store("_id" => "otherdoc")
162
- @doc.save
163
- @doc.move_to("otherdoc", :rev => res['rev']).should.be.true
153
+ @doc.copy_to("otherdoc", :rev => res['rev']).should.not.be.nil
164
154
  @db.fetch("otherdoc")["foo"].should == "bar"
165
- @db.key?("123").should.be.false
166
155
  end
167
156
 
168
157
  it "should serialize its attributes with #to_json" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: akdubya-cushion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksander Williams
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-14 00:00:00 -07:00
12
+ date: 2009-03-20 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency