1
= CouchObject
2
3
CouchObject is a set of classes to help you talk to CouchDb (http://couchdbwiki.com/) with Ruby.
4
5
* Author: Johan Sørensen, Sebastian Probst Eide
6
* Contact: johan (at) johansorensen DOT com
7
* Home: http://rubyforge.org/projects/couchobject/
8
* Source (Git): http://gitorious.org/projects/couchobject
9
 
10
== Creating, opening and deleting databases
11
12
CouchObject::Database is the first interaction point to your CouchDb. Creating a CouchDb database:
13
14
	>> CouchObject::Database.create!("http://localhost:5984", "mydb")
15
	=> {"ok"=>true}
16
	>> CouchObject::Database.all_databases("http://localhost:5984")
17
	=> ["couchobject", "couchobject_test", "foo", "mydb"]
18
	>> db = CouchObject::Database.open("http://localhost:5984/mydb")
19
	=> #<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">
20
	>> db.name
21
	=> "mydb"
22
	>> CouchObject::Database.delete!("http://localhost:5984", "mydb")
23
	=> {"ok"=>true}
24
	>> CouchObject::Database.all_databases("http://localhost:5984").include?("mydb")
25
	=> false
26
		
27
=== Interacting with the database
28
29
	>> db.get("_all_docs")
30
	=> #<CouchObject::Response:0x14ed364 @response=#<Net::HTTPOK 200 OK readbody=true>, @parsed_body={"rows"=>[], "view"=>"_all_docs"}>
31
		
32
Issueing CouchObject::Database#get, CouchObject::Database#post, CouchObject::Database#put and CouchObject::Database#delete requests will return a CouchObject::Response object
33
		
34
	>> db.get("_all_docs").body
35
	=> "{\"view\":\"_all_docs\", \"rows\":[\n\n]}"
36
	>> db.get("_all_docs").parsed_body
37
	=> {"rows"=>[], "view"=>"_all_docs"}
38
	>> db.post("", JSON.unparse({"foo" => "bar"}))
39
	=> #<CouchObject::Response:0x14d7780 @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F", "ok"=>true}>
40
	>> db.get("_all_docs").parsed_body
41
	=> {"rows"=>[{"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F"}], "view"=>"_all_docs"}
42
	>> db.get("1206189E4496409DAD3818D241F5478F").parsed_body
43
	=> {"_rev"=>-992681820, "_id"=>"1206189E4496409DAD3818D241F5478F", "foo"=>"bar"}
44
	>> db.delete("1206189E4496409DAD3818D241F5478F").parsed_body
45
	=> {"_rev"=>548318611, "ok"=>true}
46
	>> db.get("_all_docs").parsed_body
47
	=> {"rows"=>[], "view"=>"_all_docs"}
48
	
49
== The Couch View Requestor
50
51
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):
52
  
53
  >> db.post("_temp_view", "proc { |doc| doc[\"foo\"] =~ /ba/ }").parsed_body["rows"]
54
  => [{"_rev"=>928806717, "_id"=>"28D568C5992CBD2B4711F57225A19517", "value"=>0}, {"_rev"=>-1696868121, "_id"=>"601D858DB2E298EFC4BBA92A11760D1E", "value"=>0}, {"_rev"=>-2093091288, "_id"=>"CABCEB3F2C8B70B3FE24A03FF6AB7A1E", "value"=>0}]
55
  >> pp db.post("_temp_view", "proc { |doc| doc[\"foo\"] =~ /ba/ }").parsed_body["rows"]
56
  [{"_rev"=>928806717, "_id"=>"28D568C5992CBD2B4711F57225A19517", "value"=>0},
57
   {"_rev"=>-1696868121, "_id"=>"601D858DB2E298EFC4BBA92A11760D1E", "value"=>0},
58
   {"_rev"=>-2093091288, "_id"=>"CABCEB3F2C8B70B3FE24A03FF6AB7A1E", "value"=>0}]
59
60
		
61
== The Document object
62
63
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):
64
65
	>> doc = CouchObject::Document.new({ "foo" => [1,2], "bar" => true  })
