# CouchPillow

Light and comfortable Document wrapper for Couchbase Server.


## Why CouchPillow?

Yet another ORM? Not quite. 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, one can
easily extend this to other NoSQL drivers as long as they `respond_to?`
the `set`, `delete`, `replace`, and `get` methods.


## Features

- Automatic timestamp
- Validation


## Installation

    gem install couchpillow


## How To Use

    require 'couchpillow'

    CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
    doc = CouchPillow::Document.new( { :stuff => 'hello' }, '123' )
    doc.save!
    
    # {
    #   '_type': 'default',
    #   'stuff': 'hello',
    #   'created_at': '2014-07-04 00:00:00 UTC'
    #   'updated_at': '2014-07-04 00:00:00 UTC'
    # }


Retrieving Documents

    doc = CouchPillow::Document.get('123')
    doc.stuff # '123'
  

Overriding `CouchPillow::Document`

    class User < CouchPillow::Document
      type :user
    end

    CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
    doc = User.new( { :email => 'john@email.com' } )
    doc.email # 'john@email.com'
    doc.save!

    # {
    #   '_id': 'fb579b265cc005c47ff420a5c2a15d2b',
    #   '_type': 'user',
    #   'email': 'john@email.com',
    #   'created_at': '2014-07-04 00:00:00 UTC'
    #   'updated_at': '2014-07-04 00:00:00 UTC'
    # }

Using validation

    class User < CouchPillow::Document
      type :user
      validate_presence :email
    end

    CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
    doc = User.new( { :first_name => 'John' } )
    doc.save! # raises ValidationError('email is missing')
    doc.email = 'john@email.com'
    doc.save! # Success!

Using custom validation blocks

    class User < CouchPillow::Document
      type :user
      validate_presence :email
      validate :phone, 'is not a number', lambda { |v| v.is_a? Numeric }
    end

    CouchPillow.db = Couchbase.connect( bucket: 'default', host: 'localhost' )
    doc = User.new
    doc.email = 'john@email.com'
    doc.first_name = 'john'
    doc.phone = '123'
    doc.save! # raises ValidationError('phone is not a number')
    doc.phone = 123
    doc.save! # Success!

What about Design Docs and Views? They 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(:body => { :key => 'john@email.com' }).map do |v|
        new User(v.value, v.id)
      end