= CouchObject

CouchObject is a set of classes to help you talk to CouchDb (http://couchdbwiki.com/) with Ruby.

  • Author: Johan Sørensen, Sebastian Probst Eide
  • Contact: johan (at) johansorensen DOT com
  • Home: http://rubyforge.org/projects/couchobject/
  • Source (Git): http://gitorious.org/projects/couchobject

== Creating, opening and deleting databases

CouchObject::Database is the first interaction point to your CouchDb. Creating a CouchDb database:

>> CouchObject::Database.create!("http://localhost:5984", "mydb")
=> {"ok"=>true}  
>> CouchObject::Database.all_databases("http://localhost:5984")  
=> ["couchobject", "couchobject_test", "foo", "mydb"]  
>> db = CouchObject::Database.open("http://localhost:5984/mydb")  
=> #<CouchObject::Database:0x642fa8 @server=#<CouchObject::Server:0x642ef4 @connection=#<Net::HTTP localhost:8888 open=false>, @port=8888, @uri=#<URI::HTTP:0x321612 URL:http://localhost:5984>, @host="localhost">, @uri="http://localhost:5984", @dbname="mydb">  
>> db.name  
=> "mydb"  
>> CouchObject::Database.delete!("http://localhost:5984", "mydb")  
=> {"ok"=>true}  
>> CouchObject::Database.all_databases("http://localhost:5984").include?("mydb")  
=> false  

=== Interacting with the database

>> db.get("_all_docs")
=> #<CouchObject::Response:0x14ed364 @response=#<Net::HTTPOK 200 OK readbody=true>, @parsed_body={"rows"=>[], "view"=>"_all_docs"}>  

Issueing CouchObject::Database#get, CouchObject::Database#post, CouchObject::Database#put and CouchObject::Database#delete requests will return a CouchObject::Response object

>> db.get("_all_docs").body
=> "{\"view\":\"_all_docs\", \"rows\":[\n\n]}"  
>> db.get("_all_docs").parsed_body  
=> {"rows"=>[], "view"=>"_all_docs"}  
>> db.post("", JSON.unparse({"foo" => "bar"}))  
=> #<CouchObject::Response:0x14d7780 @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F", "ok"=>true}>  
>> db.get("_all_docs").parsed_body  
=> {"rows"=>[{"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F"}], "view"=>"_all_docs"}  
>> db.get("1206189E4496409DAD3818D241F5478F").parsed_body  
=> {"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F", "foo"=>"bar"}  
>> db.delete("1206189E4496409DAD3818D241F5478F").parsed_body  
=> {"_rev"=>548318611, "ok"=>true}  
>> db.get("_all_docs").parsed_body  
=> {"rows"=>[], "view"=>"_all_docs"}  

== The Couch View Requestor

couch_ruby_view_requestor is a JsServer client for CouchDb, allowing you to query documents with Ruby instead of Javascript! All you need to do is pass in a string with something that reponds to #call with one argument (the document):

>> db.post(“temp_view”, “proc { |doc| doc["foo"] =~ /ba/ }”).parsed_body[“rows”]
=> [{“
rev”=>928806717, “id”=>“28D568C5992CBD2B4711F57225A19517”, “value”=>0}, {“rev”=>-1696868121, “id”=>“601D858DB2E298EFC4BBA92A11760D1E”, “value”=>0}, {“rev”=>-2093091288, “id”=>“CABCEB3F2C8B70B3FE24A03FF6AB7A1E”, “value”=>0}]
>> pp db.post(“
temp_view”, “proc { |doc| doc["foo"] =~ /ba/ }”).parsed_body[“rows”]
[{“rev”=>928806717, “id”=>“28D568C5992CBD2B4711F57225A19517”, “value”=>0},
{“rev”=>-1696868121, “id”=>“601D858DB2E298EFC4BBA92A11760D1E”, “value”=>0},
{“rev”=>-2093091288, “id”=>“CABCEB3F2C8B70B3FE24A03FF6AB7A1E”, “value”=>0}]

== The Document object

CouchObject::Document wraps a few things in a nice api. In particular you can use it if you don’t want to deal with hashes all the time (similar to ActiveRecord and so on):

>> doc = CouchObject::Document.new({ "foo" => [1,2], "bar" => true  })
=> #<CouchObject::Document:0x14a7224 @id=nil, @attributes={"foo"=>[1, 2], "bar"=>true}, @revision=nil>  
>> doc["foo"]  
=> [1, 2]  
>> doc.foo  
=> [1, 2]  
>> doc.bar  
=> true  
>> doc.bar?  
=> true  

You can also save a document to the database:

>> doc.new?
=> true  
>> doc.save(db)  
=> #<CouchObject::Response:0x149f358 @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>2030456697, "_id"=>"CAEADDC895AC4D506542A3796CCA355D", "ok"=>true}>  
>> doc.id  
=> "CAEADDC895AC4D506542A3796CCA355D"  

Since CouchObject::Database#get returns a CouchObject::Response object we can convert it into a Document instance easily with CouchObject::Database#to_document:

>> response = db.get(doc.id)
=> #<CouchObject::Response:0x1498b98 @response=#<Net::HTTPOK 200 OK readbody=true>, @parsed_body={"_rev"=>2030456697, "_id"=>"CAEADDC895AC4D506542A3796CCA355D", "foo"=>[1, 2], "bar"=>true}>  
>> the_doc_we_just_saved = response.to_document  
=> #<CouchObject::Document:0x148415c @id="CAEADDC895AC4D506542A3796CCA355D", @attributes={"foo"=>[1, 2], "bar"=>true}, @revision=2030456697>  
>> the_doc_we_just_saved.foo  
=> [1, 2]  
>> doc.foo = "quux"  
=> "quux"  
>> doc.save(db)  
=> #<CouchObject::Response:0x4b0adc @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>1670064786, "_id"=>"B4077269D2DF8433D145DC0702B9791C", "ok"=>true}>

== CouchObject::Persistable

It all started with this module, it maps ruby objects to CouchDb documents.

require 'rubygems'
require 'couch_object'  

class RacingCar  
  include CouchObject::Persistable  

  def initialize  
    @races_won = 0  
  end  

  def won_a_race  
    @races_won += 1  
  end  

  def lost_a_race  
    @races_won -= 1  
  end     
end


>> fast_car = RacingCar.new  
=> #<RacingCar:0x12b630c @races_won=0>

The first time an object is saved to the database, the database uri   
has to be supplied as an argument to the +save+ method:

>> fast_car.save("http://localhost:5984/mydb/")  
=> {:revision=>"2107049750", :id=>"B1D0576DA2E7846550DCD61DCC8CDAE4"}

>> fast_car.won_a_race  
=> 1

Later the object can be saved without supplying a database uri

>> fast_car.save  
=> {:revision=>"3335068490", :id=>"B1D0576DA2E7846550DCD61DCC8CDAE4"}

>> loading_the_fast_car = RacingCar.get(db_address, "B1D0576DA2E7846550DCD61DCC8CDAE4")  
=> #<RacingCar:0x129fddc @races_won=1, @revision="3335068490", @location="http://localhost:5984/mydb", @id="B1D0576DA2E7846550DCD61DCC8CDAE4">

>> loading_the_fast_car.revision == fast_car.revision && loading_the_fast_car.id == fast_car.id  
=> true

To omit having to type in the database uri each single time a new object gets saved, it is possible to set the uri to the database in the class itself:

require 'rubygems'
require 'couch_object'

class Balloon  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'  
end  

>> my_balloon = Balloon.new  
=> #<Balloon:0x12b4b74>  

>> my_balloon.save  
=> {:revision=>"1118628227", :id=>"ASD21"}

>> other_balloon = Balloon.get("123")  
=> #<Balloon:0x12a6024 @id="123", @location="http://localhost:5984/mydb", @revision="1234">  

If you want more control over the way the object is serialized and deserialized (and currently also if the initializer requires arguments) you have to implement and instance method called +to_couch+, which returns a hash of the values you want stored, and a class method called +from_couch+, which should take an array of attributes, which initializes a new object.

require 'rubygems'
require 'couch_object'

class Pizza  
  include CouchObject::Persistable  

  def initialize(owner, slices_eaten)  
    owner == "Sebastian" ? @my_pizza = true : @my_pizza = false  
    @owner_name = owner  
    @slices_left = 10 - slices_eaten  
  end

  def my_pizza?  
    @my_pizza == true  
  end

  def eat  
    @slices_left -= 1  
  end

  def to_couch  
    { :owner => @owner_name,  
      :slices_left => @slices_left }  
  end

  def self.from_couch(attributes)  
    slices_eaten = 10 - attributes["slices_left"]  
    owner = attributes["owner"]  
    new(owner, slices_eaten)  
  end  
end  


>> the_pizza = Pizza.new("Hans",0)  
=> #<Pizza:0x12b2644 @slices_left=10, @owner_name="Hans", @my_pizza=false>

>> the_pizza.my_pizza?  
=> false  
Not our pizza... we better eat it fast before the owner comes.

>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
>> the_pizza.eat  
=> 1  
Let's leave a slice for Hans

>> the_pizza.save("http://localhost:5984/mydb")  
=> {:revision=>"3412312521", :id=>"88781A212BB4676B48B352B209A4D979"}

>> hans_pizza = Pizza.get("88781A212BB4676B48B352B209A4D979","http://localhost:5984/mydb")  
=> #<Pizza:0x12989c4 @id="88781A212BB4676B48B352B209A4D979", @slices_left=1, @location="http://localhost:5984/mydb", @owner_name="Hans", @revision="3412312521", @my_pizza=false>

>> hans_pizza.my_pizza?  
=> false  
Still not my pizza... damnit

>> hans_pizza.eat  
=> 0

Objects that are loaded from the database automatically know where they are stored and therefore don't need the database address as a parameter for the save method  
>> hans_pizza.save  
=> {:revision=>"2414021920", :id=>"88781A212BB4676B48B352B209A4D979"}

It is possible to load all objects of a certain type with the +all+ parameter

require 'rubygems'
require 'couch_object'

class Balloon  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'  
end

>> Balloon.new.save  
>> Balloon.new.save   
>> Balloon.new.save  
>> Balloon.new.save  
>> Balloon.new.save  
>> Balloon.new.save               
>> balloons = Balloon.all  
>> balloons.size  
=> 6  

You can also have timestamps added automatically to your class using the +add_timestamp_for+ method which takes the values +:on_create+ and +:on_update+.

require 'rubygems'
require 'couch_object'

class BankAccount  
  include CouchObject::Persistable  
  add_timestamp_for :on_create, :on_update  
  database 'http://localhost:5984/mydb'  
end

>> my_account = BankAccount.new  
=> #<BankAccount:0x12b5b00>

>> my_account.save  
=> {:revision=>"3733197239", :id=>"C7A492BB92B1308E646E6536020EAE27"}

>> my_account.created_at  
=> Sat Feb 02 17:07:36 -0300 2008

>> my_account.updated_at  
=> Sat Feb 02 17:07:36 -0300 2008

>> my_account.save  
=> {:revision=>"486590755", :id=>"C7A492BB92B1308E646E6536020EAE27"}

>> my_account.created_at  
=> Sat Feb 02 17:07:36 -0300 2008

>> my_account.updated_at  
=> Sat Feb 02 17:07:53 -0300 2008

=== Relations

There are two different types of relations available for persistable objects:

1. Sub objects are made a part of the object itself and stored in the same database document, or
2. Sub objects are stored to the database as separate documents and only loaded when needed.  
(3. The hackish pro way)  

1) If you want to use the first option, you have to make sure each sub class either responds to a +to_json+ method or includes the CouchObject::Persistable module so they can be serialized.
CouchObject will then take care of serialization and initialization for you.