66
	=> #<CouchObject::Document:0x14a7224 @id=nil, @attributes={"foo"=>[1, 2], "bar"=>true}, @revision=nil>
67
	>> doc["foo"]
68
	=> [1, 2]
69
	>> doc.foo
70
	=> [1, 2]
71
	>> doc.bar
72
	=> true
73
	>> doc.bar?
74
	=> true
75
		
76
You can also save a document to the database:
77
78
	>> doc.new?
79
	=> true
80
	>> doc.save(db)
81
	=> #<CouchObject::Response:0x149f358 @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>2030456697, "_id"=>"CAEADDC895AC4D506542A3796CCA355D", "ok"=>true}>
82
	>> doc.id
83
	=> "CAEADDC895AC4D506542A3796CCA355D"
84
		
85
Since CouchObject::Database#get returns a CouchObject::Response object we can convert it into a Document instance easily with CouchObject::Database#to_document:
86
87
	>> response = db.get(doc.id)
88
	=> #<CouchObject::Response:0x1498b98 @response=#<Net::HTTPOK 200 OK readbody=true>, @parsed_body={"_rev"=>2030456697, "_id"=>"CAEADDC895AC4D506542A3796CCA355D", "foo"=>[1, 2], "bar"=>true}>
89
	>> the_doc_we_just_saved = response.to_document
90
	=> #<CouchObject::Document:0x148415c @id="CAEADDC895AC4D506542A3796CCA355D", @attributes={"foo"=>[1, 2], "bar"=>true}, @revision=2030456697>
91
	>> the_doc_we_just_saved.foo
92
	=> [1, 2]
93
	>> doc.foo = "quux"
94
	=> "quux"
95
	>> doc.save(db)
96
	=> #<CouchObject::Response:0x4b0adc @response=#<Net::HTTPCreated 201 Created readbody=true>, @parsed_body={"_rev"=>1670064786, "_id"=>"B4077269D2DF8433D145DC0702B9791C", "ok"=>true}>
97
98
99
== CouchObject::Persistable
100
101
It all started with this module, it maps ruby objects to CouchDb documents.
102
103
	require 'rubygems'
104
	require 'couch_object'
105
	
106
	class RacingCar
107
	  include CouchObject::Persistable
108
	  
109
	  def initialize
110
	    @races_won = 0
111
	  end
112
	  
113
	  def won_a_race
114
	    @races_won += 1
115
	  end
116
	  
117
	  def lost_a_race
118
	    @races_won -= 1
119
	  end	
120
	end
121
122
123
	>> fast_car = RacingCar.new
124
	=> #<RacingCar:0x12b630c @races_won=0>
125
126
	The first time an object is saved to the database, the database uri 
127
	has to be supplied as an argument to the +save+ method:
128
129
	>> fast_car.save("http://localhost:5984/mydb/")
130
	=> {:revision=>"2107049750", :id=>"B1D0576DA2E7846550DCD61DCC8CDAE4"}
131
132
	>> fast_car.won_a_race
133
	=> 1
134
135
	Later the object can be saved without supplying a database uri
136
137
	>> fast_car.save
138
	=> {:revision=>"3335068490", :id=>"B1D0576DA2E7846550DCD61DCC8CDAE4"}
139
140
	>> loading_the_fast_car = RacingCar.get(db_address, "B1D0576DA2E7846550DCD61DCC8CDAE4")
141
	=> #<RacingCar:0x129fddc @races_won=1, @revision="3335068490", @location="http://localhost:5984/mydb", @id="B1D0576DA2E7846550DCD61DCC8CDAE4">
142
143
	>> loading_the_fast_car.revision == fast_car.revision && loading_the_fast_car.id == fast_car.id
144
	=> true
145
146
	
147
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:
148
149
	require 'rubygems'
150
	require 'couch_object'
151
152
	class Balloon
153
	  include CouchObject::Persistable
154
	  database 'http://localhost:5984/mydb'
155
	end
156
	
157
	>> my_balloon = Balloon.new
158
	=> #<Balloon:0x12b4b74>
159
	
160
	>> my_balloon.save
161
	=> {:revision=>"1118628227", :id=>"ASD21"}
