Class: Analysand::Database
- Inherits:
-
Object
- Object
- Analysand::Database
- Defined in:
- lib/analysand/database.rb
Overview
A wrapper around a CouchDB database in a CouchDB instance.
Databases MUST be identified by an absolute URI; instantiating this class with a relative URI will raise an exception.
Common tasks
Creating a database
vdb = Analysand::Database.create!('http://localhost:5984/videos/',
credentials)
If the database was successfully created, you'll get back a
Analysand::Database instance. If database creation failed, a
DatabaseError containing a CouchDB response will be raised.
You can also instantiate a database and then create it:
vdb = Analysand::Database.new('http://localhost:5984/videos')
vdb.create(credentials) # => #<Response ...>
Dropping a database
Analysand::Database.drop('http://localhost:5984/videos',
credentials)
# => #<Response code=200 ...>
# => #<Response code=401 ...>
# => #<Response code=404 ...>
You can also instantiate a database and then drop it:
db = Analysand::Database.new('http://localhost:5984/videos')
db.drop # => #<Response ...>
You can also use #drop!, which will raise Analysand::CannotDropDatabase
on a non-success response.
Opening a database
vdb = Analysand::Database.new('http://localhost:5984/videos/')
Closing connections
vdb.close
Note that this only closes the connection used for the current thread. If the database object is being used from several threads, there will still be other connections active. To close all connections, you must call #close from all threads that are using the database object.
It is safe to call #close without additional synchronization.
After close returns, you can re-open a connection by calling #get, #put, etc.
Creating a document
doc = { ... }
vdb.put(doc_id, doc, credentials) # => #<Response code=201 ...>
# => #<Response code=403 ...>
# => #<Response code=409 ...>
Any object that responds to #to_json with a JSON representation of itself may be used as the document.
Updating a document
doc = { '_rev' => rev, ... }
vdb.put(doc_id, doc, credentials) # => #<Response code=201 ...>
# => #<Response code=401 ...>
# => #<Response code=409 ...>
You can also use #put!, which will raise Analysand::DocumentNotSaved if the response code is non-success.
begin
vdb.put!(doc_id, doc, credentials)
rescue Analysand::DocumentNotSaved => e
puts "Unable to save #{doc_id}, reason: #{e.response.body}"
end
#put!, if it returns, returns the response.
Deleting a document
vdb.delete(doc_id, rev, credentials) # => #<Response code=200 ...>
# => #<Response code=401 ...>
# => #<Response code=409 ...>
You can also use #delete!, which will raise Analysand::DocumentNotDeleted if the response code is non-success.
Retrieving a document
vdb.get(doc_id, credentials) # => #<Response code=200 ...>
# => #<Response code=401 ...>
# => #<Response code=404 ...>
Note: CouchDB treats forward slashes (/) specially. For document IDs, / denotes a separator between document ID and the name of an attachment. This library makes use of that to implement attachment storage and retrieval (see below).
If you are using forward slashes in document IDs, you MUST encode them (i.e. replace / with %2F).
You can also use #get!, which will raise Analysand::CannotAccessDocument if the response code is non-success.
Reading a view
vdb.view('video/recent', :key => ['member1'])
vdb.view('video/by_artist', :startkey => 'a', :endkey => 'b')
Keys are automatically JSON-encoded, as required by CouchDB.
If you’re running into problems with large key sets generating very long query strings, you can use POST mode (CouchDB 0.9+):
vdb.view('video/by_artist', :keys => many_keys, :post => true)
If you’re reading many records from a view, you may want to stream them in:
vdb.view('video/all', :stream => true)
View data and metadata may be accessed as follows:
resp = vdb.view('video/recent', :limit => 10)
resp.total_rows # => 16
resp.offset # => 0
resp.rows # => an Enumerable
See ViewResponse and StreamingViewResponse for more details.
You can also use view!, which will raise Analysand::CannotAccessView on a non-success response.
Uploading an attachment
vdb.('doc1/attachment', io, {}, credentials)
# => #<Response>
The second argument MUST be an IO-like object. The third argument MAY contain any of the following options:
-
:rev: When specified, this will be used as the rev of the document that will own the attachment. When not specified, no rev will be passed in the request. In order to add attachments to existing documents, then, you MUST pass this option.
-
:content_type: The MIME type of the attachment.
Retrieving an attachment
vdb.('doc1/attachment', credentials) do |resp|
# resp is a Net::HTTPResponse
end
or, if you don’t need that level of control when reading the response body:
vdb.('doc1/attachment', credentials)
# => Net::HTTPResponse
When a block is passed, #get_attachment does not read the response body, leaving that up to the programmer. When a block is not passed, #get_attachment reads the body in full.
Pinging a database
Useful for connection testing:
vdb.ping # => #<Response code=200 ...>
Getting database status
vdb.status # => { "db_name" => "videos", ... }
The returned hash is a parsed form of the JSON received from a GET on the database.
Copying a document
vdb.copy('source', 'destination', credentials)
# => #<Response code=201 ...>
# => #<Response code=401 ...>
# => #<Response code=409 ...>
To overwrite, you’ll need to provide a rev of the destination document:
vdb.copy('source', "destination?rev=#{rev}", credentials)
NOTE: CouchDB 1.5.0 and 1.6.1 expect an unescaped destination document ID.
Acceptable credentials
Every method that interacts with CouchDB has an optional credentials parameter. Two forms of credential are recognized by this class.
-
HTTP Basic authentication: When credentials is a hash of the form
{ :username => "...", :password => "... }
then it will be transformed into an Authorization header for HTTP Basic authentication.
-
Token authentication: When credentials is a string, it is interpreted as a cookie from CouchDB’s Session API. The string is used as the value of a Cookie header.
There are two ways to retrieve a token:
-
Establishing a session. You can use Analysand::Instance#establish_sesssion for this.
-
CouchDB may also issue updated session cookies as part of a response. You can access such cookies using #session_cookie on the response object.
Omitting the credentials argument, or providing a form of credentials not listed here, will result in no credentials being passed in the request.
Thread safety
Database objects may be shared across multiple threads. The HTTP client used by this object (Net::HTTP::Persistent) creates one persistent connection per (uri.host, uri.port, thread) tuple, so connection pooling is also done.
Constant Summary
Constants included from Viewing
Viewing::JSON_VALUE_PARAMETERS
Constants included from Http
Instance Attribute Summary
Attributes included from Http
Class Method Summary collapse
Instance Method Summary collapse
- #create(credentials = nil) ⇒ Object
- #create!(credentials = nil) ⇒ Object
- #drop(credentials = nil) ⇒ Object
- #drop!(credentials = nil) ⇒ Object
-
#initialize(uri) ⇒ Database
constructor
A new instance of Database.
- #json_headers ⇒ Object
- #ping(credentials = nil) ⇒ Object
- #status(credentials = nil) ⇒ Object
Methods included from Writing
#bulk_docs, #bulk_docs!, #copy, #delete, #delete!, #ensure_full_commit, #put, #put!, #put_attachment
Methods included from Viewing
#all_docs, #all_docs!, #do_view_query, #encode_parameters, #expand_view_path, #get_view, #post_view, #return_view, #stream_view, #view, #view!
Methods included from Reading
#get, #get!, #get_attachment, #head
Methods included from Http
#_req, #close, #init_http_client, #set_credentials
Methods included from Errors
Constructor Details
#initialize(uri) ⇒ Database
Returns a new instance of Database.
279 280 281 |
# File 'lib/analysand/database.rb', line 279 def initialize(uri) init_http_client(uri) end |
Class Method Details
.create!(uri, credentials = nil) ⇒ Object
283 284 285 |
# File 'lib/analysand/database.rb', line 283 def self.create!(uri, credentials = nil) new(uri).tap { |db| db.create!(credentials) } end |
.drop(uri, credentials = nil) ⇒ Object
287 288 289 |
# File 'lib/analysand/database.rb', line 287 def self.drop(uri, credentials = nil) new(uri).drop(credentials) end |
Instance Method Details
#create(credentials = nil) ⇒ Object
299 300 301 |
# File 'lib/analysand/database.rb', line 299 def create(credentials = nil) Response.new _put('', credentials) end |
#create!(credentials = nil) ⇒ Object
303 304 305 306 307 |
# File 'lib/analysand/database.rb', line 303 def create!(credentials = nil) create(credentials).tap do |resp| raise ex(DatabaseError, resp) unless resp.success? end end |
#drop(credentials = nil) ⇒ Object
309 310 311 |
# File 'lib/analysand/database.rb', line 309 def drop(credentials = nil) Response.new _delete('', credentials) end |
#drop!(credentials = nil) ⇒ Object
313 314 315 316 317 |
# File 'lib/analysand/database.rb', line 313 def drop!(credentials = nil) drop(credentials).tap do |resp| raise ex(CannotDropDatabase, resp) unless resp.success? end end |
#json_headers ⇒ Object
319 320 321 |
# File 'lib/analysand/database.rb', line 319 def json_headers { 'Content-Type' => 'application/json' } end |
#ping(credentials = nil) ⇒ Object
291 292 293 |
# File 'lib/analysand/database.rb', line 291 def ping(credentials = nil) Response.new _get('', credentials) end |
#status(credentials = nil) ⇒ Object
295 296 297 |
# File 'lib/analysand/database.rb', line 295 def status(credentials = nil) ping(credentials).body end |