Example:

class House  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'

  def initialize  
    @owner = OwnerPerson.new  
  end  
  attr_accessor :owner  
end

class OwnerPerson  
  include CouchObject::Persistable

  def initialize  
    @name = "Unknown owner"  
  end  
  attr_accessor :name  
end  

>> my_home = House.new  
>> my_home.owner.name = "Sebastian"  
=> "Sebastian"

>> my_home.save  
=> {:revision=>"519758193", :id=>"3E8E2F7A0AE7DACC7D537ECE5220C6FF"}

>> your_home = House.get("3E8E2F7A0AE7DACC7D537ECE5220C6FF")  
>> your_home.owner.name  
=> "Sebastian"  

Make sure to understand the fact that the OwnerPerson object is stored as part of the House document in the database. The OwnerObject will therefore always be read and initialized when the House is loaded from the database!
If your application has a BlogEntry class and each entry can potentially have thousands of comments and you sometimes want to load the blog entries without loading all the comments at the same time then option number 2, described under, is a better choice for you!

2) There are two types of relations where the sub object(s) are NOT stored in the same database document: +has_one+ relationships and +has_many+ relationships:

==== has_many / belongs_to, :as

In cases where your object has many related sub objects that you might not always need when accessing the object this is the route to go.
Relations are specified using the +has_many+ and +belongs_to ,:as+ methods.