162
163
	>> other_balloon = Balloon.get("123")
164
	=> #<Balloon:0x12a6024 @id="123", @location="http://localhost:5984/mydb", @revision="1234">
165
	
166
	
167
168
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.
169
170
    require 'rubygems'
171
	require 'couch_object'
172
173
	class Pizza
174
	  include CouchObject::Persistable
175
	
176
	  def initialize(owner, slices_eaten)
177
	    owner == "Sebastian" ? @my_pizza = true : @my_pizza = false
178
	    @owner_name = owner
179
	    @slices_left = 10 - slices_eaten
180
	  end
181
182
	  def my_pizza?
183
	    @my_pizza == true
184
	  end
185
186
	  def eat
187
	    @slices_left -= 1
188
	  end
189
190
	  def to_couch
191
	    { :owner => @owner_name,
192
	      :slices_left => @slices_left }
193
	  end
194
195
	  def self.from_couch(attributes)
196
	    slices_eaten = 10 - attributes["slices_left"]
197
	    owner = attributes["owner"]
198
	    new(owner, slices_eaten)
199
	  end
200
	end
201
	
202
	
203
	>> the_pizza = Pizza.new("Hans",0)
204
	=> #<Pizza:0x12b2644 @slices_left=10, @owner_name="Hans", @my_pizza=false>
205
206
	>> the_pizza.my_pizza?
207
	=> false
208
	Not our pizza... we better eat it fast before the owner comes.
209
210
	>> the_pizza.eat
211
	>> the_pizza.eat
212
	>> the_pizza.eat
213
	>> the_pizza.eat
214
	>> the_pizza.eat
215
	>> the_pizza.eat
216
	>> the_pizza.eat
217
	>> the_pizza.eat
218
	>> the_pizza.eat
219
	=> 1
220
	Let's leave a slice for Hans
221
222
	>> the_pizza.save("http://localhost:5984/mydb")
223
	=> {:revision=>"3412312521", :id=>"88781A212BB4676B48B352B209A4D979"}
224
225
	>> hans_pizza = Pizza.get("88781A212BB4676B48B352B209A4D979","http://localhost:5984/mydb")
226
	=> #<Pizza:0x12989c4 @id="88781A212BB4676B48B352B209A4D979", @slices_left=1, @location="http://localhost:5984/mydb", @owner_name="Hans", @revision="3412312521", @my_pizza=false>
227
228
	>> hans_pizza.my_pizza?
229
	=> false
230
	Still not my pizza... damnit
231
232
	>> hans_pizza.eat
233
	=> 0
234
235
	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
236
	>> hans_pizza.save
237
	=> {:revision=>"2414021920", :id=>"88781A212BB4676B48B352B209A4D979"}
238
239
240
It is possible to load all objects of a certain type with the +all+ parameter
241
242
	require 'rubygems'
243
	require 'couch_object'
244
245
	class Balloon
246
	  include CouchObject::Persistable
247
	  database 'http://localhost:5984/mydb'
248
	end
249
250
	>> Balloon.new.save
251
	>> Balloon.new.save	
252
	>> Balloon.new.save
253
	>> Balloon.new.save
254
	>> Balloon.new.save
255
	>> Balloon.new.save				
256
	>> balloons = Balloon.all
257
	>> balloons.size
258
	=> 6
259
	
260
261
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+.
262
263
	require 'rubygems'
264
	require 'couch_object'
265
266
	class BankAccount
267
	  include CouchObject::Persistable
268
	  add_timestamp_for :on_create, :on_update
269
	  database 'http://localhost:5984/mydb'
270
	end
271
272
	>> my_account = BankAccount.new
273
	=> #<BankAccount:0x12b5b00>
274
275
	>> my_account.save
276
	=> {:revision=>"3733197239", :id=>"C7A492BB92B1308E646E6536020EAE27"}
277
278
	>> my_account.created_at
279
	=> Sat Feb 02 17:07:36 -0300 2008
280
281
	>> my_account.updated_at
282
	=> Sat Feb 02 17:07:36 -0300 2008
283
284
	>> my_account.save
