Friday, September 4, 2015

Ruby on Rails on Couch part 2

Welcome Back.

In my last post Ruby on Rails on Couch part 1, I explored the basics of CouchDB's RESTful HTTP API.  We found that we could use standard and simple HTTP methods to create our database, get info about our database, create documents in our database, update those documents, delete those documents, and even delete out database.  Some of the more advanced features of couch, like replication, we will cover at a later date.  Now that we are familiar with the basics of CouchDB, I think its time to see what our wonderful open source community has to offer us.

The most simple solution in gem form is none other than CouchRest. With a self professed slogan like "Couch, close to the metal", who can argue? This gem is a very bare bones approach to dealing with the CouchDB API.

Let's dive right in!

 server =  
 => #<CouchRest::Server:0x007fc106660390 @uri="", @uuid_batch_count=1000>  

Well that is nice! Now our server has been wrapped up into a nice and lightweight server object. Now lets try creating a database.

 db = server.database!('fubar')  
 => #<CouchRest::Database:0x007fb781fc0158 @name="fubar", @server=#<CouchRest::Server:0x007fb78209d6e8 @uri="", @uuid_batch_count=1000>, @host="", @uri="/fubar", @root="", @streamer=#<CouchRest::Streamer:0x007fb781fbb680 @default_curl_opts="--silent --no-buffer --tcp-nodelay -H \"Content-Type: application/json\"">, @bulk_save_cache=[], @bulk_save_cache_limit=500>  

Isn't that neat? What's more, now we can add documents to the database at will, using a method on the database object.  Let's investigate.

 db.save_doc '_id' => '1', 'first_name' => 'Sean', 'last_name' => 'Cook'  
 => {"ok"=>true, "id"=>"1", "rev"=>"1-330e7cd6a8403f3b716527cbd03477f4"}  

That saves us a decent amount of typing out the full url and using curl to access the database though the HTTP API.  CouchRest handles all of that for us, saving us the headache of searching a large URL for a typo.  Now we can just look at the keys and values of the doc we want to give.  What happens when we try to save another document with the same ID?

 db.save_doc '_id' => '1', 'first_name' => 'Foo', 'last_name' => 'Bar'  
 RestClient::Conflict: 409 Conflict  

As expected, the 409 response is raised as an exception, which can now be handled however you desire using rescue!  What happens if we try to save a doc without an id?

 db.save_doc 'first_name' => 'Foo', 'last_name' => 'Bar'  
 => {"ok"=>true, "id"=>"952c782924bbdfb6afa08de89265a21a", "rev"=>"1-4ccd21e03116a2033a0ac3ffd1f0c324"}  

The document gets created, but since we didn't specify an id, couch auto generates a unique ID.  Couch recommends that we use supply our our ID's if we can guarantee uniqueness.  For instance, for users, a good idea for the ID is an email, as they are guaranteed to be unique.

So the next question that remains is how do we retrieve the docs from our database?  Well, that depends on what documents we want to get.  Let's start off with all of them.

 => {"total_rows"=>2, "offset"=>0, "rows"=>[{"id"=>"1", "key"=>"1", "value"=>{"rev"=>"1-330e7cd6a8403f3b716527cbd03477f4"}}, {"id"=>"952c782924bbdfb6afa08de89265a21a", "key"=>"952c782924bbdfb6afa08de89265a21a", "value"=>{"rev"=>"1-4ccd21e03116a2033a0ac3ffd1f0c324"}}]}  

How about if we want to find a single doc? Normally we do that with a get request, and CouchRest::Database provides us with a simple get method that does exactly that.

 db.get '1'  
 => #<CouchRest::Document _id: "1", _rev: "1-330e7cd6a8403f3b716527cbd03477f4", first_name: "Sean", last_name: "Cook">  

Again, really simple.  There's really no bullshit when it comes to CouchRest, it's so straightforward. CouchRest just gets the job done. It is a very unobtrusive, lightweight, and minimal gem, that does it's job very well.

In my next post, I plan on continuing to investigate CouchRest, and how it fits in with a real web application. Stay tuned!