The syntax for relations is as follows:

has_many :name_of_relation
belongs_to :name_of_relation, :as => :name_of_the_has_many_relation

To work, a relation has to be defined in both the has_many and belongs_to class!

As CouchDB doesn’t care what we put in it’s documents neither does CouchObject. What you name your relations is therefore completely up to you.
An example says more than a thousand words:

Example:

class House  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'  
  has_many :inhabitants  
  has_many :has  
end

class Inhabitant  
  include CouchObject::Persistable  
  belongs_to :house, :as => :inhabitants  
end

class Book  
  include CouchObject::Persistable  
  belongs_to :is_in, :as => :has  
end

class Bed  
  include CouchObject::Persistable  
  belongs_to :is_in, :as => :has  
end  

The class definitions above allow us to write the following code:

>> my_home = House.new
>> me = Inhabitant.new  
>> a_book = Book.new  
>> a_bed = Bed.new  

>> my_home.inhabitants << me  

>> me.house  
=> #<House:0x126ebd8 @couch_object_inhabitants=[#<Inhabitant:0x126cbd0 @couch_object_house=#<House:0x126ebd8 ...>>]>  

>> my_home.has << a_bed  
>> my_home.has << a_book  

>> a_book.is_in  
=> #<House:0x126ebd8 @couch_object_has=[#<Bed:0x1268dc8 @couch_object_is_in=#<House:0x126ebd8 ...>>, #<Book:0x126ac90 @couch_object_is_in=#<House:0x126ebd8 ...>>], @couch_object_inhabitants=[#<Inhabitant:0x126cbd0 @couch_object_house=#<House:0x126ebd8 ...>>]>