285
	=> {:revision=>"486590755", :id=>"C7A492BB92B1308E646E6536020EAE27"}
286
287
	>> my_account.created_at
288
	=> Sat Feb 02 17:07:36 -0300 2008
289
290
	>> my_account.updated_at
291
	=> Sat Feb 02 17:07:53 -0300 2008
292
293
294
=== Relations
295
296
There are two different types of relations available for persistable objects:
297
298
	1. Sub objects are made a part of the object itself and stored in the same database document, or
299
	2. Sub objects are stored to the database as separate documents and only loaded when needed.
300
	(3. The hackish pro way)
301
	
302
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.
303
CouchObject will then take care of serialization and initialization for you.
304
305
	Example:
306
	
307
	class House
308
	  include CouchObject::Persistable
309
	  database 'http://localhost:5984/mydb'
310
311
	  def initialize
312
	    @owner = OwnerPerson.new
313
	  end
314
	  attr_accessor :owner
315
	end
316
317
	class OwnerPerson
318
	  include CouchObject::Persistable
319
320
	  def initialize
321
	    @name = "Unknown owner"
322
	  end
323
	  attr_accessor :name
324
	end
325
	
326
	>> my_home = House.new
327
	>> my_home.owner.name = "Sebastian"
328
	=> "Sebastian"
329
330
	>> my_home.save
331
	=> {:revision=>"519758193", :id=>"3E8E2F7A0AE7DACC7D537ECE5220C6FF"}
332
333
	>> your_home = House.get("3E8E2F7A0AE7DACC7D537ECE5220C6FF")
334
	>> your_home.owner.name
335
	=> "Sebastian"
336
	
337
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!
338
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!
339
340
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:
341
342
==== has_many / belongs_to, :as
343
344
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.
345
Relations are specified using the +has_many+ and +belongs_to ,:as+ methods.
346
347
The syntax for relations is as follows:
348
349
	has_many :name_of_relation
350
	belongs_to :name_of_relation, :as => :name_of_the_has_many_relation
351
352
To work, a relation has to be defined in both the has_many and belongs_to class!
353
354
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.
355
An example says more than a thousand words: 
356
357
	Example:
358
	
359
	class House
360
	  include CouchObject::Persistable
361
	  database 'http://localhost:5984/mydb'
362
	  has_many :inhabitants
363
	  has_many :has
364
	end
365
366
	class Inhabitant
367
	  include CouchObject::Persistable
368
	  belongs_to :house, :as => :inhabitants
369
	end
370
371
	class Book
372
	  include CouchObject::Persistable
373
	  belongs_to :is_in, :as => :has
374
	end
375
376
	class Bed
377
	  include CouchObject::Persistable
378
	  belongs_to :is_in, :as => :has
379
	end
380
	
381
The class definitions above allow us to write the following code:
382
383
	>> my_home = House.new
384
	>> me = Inhabitant.new
385
	>> a_book = Book.new
386
	>> a_bed = Bed.new
387
	
388
	>> my_home.inhabitants << me
389
	
390
	>> me.house
391
	=> #<House:0x126ebd8 @couch_object_inhabitants=[#<Inhabitant:0x126cbd0 @couch_object_house=#<House:0x126ebd8 ...>>]>
392
	
393
	>> my_home.has << a_bed
394
	>> my_home.has << a_book
395
	
396
	>> a_book.is_in
397
	=> #<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 ...>>]>
398
399
	>> a_bed.is_in
400
	=> #<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 ...>>]>
401
402
	Saving the master object also saves the children.
403
	>> my_home.save
404
	=> {:revision=>"1793606849", :id=>"C65B9837CD572FC66931F12392A3181E"}
405
406
	
407
	>> home_from_db = House.get("C65B9837CD572FC66931F12392A3181E")
408
	=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">
409
	
410
	All relations are lazily loaded the first time they are needed.
411
	>> home_from_db.has
