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.new  
 => #<CouchRest::Server:0x007fc106660390 @uri="http://127.0.0.1:5984", @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="http://127.0.0.1:5984", @uuid_batch_count=1000>, @host="http://127.0.0.1:5984", @uri="/fubar", @root="http://127.0.0.1:5984/fubar", @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.

 db.all_docs  
 => {"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!

Saturday, August 15, 2015

Ruby on Rails on Couch part 1

I use Ruby on Rails everyday for work, and in the past two years have worked on over 9 rails projects.  Recently, our shop has been turning to CouchDB as our database solution because of the excellent features it provides, so today I'm going to explore the basics of CouchDB's RESTful API. If you'd like to follow along with me, you can instal CouchDB here.

CouchDB is a document based database that stores your data as a JSON document.  This format makes it immediately useful for use in any rails app, as it is quite flexible, compact, and fast.  Most ruby developers will be very familiar with this method.

 JSON.parse response  

This method easily converts the JSON into a hash, which is quite easy to work with in Ruby on Rails. Anyway, before we interact with bring any more ruby into the discussion, lets explore the basic CouchDB API through HTTP methods GET, POST, PUT, and DELETE.  If you have installed CouchDB along with me, you can try this out in your terminal.

 $ curl http://127.0.0.1:5984  
 {"couchdb":"Welcome","uuid":"6f2ab581sb4705y52bd470b1e1242z1v","version":"1.6.1","vendor":{"version":"1.6.1","name":"The Apache Software Foundation"}}  

VoilĂ ! Isn't that neat? Lets try creating a database.

 $ curl -X PUT http://127.0.0.1:5984/fubar  
 {"ok":true}  

Excellent! But how can we gather any info about our db? With another GET request of course.

$ curl http://127.0.0.1:5984/fubar  
 {"db_name":"fubar",  
 "doc_count":0,  
 "doc_del_count":0,  
 "update_seq":0,  
 "purge_seq":0,  
 "compact_running":false,  
 "disk_size":79,  
 "data_size":0,  
 "instance_start_time":"1439347017504450",  
 "disk_format_version":6,  
 "committed_update_seq":0}  

We can even add a record to our database!

$ curl -H 'Content-Type: application/json' -X POST http://127.0.0.1:5984/fubar -d '{"Foo": "Bar"}'  
 {"ok":true,  
 "id":"c33480e7b087402adcf32824d90011e8",  
 "rev":"1-9f991710ef01160088e7f4546a8c0b81"}  

This response gives us some important information.  The "id" is as you can probably guess, the identifier of our JSON document.  The "rev" stands for revision, which CouchDB uses to handle any conflicts.  This allows CouchDB give us eventual consistency.  Lets try reading from our document to see if we actually did anything.

 $ curl http://127.0.0.1:5984/fubar/c33480e7b087402adcf32824d90011e8  
 {"_id":"c33480e7b087402adcf32824d90011e8","_rev":"1-9f991710ef01160088e7f4546a8c0b81","Foo":"Bar"}  

Look at that. Our data is right there! How great is that. It's really simple.  That is what is so beautiful about couch.  At it's core, it's dead simple to use.  You can do everything you need through HTTP. Lets take a look at the database info again.

$ curl http://127.0.0.1:5984/fubar 
{"db_name":"fubar",  
 "doc_count":1,  
 "doc_del_count":0,  
 "update_seq":1,  
 "purge_seq":0,  
 "compact_running":false,  
 "disk_size":4185,  
 "data_size":275,  
 "instance_start_time":"1439347017504450",
 "disk_format_version":6,  
 "committed_update_seq":1}  

Here, you can see the changes to the doc_count, update_seq, disk_size, data_size, and committed_update_seq.  Most of these are self explanatory, although I want to touch on three of the fields.  The update_seq represents the number of updates to the database, and its relative comitted_update_seq represented the number of committed updates. The purge_seq represents the number of purges to the database.  A normal delete operation in CouchDB will not delete the document, only mark it with a flag _deleted=true.  A purge on the other hand will permanently remove references to the document to the database. CouchDB warns that this should only be done as a last resort.  They also warn that in a clustered environment that makes use of the replication features, that a purge should be used on all replicated data.  For now, lets just take a look at the DELETE method.

 $ curl -X DELETE 'http://127.0.0.1:5984/fubar/c33480e7b087402adcf32824d90011e8?rev=1-9f991710ef01160088e7f4546a8c0b81'  
 {"ok":true,  
 "id":"c33480e7b087402adcf32824d90011e8",  
 "rev":"2-5c826aa8dbebbe7df9fc34702ae3dd3e"}  

Bam! That should about cover it.  We can delete the document by using its id and rev in the request.

Well, I think I'm going to conclude here.  My plan for the next few post is to explore the different ruby gems that interact with couch, evaluating the pro's and cons of each.

Cheers!




Monday, August 10, 2015

Obligatory First Post!

Obligatory first post!

Well, that was sort of anticlimactic.  Regardless, here we are.  

Perhaps a little about myself.  

I am a 25 year old software engineer in the wonderful city of San Diego.  I've coded for a little over two and a half years, and am interested primarily in ruby, go, and swift. I am a full stack rails engineer by trade, although I prefer to work on more backend code.  I studied physics at Pepperdine, and still am fascinated by the subject.  

I want this blog to be an outlet for me to share the musings and ideas i have, mostly regarding programming, but also my thoughts about working in IT, physics, and anything that might interest me technology wise.

That is all for now, Cheers!