>> a_bed.is_in  
=> #<House:0x126ebd8 @couch_object_has=[#<Bed:0x1268dc8 @couch_object_is_in=#<House:0x126ebd8 ...>>, #<Book:0x126ac90 @couch_object_is_in=#<House:0x126ebd8 ...>>], @couch_object_inhabitants=[#<Inhabitant:0x126cbd0 @couch_object_house=#<House:0x126ebd8 ...>>]>

Saving the master object also saves the children.  
>> my_home.save  
=> {:revision=>"1793606849", :id=>"C65B9837CD572FC66931F12392A3181E"}


>> home_from_db = House.get("C65B9837CD572FC66931F12392A3181E")  
=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">  

All relations are lazily loaded the first time they are needed.  
>> home_from_db.has  
=> [#<Bed:0x1224614 @couch_object_is_in=#<House:0x1229790 @revision="1793606849", @couch_object_has=[...], @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">, @revision="1572453885", @id="37A414CE5440B095C2DF46CEFCBBAF33", @belongs_to_id="C65B9837CD572FC66931F12392A3181E">, #<Book:0x1224358 @couch_object_is_in=#<House:0x1229790 @revision="1793606849", @couch_object_has=[...], @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">, @revision="1604857972", @id="DA67DCB6F4BECE8D8DD9F87F814E8340", @belongs_to_id="C65B9837CD572FC66931F12392A3181E">]  

>> home_from_db.has.size  
=> 2  

>> home_from_db.inhabitants  
=> [#<Inhabitant:0x121f7e0 @couch_object_house=#<House:0x1229790 @revision="1793606849", @couch_object_has=[#<Bed:0x1224614 @couch_object_is_in=#<House:0x1229790 ...>, @revision="1572453885", @id="37A414CE5440B095C2DF46CEFCBBAF33", @belongs_to_id="C65B9837CD572FC66931F12392A3181E">, #<Book:0x1224358 @couch_object_is_in=#<House:0x1229790 ...>, @revision="1604857972", @id="DA67DCB6F4BECE8D8DD9F87F814E8340", @belongs_to_id="C65B9837CD572FC66931F12392A3181E">], @couch_object_inhabitants=[...], @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">, @revision="1062171341", @id="ED5DFCF2E28C2D01AE9D4945434CE587", @belongs_to_id="C65B9837CD572FC66931F12392A3181E">]  

>> home_from_db.inhabitants.first.house == home_from_db  
=> true  

>> home_from_db == my_home  
=> true

===== Setting and removing relations

The following examples use the class definitions used in the example above to show different ways to initiate and end relationships

>> my_home = House.new  
>> me = Inhabitant.new

The relationship can be set either as 

>> my_home.inhabitants << me  
or   
>> me.house = my_home

and ended the following ways:

>> me.house = nil  
or  
>> my_home.inhabitants.remove(me)  

==== has_one / belongs_to

This type of relationship works very much like has_many relationships. The following example shows the difference:

Example:

class Person  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'  
  has_one :life  
end

class Life  
  include CouchObject::Persistable  
  database 'http://localhost:5984/mydb'  
  belongs_to :person, :as => :life  
end  

>> me = Person.new  
=> #<Person:0x1270a3c>  
>> my_life = Life.new  
=> #<Life:0x126eac0>  

>> other_persons_life = Life.new  
=> #<Life:0x126c8b0>  

>> my_life.person == me  
=> true  

Creating the relationship between the "other_persons_life" and "me" removes the connection between "me" and "my_life"  
>> other_persons_life.person = me  
=> #<Person:0x1270a3c @couch_object_has_one_life=[#<Life:0x126c8b0 @couch_object_person=#<Person:0x1270a3c ...>>]>  

>> me.life == other_persons_life  
=> true  

>> me.life == my_life  
=> false  

3) In some cases none of the solutions above completely cover your needs. That’s when the last option comes to your aid.
It might be that you need to load a huge number of different types of relations in one swoop, or you want to load objects that aren’t strictly related to your class at all.
By using the class level method +get_from_view+ from within your class you can load an arbitrary number of objects you can then do whatever you please with.

The method takes the name of the view as the first parameter and a hash of options as an optional second parameter.
The options can be any of the querying options supported by CouchDB (http://www.couchdbwiki.com/index.php?title=HTTP_View_API) in addition to the database uri if it hasn’t been specified on the class level.

Recommended reading:
http://www.couchdbwiki.com/index.php?title=Views
http://www.couchdbwiki.com/index.php?title=View_Collation

==== Stopping relations from being loaded

When adding an object to a has_many relationship all the other objects in the relationship are automatically loaded. In cases where you don't want to access the other relations at all and just want to add a new object, you can use the +do_not_load_has_many_relations+ instance method, which tells the object not to load its relations.
This method call has to be made before the relations are accessed though, or it wont have any effect at all.  

Example:  

>> home_from_db = House.get("C65B9837CD572FC66931F12392A3181E")  
=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">  

Make sure the relations are NOT loaded  
>> home_from_db.do_not_load_has_many_relations  

Normally all relations are lazily loaded the first time they are needed.  
>> home_from_db.has  
=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">  

>> home_from_db.has.size  
=> 0

There is also a method called +do_load_has_many_relations+. But please be aware that relations are only loaded the first time the relations are accessed. We therefore get behavior like this when continuing with the code example from above:  

Reactivate loading of relations  
>> home_from_db.do_load_has_many_relations  

>> home_from_db.has  
=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">  

>> home_from_db.has.size  
=> 0  

As the relations are only loaded the first time they are accessed they wont be loaded again later although loading of relations has been reactivated.  
This feature is helpful in cases like this though:  

>> my_home = House.new  
=> #<House:0x1263f80>  
>> my_home.inhabitants << Inhabitant.new  
>> my_home.has << Book.new << Bed.new  
>> my_home.save  
=> {:id=>"4CDC2355A21DDC4D8887882540A84A14", :revision=>"3659215175"}

>> loaded_home = House.get("4CDC2355A21DDC4D8887882540A84A14")  

We want to add a book to the "has" relation without loading the already saved book and bed  
>> loaded_home.do_not_load_has_many_relations  
=> true  

>> loaded_home.has << Book.new  

From here there are two different routes:  

1) We do not reactivate loading of has_many relations  

>> loaded_home.inhabitants.size  
=> 0

2) We reactivate loading of has_many relations   