412
	=> [#<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">]
413
	
414
	>> home_from_db.has.size
415
	=> 2
416
	
417
	>> home_from_db.inhabitants
418
	=> [#<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">]
419
	
420
	>> home_from_db.inhabitants.first.house == home_from_db
421
	=> true
422
	
423
	>> home_from_db == my_home
424
	=> true
425
426
427
===== Setting and removing relations
428
429
	The following examples use the class definitions used in the example above to show different ways to initiate and end relationships
430
431
	>> my_home = House.new
432
	>> me = Inhabitant.new
433
434
	The relationship can be set either as 
435
436
	>> my_home.inhabitants << me
437
	or 
438
	>> me.house = my_home
439
440
	and ended the following ways:
441
442
	>> me.house = nil
443
	or
444
	>> my_home.inhabitants.remove(me)
445
		
446
		
447
448
==== has_one / belongs_to
449
450
This type of relationship works very much like has_many relationships. The following example shows the difference:
451
452
	Example:
453
	
454
	class Person
455
	  include CouchObject::Persistable
456
	  database 'http://localhost:5984/mydb'
457
	  has_one :life
458
	end
459
460
	class Life
461
	  include CouchObject::Persistable
462
	  database 'http://localhost:5984/mydb'
463
	  belongs_to :person, :as => :life
464
	end
465
	
466
	>> me = Person.new
467
	=> #<Person:0x1270a3c>
468
	>> my_life = Life.new
469
	=> #<Life:0x126eac0>
470
	
471
	>> other_persons_life = Life.new
472
	=> #<Life:0x126c8b0>
473
	
474
	>> my_life.person == me
475
	=> true
476
	
477
	Creating the relationship between the "other_persons_life" and "me" removes the connection between "me" and "my_life"
478
	>> other_persons_life.person = me
479
	=> #<Person:0x1270a3c @couch_object_has_one_life=[#<Life:0x126c8b0 @couch_object_person=#<Person:0x1270a3c ...>>]>
480
	
481
	>> me.life == other_persons_life
482
	=> true
483
	
484
	>> me.life == my_life
485
	=> false
486
	
487
488
3)	In some cases none of the solutions above completely cover your needs. That's when the last option comes to your aid.
489
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.
490
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.
491
492
The method takes the name of the view as the first parameter and a hash of options as an optional second parameter.
493
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.
494
495
Recommended reading:
496
http://www.couchdbwiki.com/index.php?title=Views
497
http://www.couchdbwiki.com/index.php?title=View_Collation
498
	
499
500
==== Stopping relations from being loaded
501
502
	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.
503
	This method call has to be made before the relations are accessed though, or it wont have any effect at all.
504
	
505
	Example:
506
	
507
	>> home_from_db = House.get("C65B9837CD572FC66931F12392A3181E")
508
	=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">
509
	
510
	Make sure the relations are NOT loaded
511
	>> home_from_db.do_not_load_has_many_relations
512
	
513
	Normally all relations are lazily loaded the first time they are needed.
514
	>> home_from_db.has
515
	=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">
516
	
517
	>> home_from_db.has.size
518
	=> 0
519
520
	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:
521
	
522
	Reactivate loading of relations
523
	>> home_from_db.do_load_has_many_relations
524
	
525
	>> home_from_db.has
526
	=> #<House:0x1229790 @revision="1793606849", @id="C65B9837CD572FC66931F12392A3181E", @location="http://localhost:5984/mydb">
527
	
528
	>> home_from_db.has.size
529
	=> 0
530
	
531
	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.
532
	This feature is helpful in cases like this though:
533
	
534
	>> my_home = House.new
535
	=> #<House:0x1263f80>
536
	>> my_home.inhabitants << Inhabitant.new
537
	>> my_home.has << Book.new << Bed.new
538
	>> my_home.save
539
	=> {:id=>"4CDC2355A21DDC4D8887882540A84A14", :revision=>"3659215175"}
540
541
	>> loaded_home = House.get("4CDC2355A21DDC4D8887882540A84A14")
542
	
543
	We want to add a book to the "has" relation without loading the already saved book and bed
544
	>> loaded_home.do_not_load_has_many_relations
545
	=> true
546
	
547
	>> loaded_home.has << Book.new
548
	
549
	From here there are two different routes:
550
	
551
	1) We do not reactivate loading of has_many relations
552
	
553
	>> loaded_home.inhabitants.size
554
	=> 0
