CouchPillow
CouchPillow is a document integrity tool for Couchbase Documents to make sure that all current and existing documents can work nicely with the current code.
CouchPillow separates itself from the database drivers, making it light and
independent from the implementation. Although it is initially designed to work
with Couchbase Server, it can be easily extended to other NoSQL databases, by
creating a driver that respond_to? the set, delete, replace, and get
methods.
Features
- Automatic id generation.
- Automatic timestamp.
- Built-in and custom data validations.
Installation
gem install couchpillow
How To Use
require 'couchpillow'
class MyDocument < CouchPillow::Document
type :my_document
attribute :stuff
end
CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
doc = CouchPillow::Document.new( { :stuff => 'hello' } )
doc.save!
# {
# '_id': 'my_document::fb579b265cc005c47ff420a5c2a15d2b',
# '_type': 'my_document',
# '_created_at': '2014-07-04 00:00:00 UTC'
# '_updated_at': '2014-07-04 00:00:00 UTC'
# 'stuff': 'hello',
# }
Retrieving Documents:
doc = MyDocument.get('my_document::fb579b265cc005c47ff420a5c2a15d2b')
doc.stuff # 'hello'
Specifying custom id:
class User < CouchPillow::Document
type :user
attribute :email
end
CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
doc = User.new( { :email => '[email protected]' }, '123' )
doc.email # '[email protected]'
doc.save!
# {
# '_id': '123',
# '_type': 'user',
# '_created_at': '2014-07-04 00:00:00 UTC'
# '_updated_at': '2014-07-04 00:00:00 UTC'
# 'email': '[email protected]',
# }
Attributes
Using Attribute Directives:
class User < CouchPillow::Document
type :user
attribute :email do
required
end
attribute :first_name do
type String
end
end
CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
doc = User.new( { :first_name => 'John' } )
doc.save! # raises ValidationError "Attribute 'email' is missing"
doc.email = '[email protected]'
doc.save! # Success!
List of Attribute Directives:
required
Sets this attribute as required. Will raise an error if attribute is missing
upon save! or update!
type(T)
Sets the type of this attribute. Will perform type check if specified.
auto_convert
Enables auto-conversion to the specified type. This gets ignored if type
directive is not specified.
default(&block)
Runs the block to set the default value for this attribute, if it's missing or nil. This is triggered on document creation and save.
content(&block)
Custom validation method to check the value of the attribute. This is useful in cases where you only want certain values to be stored (e.g a number between 1-10 only)
TTL Support
TTL is supported by passing options when saving the document. Using the above example:
doc = User.new( { :email => '[email protected]' } )
doc.save! ttl: 3600
Multiple DB Connections Support
If you have a model that's accessing a different Couchbase bucket, or a
different Couchbase DB cluster entirely, you can specify the connections
via the db directive. Example:
CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
memcached = Couchbase.connect( bucket: 'mymemcache_bucket', host: '128.128.128.128' )
class User < CouchPillow::Document
type :user
attribute :first_name do
type String
end
end
class Token < CouchPillow::Document
type :token
db memcached
attribute :token do
type String
end
end
doc = User.new( { :first_name => 'John' } )
doc.save! # This gets saved to the localhost/bucket
token = Token.new( token: SecureRandom.uuid )
doc.save! # This gets saved to the 128.128.128.128/mymemcache_bucket
You can also specify multiple db directives. The first time the db
directive is called, it sets that connection as the primary connection, as the
above example shows. Any subsequent calls will insert that DB connection as
secondary connections, which will only be trigger on write (save!, update!,
and delete!).
class Token < CouchPillow::Document
type :token
db primary_connection
db migration
db backup
attribute :token do
type String
end
end
This can be useful as part of a migration process where you want to save incoming data to another cluster while keeping the old one active.
Migration
Using rename to rename keys. Useful to maintain document integrity
after a migration.
class User < CouchPillow::Document
rename :username, :nickname
attribute :nickname
end
u = User.new( { :username => 'jdoe' } )
u.nickname # 'jdoe'
Rename triggers per-document basis. You can use this on a separate script that queries each document in the database and updates them, or you can simply use this inside your application code, so it only migrates the document as it reads them.
Design Docs and Views
Design Docs and Views are outside the scope of CouchPillow.
However, given a design doc named my_design_doc and a View named by_email,
that returns documents as values, you can easily use it like this:
CouchPillow.db.design_docs['my_design_doc'].
by_email(:key => '[email protected]').map do |v|
User.new(v.doc, v.id)
end