>> loaded_home.do_load_has_many_relations  
=> false  

>> loaded_home.inhabitants.size  
=> 1  

==== Deleting objects

Persistable objects can be deleted from the database using the +delete+ method. Deleting an object that has has_many relations will also delete the relations. Deleting an object that is in a belongs_to relation will on the other hand NOT delete its relation!

==== Saving relations

When saving an object that has has_many relations, all its relations are also saved.
When saving an object that is in a belongs_to relationship with a new object, the master object is also saved which then again saves all its has_many relations as well! This is because the child object on which the save command was issued needs its parents ID to be validly saved in a relation, which it can’t get until the parent has been saved.
When saving an object that is in a belongs_to relationship with a previously saved object only the child gets saved.

===== Callbacks.

CouchObject::Persistable performs callbacks by calling the following methods before and after save, create, update and delete:

+before_save+
+after_save+  
+before_create+  
+after_create+  
+before_update+  
+after_update+  
+before_delte+  
+after_delete+  

Example:  

class WithCallbacks  
  include CouchObject::Persistable  
  database 'foo'

  def initialize  
    @calls = []  
  end  
  attr_accessor :calls

  def before_save  
    @calls << "before_save"  
  end  
  def after_save  
    @calls << "after_save"  
  end  
  def before_create  
    @calls << "before_create"  
  end  
  def after_create  
    @calls << "after_create"  
  end  
  def before_update  
    @calls << "before_update"  
  end  
  def after_update  
    @calls << "after_update"  
  end  
  def before_delete  
    @calls << "before_delete"  
  end  
  def after_delete  
    @calls << "after_delete"  
  end  