555
556
	2) We reactivate loading of has_many relations 
557
	
558
	>> loaded_home.do_load_has_many_relations
559
	=> false
560
	
561
	>> loaded_home.inhabitants.size
562
	=> 1
563
	
564
565
566
==== Deleting objects
567
568
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!
569
570
571
==== Saving relations
572
573
When saving an object that has has_many relations, all its relations are also saved.
574
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.
575
When saving an object that is in a belongs_to relationship with a previously saved object only the child gets saved.
576
577
578
===== Callbacks.
579
580
CouchObject::Persistable performs callbacks by calling the following methods before and after save, create, update and delete:
581
582
	+before_save+
583
	+after_save+
584
	+before_create+
585
	+after_create+
586
	+before_update+
587
	+after_update+
588
	+before_delte+
589
	+after_delete+
590
	
591
	Example:
592
		
593
	class WithCallbacks
594
	  include CouchObject::Persistable
595
	  database 'foo'
596
597
	  def initialize
598
	    @calls = []
599
	  end
600
	  attr_accessor :calls
601
602
	  def before_save
603
	    @calls << "before_save"
604
	  end
605
	  def after_save
606
	    @calls << "after_save"
607
	  end
608
	  def before_create
609
	    @calls << "before_create"
610
	  end
611
	  def after_create
612
	    @calls << "after_create"
613
	  end
614
	  def before_update
615
	    @calls << "before_update"
616
	  end
617
	  def after_update
618
	    @calls << "after_update"
619
	  end
620
	  def before_delete
621
	    @calls << "before_delete"
622
	  end
623
	  def after_delete
624
	    @calls << "after_delete"
625
	  end
626
	end
627
	
628
	wc = WithCallbacks.new
629
    wc.save
630
    wc.save
631
    wc.delete
632
    wc.calls.should == ["before_save", 
633
                        "before_create",
634
                        "after_create",
635
                        "after_save",
636
                        "before_save",
637
                        "before_update",
638
                        "after_update",
639
                        "after_save",
640
                        "before_delete",
641
                        "after_delete"]
642
    
643
=== Smart save
644
645
The way a CouchObject instance acts by default is to save itself and all
646
its relatives regardless of if it needs to be saved or not when the +save+ 
647
method is called.
648
649
When activating smart save each instance contains a copy of its original
650
state, and can, based on that, make smart decisions regarding wether or
651
not it actually needs to save.
652
653
Smart save should be used selectively though because keeping a copy of it's
654
original state will increase the memory usage drastically for objects that
655
contain a lot of data! There is also an overhead while initializing the
656
object when the state is created, although that will in most cases be 
657
rather insignificant. These factors add up quickly though if you are working
658
with many objects at the same time.
659
660
Smart save can either be defined in the class definition:
661
662
	class SmartClass
663
	  include CouchObject::Persistable
664
	  smart_save
665
	end
666
	
667
	instance_with_smart_save_activated = SmartClass.get("foo")
668
669
where all instances will receive the smart saving feature by default,
670
or it can be toggled manually:
671
672
	class NotSoSmartClass
673
	  include CouchObject::Persistable
674
	end
675
	
676
	instance_WITHOUT_smart_save_activated = NotSoSmartClass.get("foo")
677
678
	NotSoSmartClass.smart_save
679
	
680
	instance_WITH_smart_save_activated = NotSoSmartClass.get("bar")
681
682
	NotSoSmartClass.deactivate_smart_save
683
	
684
	instance_WITHOUT_smart_save_activated_2 = NotSoSmartClass.get("dong")
685
686
The same as in the example above can be achieved with the convenience 
687
method +get_with_smart_save+ which takes the same parameters as +get+.
688
The same example could therefor also be written as:
689
690
	class NotSoSmartClass
691
	  include CouchObject::Persistable
692
	end
693
694
	instance_WITHOUT_smart_save_activated = NotSoSmartClass.get("foo")
695
696
	instance_WITH_smart_save_activated = NotSoSmartClass.get_with_smart_save("bar")
697
698
	instance_WITHOUT_smart_save_activated_2 = NotSoSmartClass.get("dong")