end  

wc = WithCallbacks.new  
wc.save  
wc.save  
wc.delete  
wc.calls.should == ["before_save",   
                    "before_create",  
                    "after_create",  
                    "after_save",  
                    "before_save",  
                    "before_update",  
                    "after_update",  
                    "after_save",  
                    "before_delete",  
                    "after_delete"]  

=== Smart save

The way a CouchObject instance acts by default is to save itself and all
its relatives regardless of if it needs to be saved or not when the +save+
method is called.

When activating smart save each instance contains a copy of its original
state, and can, based on that, make smart decisions regarding wether or
not it actually needs to save.

Smart save should be used selectively though because keeping a copy of it’s
original state will increase the memory usage drastically for objects that
contain a lot of data! There is also an overhead while initializing the
object when the state is created, although that will in most cases be
rather insignificant. These factors add up quickly though if you are working
with many objects at the same time.

Smart save can either be defined in the class definition:

class SmartClass
  include CouchObject::Persistable  
  smart_save  
end  

instance_with_smart_save_activated = SmartClass.get("foo")

where all instances will receive the smart saving feature by default,
or it can be toggled manually:

class NotSoSmartClass
  include CouchObject::Persistable  
end  

instance_WITHOUT_smart_save_activated = NotSoSmartClass.get("foo")

NotSoSmartClass.smart_save  

instance_WITH_smart_save_activated = NotSoSmartClass.get("bar")

NotSoSmartClass.deactivate_smart_save  

instance_WITHOUT_smart_save_activated_2 = NotSoSmartClass.get("dong")

The same as in the example above can be achieved with the convenience
method +get_with_smart_save+ which takes the same parameters as +get+.
The same example could therefor also be written as:

class NotSoSmartClass
  include CouchObject::Persistable  
end

instance_WITHOUT_smart_save_activated = NotSoSmartClass.get("foo")

instance_WITH_smart_save_activated = NotSoSmartClass.get_with_smart_save("bar")

instance_WITHOUT_smart_save_activated_2 = NotSoSmartClass.get("dong")