<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>The iNK blot</title>
 <link href="http://novemberkilo.com/atom.xml" rel="self"/>
 <link href="http://novemberkilo.com/"/>
 <updated>2010-07-04T05:28:31-07:00</updated>
 <id>http://novemberkilo.com/</id>
 <author>
   <name>Navin Keswani</name>
   <email>navin@novemberkilo.com</email>
 </author>
 
 <entry>
   <title>Django, Grappelli and Piston!</title>
   <link href="http://novemberkilo.com/2010/07/Adventures-in-Django"/>
   <updated>2010-07-01T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/07/Adventures-in-Django</id>
   <content type="html">&lt;p&gt;After learning Ruby and Rails for a few months, my first commercial gig involved building the server side components of an iPhone application using Python and Django.  In the words of Morpheus, &lt;i&gt;&amp;#8220;Fate, it seems, is not without a sense of irony!&amp;#8221;&lt;/i&gt; Luckily for me, a lot of what I had learned in Ruby land ported across to this project and my relative inexperience at this point helped &amp;#8211; I didn&amp;#8217;t have a lot of Rails-muscle-memory to unlearn!&lt;/p&gt;
&lt;p&gt;For context, I was required to build a website that would be used for basic &lt;span class=&quot;caps&quot;&gt;CRUD&lt;/span&gt; (Create, Read, Update, Delete) management of the assets that the iPhone application would present.  I also had to build an &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; that the iPhone application would call to update its assets.&lt;/p&gt;
&lt;h3&gt;The setup&lt;/h3&gt;
&lt;p&gt;I used &lt;a href=&quot;http://pypi.python.org/pypi/virtualenv&quot;&gt;&lt;code&gt;virtualenv&lt;/code&gt;&lt;/a&gt; to sandbox the app. &lt;code&gt;virtualenv&lt;/code&gt; allows fine-grained control of the Python libraries, versions, etc. used in constructing the app &amp;#8211; and the move to a production environment is then trivial. Also, it allows for different environments to coexist on your development machine without contaminating each other.  I&amp;#8217;ve noticed that &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;&lt;code&gt;rvm&lt;/code&gt;&lt;/a&gt; is providing Rubyists with a similar experience.&lt;/p&gt;
&lt;h3&gt;Admin pages&lt;/h3&gt;
&lt;p&gt;Django generates admin pages by default and if all you need is basic &lt;span class=&quot;caps&quot;&gt;CRUD&lt;/span&gt; maintenance of your database, these do a terrific job. So as to jazz up the presentation, I used &lt;a href=&quot;http://code.google.com/p/django-grappelli/&quot;&gt;grapelli.&lt;/a&gt;  The main problem I ran into was general confusion with the set up of templates.  Here&amp;#8217;s what we ended up doing:  In &lt;code&gt;settings.py&lt;/code&gt; set &lt;code&gt;ADMIN_MEDIA_PREFIX='/site-media/'&lt;/code&gt; and make sure that the media folder of grappelli is copied over to a folder &lt;code&gt;site-media&lt;/code&gt; in the project.  Then start &lt;code&gt;runserver&lt;/code&gt; by:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;       &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;manage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runserver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adminmedia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`pwd`&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Tidy file paths&lt;/h3&gt;
&lt;p&gt;One of the more interesting problems with this project was that I needed to save uploaded media files in a directory corresponding to the &lt;code&gt;id&lt;/code&gt; of the object to which they were associated.  This would allow the local filesystem to be replicated on the iPhone and, knowing the structure of file paths would  allow for efficient searching for media files.  The issue here is that an object does not have an &lt;code&gt;id&lt;/code&gt; until it has been saved.&lt;/p&gt;
&lt;p&gt;Our first approach was to overload the &lt;code&gt;save&lt;/code&gt; method by first calling the real save method, then redoing the file paths using the resulting &lt;code&gt;id&lt;/code&gt; and then saving again. This was very messy and caused for duplicate objects to be created when importing from a &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt;.  However, this is a pattern that I found in a few places out there so here it is incase it is useful:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# Overload the save method so that we get the id of the parent object &lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# move media files from tmp to category_thumbnails/category_id/&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Call the &amp;quot;real&amp;quot; save() method.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thumbnail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tmp_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;tmp/&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Transfer the contents of the tmp directory&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dest_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;category_thumbnails/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# delete the dest_path if it exists&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;shutil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rmtree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ignore_errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;shutil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thumbnail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Now update the database entry with the new filename&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The solution that we ended up going with involved making a &lt;code&gt;guid&lt;/code&gt; and then using something like this to set up the file path:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;category_thumbnail_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;category/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;thumbnail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upload_to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category_thumbnail_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Importing from a &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Import from &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; was frighteningly simple &amp;#8211; the following two step process got me there:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Line up the fields and use &lt;code&gt;get_or_create&lt;/code&gt; to either create the object or identify duplicates&lt;/li&gt;
	&lt;li&gt;Once the object has been created, use &lt;code&gt;add&lt;/code&gt; to add in associated objects that are in a many-to-many relationship with the object&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;		
&lt;span class=&quot;c&quot;&gt;# First read in a line from the file and set fields of your object &lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;import_file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# skip header line&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]:&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sub_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# etc. ...&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Next use get_or_create to create the object &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Note that duplicates detected when both title and address match&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Asset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_or_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;sub_title&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;s&quot;&gt;&amp;#39;start_date&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;s&quot;&gt;&amp;#39;end_date&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;s&quot;&gt;&amp;#39;publish&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;publish&lt;/span&gt;
			&lt;span class=&quot;c&quot;&gt;# etc. ...&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
				
&lt;span class=&quot;c&quot;&gt;# And here is how you add associated objects that are in many-to-many relationships with your object&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Created=&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        	&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; and django-piston&lt;/h3&gt;
&lt;p&gt;Need a RESTful &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; that responds in &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;? &lt;a href=&quot;http://bitbucket.org/jespern/django-piston/wiki/Home&quot;&gt;Django-piston&lt;/a&gt; to the rescue!  It took me the better part of a day of looking at some examples and reading the documentation to get to understand it but once I got the simplicity of the django-piston framework, I had an &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; in no time flat! I won&amp;#8217;t elaborate on this any further &amp;#8211; I found that the framework comes with excellent supporting code snippets and the interested reader should simply work through these.&lt;/p&gt;
&lt;h3&gt;Tricks for young players&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s one that I think you only learn from experience! The system generated timestamp associated to an object need not be unique nor represent the order in which the object was entered. Implement an index that increments on every save to the database to achieve this&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DBstate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# Counter that is incremented on every save to the database&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# Used when calling the API to specify the state of the DB on the iPhone&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;save_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IntegerField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Of course you will need to overload each object&amp;#8217;s &lt;code&gt;save&lt;/code&gt; method to implement this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# set db_count&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DBstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
		&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_count&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SaveCounter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DoesNotExist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DBstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
		&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_count&lt;/span&gt;
			
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And this is definitely for fellow newbies &amp;#8211; be very careful about the difference between using &lt;i&gt;functions&lt;/i&gt; and &lt;i&gt;return values&lt;/i&gt; when setting default values for fields. For instance,&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uuid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uuid1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;editable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;will result in &lt;code&gt;uuid.uuid1().hex&lt;/code&gt; being called once and its &lt;i&gt;return value&lt;/i&gt; being used as the default value for the &lt;code&gt;guid&lt;/code&gt; of all instances of the object.  On the other hand, if you use the &lt;i&gt;function&lt;/i&gt; only when specifying the default (note the missing parentheses):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uuid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uuid1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;editable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;then it will be called every time a default value is needed and each object will have a different &lt;code&gt;guid&lt;/code&gt;.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>The story of this blog</title>
   <link href="http://novemberkilo.com/2010/06/Story-of-the-blog"/>
   <updated>2010-06-01T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/06/Story-of-the-blog</id>
   <content type="html">&lt;p&gt;Until recently I wasn&amp;#8217;t much of a blogger.  Not withstanding a couple of articles on &lt;i&gt;trust ratings,&lt;/i&gt; I didn&amp;#8217;t feel like I had anything to say that was profound enough to publish (still don&amp;#8217;t but do read on!). I had set up something on blogger.com but was using it more as an OpenID server than anything else!&lt;/p&gt;
&lt;p&gt;When I started my return to development, I began to appreciate how valuable it is to quickly document a trick, idea, or discovery. Googling for help when I was looking to get unstuck from a code related problem invariably lead me to posts of other developers.  I also noticed that a lot of people in the Ruby and Python communities use their a blog as a mechanism for establishing themselves as professionals &amp;#8211; a GitHub (or google code) account and a blog appear to be the business cards of the developer.  So, I set out to resurrect &lt;strong&gt;the iNK blot&lt;/strong&gt; with the intention of writing about my journey back to development, and, to document tips and tricks that other developers might find useful.&lt;/p&gt;
&lt;p&gt;I looked around a bit and found that since I had mucked around with blogger, there were several options for creating quick and easy blogs.  I checked out the usual suspects including Wordpress, Posterous and Tumblr, and I also saw several references in the Ruby community to the &lt;i&gt;blog like a hacker&lt;/i&gt; approach.  I guess it depends on what you are setting out to do but my simple take on things is that if you want to write prose, throw in images, videos, etc., then a service like Posterous or Tumblr is probably what you need.  Editing a blog is easy on these platforms.  You can concentrate on the content and never worry about hosting issues, but you also need to abdicate control of the minutiae of the style in which your pages are presented.  If you want to present code blocks and get fancy with the features of HTML5 and CSS then you will likely find these services to be too constraining.&lt;/p&gt;
&lt;p&gt;Anyway, I set myself a project to investigate further.  I wanted to know more about what it would take to build a blog using Ruby tools and I was curious about whether this would then be too complicated and turn out to get in the way of writing &amp;#8211; i.e. would it be a productivity blocker.&lt;/p&gt;
&lt;p&gt;I started with the awesomely tiny &lt;a href=&quot;http://cloudhead.io/toto&quot;&gt;toto&lt;/a&gt; which I discovered in an &lt;a href=&quot;http://www.rubyinside.com/deploy-blog-with-toto-and-heroku-2962.html&quot;&gt;article&lt;/a&gt; by Peter Cooper on Ruby Inside. Toto will get you &lt;b&gt;blogging in 10 seconds!&lt;/b&gt;  It is minimalist in its approach, elegant, and it integrates neatly with heroku and git.  I had a lot of fun playing with it and when I noticed that it is based on &lt;a href=&quot;http://github.com/adamwiggins/scanty&quot;&gt;Scanty,&lt;/a&gt; I went off to see what this was about. Right about at this time I was also curious about &lt;a href=&quot;http://twitter.com/defunkt&quot;&gt;Chris Wanstrath&amp;#8217;s&lt;/a&gt; template language &lt;a href=&quot;http://github.com/defunkt/mustache&quot;&gt;Mustache&lt;/a&gt; and lightweight alternatives to Rails like &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; and, found Scanty&amp;#8217;s cousin &lt;a href=&quot;http://github.com/juvenn/hackpad&quot;&gt;Hackpad&lt;/a&gt; which uses both Sinatra and Mustache.  Unfortunately, I found the scantiness of documentation on Hackpad to thwart my meager Ruby powers &amp;#8211; I found it to be not so easy to set up after all.&lt;/p&gt;
&lt;p&gt;The aforementioned &lt;a href=&quot;http://www.rubyinside.com/&quot;&gt;Ruby Inside&lt;/a&gt; article also made reference to &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll,&lt;/a&gt; mentioning that it &lt;i&gt;includes a blog-like system but at heart is designed to cope with full sites.&lt;/i&gt; Well, Jekyll is very well &lt;a href=&quot;http://wiki.github.com/mojombo/jekyll/&quot;&gt;documented&lt;/a&gt; and owing to its connections with GitHub (&lt;a href=&quot;http://github.com/mojombo&quot;&gt;Tom Preston-Werner,&lt;/a&gt; author of Jekyll, is also a co-founder of GitHub), comes with many &lt;a href=&quot;http://wiki.github.com/mojombo/jekyll/sites&quot;&gt;examples&lt;/a&gt; of its use.  It is used by GitHub to power its &lt;a href=&quot;http://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; feature that allows for publishing content in a GitHub repository to the web. Tom has written about his motivation and experience with creating Jekyll in the article, &lt;a href=&quot;http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html&quot;&gt;&amp;#8220;Blogging like a hacker&amp;#8221;&lt;/a&gt; and, presumably, is attributed with coining the phrase.&lt;/p&gt;
&lt;p&gt;Eventually, I settled on Jekyll because I liked the fact that it is actively used and supported by so many of the GitHub community.  I looked around the &lt;a href=&quot;http://wiki.github.com/mojombo/jekyll/sites&quot;&gt;Sites&lt;/a&gt; list in the Jekyll wiki pages and settled on &lt;a href=&quot;http://al3x.net/&quot;&gt;Alex Payne&amp;#8217;s weblog&lt;/a&gt; as a starting point. Incidentally, I had no idea at the time that I was borrowing from such as strong member of the tech community &amp;#8211; if you want to know more, check out his latest venture &lt;a href=&quot;http://banksimple.net/&quot;&gt;BankSimple.&lt;/a&gt; I had a prototype going in a few hours and found that rolling in google analytics, disqus comments and fonts from Typekit was ridiculously easy. By the end of the day I was up on GitHub pages and happily blogging like a hacker! The only hit to productivity appears to be that I have not yet settled on a text editor!&lt;/p&gt;
&lt;p&gt;When I started writing the post on the &lt;a href=&quot;http://novemberkilo.com/2010/05/Flickr-notifier/&quot;&gt;flickr-notifier,&lt;/a&gt; I wanted to put up code snippets and so went looking around for examples of how to do this.  Since then I have used &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; by &lt;a href=&quot;http://ascarter.net/&quot;&gt;Andrew Carter.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As I use Jekyll I am beginning to better understand Peter Cooper&amp;#8217;s comment that Jekyll is designed to cope with full sites.  I now see how to use Jekyll to create and easily maintain a static (i.e. not database driven) website.  I am pleasantly surprised by this side-effect!  See this &lt;a href=&quot;http://articles.sitepoint.com/article/jekyll-sites-made-simple&quot;&gt;post&lt;/a&gt; by Simon Pascal Klein for more on this topic.&lt;/p&gt;
&lt;p&gt;Since learning about Jekyll I have heard of similar static-site generators such as &lt;a href=&quot;http://nanoc.stoneship.org/&quot;&gt;nanoc&lt;/a&gt; and having spent some time in Python/Django land, run into Jekyll&amp;#8217;s evil Python based twin, &lt;a href=&quot;http://github.com/lakshmivyas/hyde&quot;&gt;Hyde!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Things I would like to do on the topic of site generators:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Play around with Jekyll &amp;#8211; look into replacing its Liquid template system with Mustache for instance&lt;/li&gt;
	&lt;li&gt;Learn more about nanoc and better understand what it does differently from Jekyll&lt;/li&gt;
	&lt;li&gt;Revisit &lt;a href=&quot;http://github.com/juvenn/hackpad&quot;&gt;Hackpad&lt;/a&gt; &amp;#8211; see if it is suited to generating lightweight dynamic websites&lt;/li&gt;
&lt;/ul&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>A Flickr notifier app</title>
   <link href="http://novemberkilo.com/2010/05/Flickr-notifier"/>
   <updated>2010-05-09T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/05/Flickr-notifier</id>
   <content type="html">&lt;p&gt;I am a daily user of &lt;a href=&quot;http://www.flickr.com/novemberkilo&quot;&gt;Flickr,&lt;/a&gt; owing mainly to my participation in a Project 365 (post a picture for everyday of 2010). Not having attained enlightment, I check my photostream several times a day for comments or view stats etc. It&amp;#8217;s obvious then that I set myself the task of using the Flickr &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; to make a nifty notifier of activity on a Flickr photostream. Here are some of the main things I learned from the experience.&lt;/p&gt;
&lt;p&gt;The following were the requirements that I set myself for this project:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Should notify the user of new comments&lt;/li&gt;
	&lt;li&gt;Provide a summary of activity on their photostream&lt;/li&gt;
	&lt;li&gt;Use &lt;a href=&quot;http://growl.info/&quot;&gt;Growl&lt;/a&gt; as the notification mechanism&lt;/li&gt;
	&lt;li&gt;Use Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initially I thought I would need the Growl &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; in its full glory.  I had recently discovered &lt;a href=&quot;http://macruby.org&quot;&gt;macruby&lt;/a&gt; and noticed a sample XCode project that showed macruby working with Growl.  So, I started out aiming to build the app using macruby.  Having seen macruby and Growl playing well together, I set about locating a ruby library that implemented Flickr &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; calls.  The Flickr &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; &lt;a href=&quot;http://www.flickr.com/services/api/&quot;&gt;documentation&lt;/a&gt; mentions &lt;code&gt;flickr-ruby&lt;/code&gt; &lt;code&gt;rflickr&lt;/code&gt; and &lt;code&gt;flickr.rb&lt;/code&gt; and so I set about checking these out.&lt;/p&gt;
&lt;p&gt;I spent most of my time with &lt;code&gt;flickr.rb&lt;/code&gt; and got very stuck with getting the &lt;a href=&quot;http://www.flickr.com/services/api/auth.howto.desktop.html&quot;&gt;authentication workflow&lt;/a&gt; going.  The Flickr &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; uses an OAuth styled approach that never requires a username and password but does require some clever shunting back and forth of &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; keys, shared secrets and frobs before a token is issued.  Because my app needed to make authenticated &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; calls, I had to find a library whose authentication methods would be accessible to this newbie.  And this is how I found &lt;a href=&quot;http://github.com/hanklords/flickraw&quot;&gt;flickraw.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here are some of the main features of flickraw:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Small single file: flickraw.rb is less than 300 lines&lt;/li&gt;
	&lt;li&gt;Uses introspection so that changes to the API will not require an update of flickraw&lt;/li&gt;
	&lt;li&gt;Ruby syntax similar to the flickr api&lt;/li&gt;
	&lt;li&gt;Flickr authentication&lt;/li&gt;
	&lt;li&gt;Photo upload&lt;/li&gt;
	&lt;li&gt;Proxy support&lt;/li&gt;
	&lt;li&gt;Delayed library loading (for rails users)&lt;/li&gt;
	&lt;li&gt;Flickr URL helpers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Flickraw has excellent &lt;a href=&quot;http://hanklords.github.com/flickraw/&quot;&gt;documentation&lt;/a&gt; and I found it to be simple and fun to use.  It uses &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; internally and so allows for dot.lookup  syntax to access attributes.  I spent some time with flickraw in &lt;code&gt;irb&lt;/code&gt; before understanding all this &amp;#8230; but that was fun too! The following is a snippet from my code that illustrates the use of flickraw &amp;#8211; keep in mind that the user has been authenticated at this point.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;recent_activity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flickr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userPhotos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:timeframe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeframe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;recent_activity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;      
      &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;comment&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@displayed_comments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commentid&lt;/span&gt;
              &lt;span class=&quot;vi&quot;&gt;@displayed_comments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commentid&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Comment: &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;fave&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Added as a favorite&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;User: &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;time_added&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dateadded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time_added&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now unfortunately, macruby 0.5 did not play well with flickraw.  Loading up the flickraw gem resulted in a message about not supporting native extensions yet.  Not knowing how to fix this, I looked around some more and came across the far less complex, command line version of Growl.  &lt;code&gt;growlnotify&lt;/code&gt; ships with the Growl disk image (for mac os x) and allows for a very simple way of popping up Growl bubbles.  More information on &lt;code&gt;growlnotify&lt;/code&gt; can be found &lt;a href=&quot;http://growl.info/documentation/growlnotify.php&quot;&gt;here.&lt;/a&gt;  The following is a snippet from my code that demonstrates how to use it (string interpolation being used here of course).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt; &lt;span class=&quot;sb&quot;&gt;`growlnotify &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sticky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-s&amp;#39;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt; --image &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;icon_filename&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt; -m &amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Thanks mainly to flickraw, I had a lot of fun with this, my first project with ruby.  Screenshots available from the Flickr App Garden &lt;a href=&quot;http://www.flickr.com/services/apps/72157623885594952/&quot;&gt;here&lt;/a&gt; and the app itself is on github &lt;a href=&quot;http://github.com/novemberkilo/flickr-notifier&quot;&gt;here.&lt;/a&gt;  I hope you check them out and give me your feedback.  Time permitting I will try again with macruby 0.6 &amp;#8211; I&amp;#8217;d like to make the installation and setup a little more user-friendly.&lt;/p&gt;
&lt;p&gt;In my next post I expect to write about the second project I set myself &amp;#8211; constructing this blog using a Ruby static site generator.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Get to know the Ruby community</title>
   <link href="http://novemberkilo.com/2010/04/Virtual-and-physical-networks"/>
   <updated>2010-04-26T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/04/Virtual-and-physical-networks</id>
   <content type="html">&lt;h1&gt;I like to watch and listen&lt;/h1&gt;
&lt;p&gt;I have benefited greatly from listening in on the chatter of Rubyists on twitter and from connecting with my local Rails community.  It&amp;#8217;s been a fantastic way of tuning into what&amp;#8217;s new and interesting, getting connected with the community, and beginning to understand the culture of Ruby and Rails. I recommend it whole heartedly to anyone starting out.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not a heavy user of social networks &amp;#8211; I am not a Facebook user and am moderately active on &lt;a href=&quot;http://www.twitter.com/novemberkilo&quot;&gt;twitter.&lt;/a&gt; I think the main reason I am unhappy with social networks is their poor signal to noise ratio  and can say that for the most part, the Rubyists I follow provide entertaining and useful information.  It feels a little weird to be eavesdropping without the (explicit) knowledge of the primary participants in the conversation but this is, after all, a central tenet of virtual social networks!&lt;/p&gt;
&lt;p&gt;Here are a few things that I did to plug into the Ruby community:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I built a list of Rubyists and news sources by starting with &lt;a href=&quot;http://twitter.com/peterc&quot;&gt;@peterc&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/defunkt&quot;&gt;@defunkt&lt;/a&gt; and checking out their lists to see who they follow.  I picked @peterc because I read his book and enjoyed it very much (see my &lt;a href=&quot;/2010/04/Books-and-tutorials/&quot;&gt;previous&lt;/a&gt; post) and I think I got to @defunkt after finding him on &lt;a href=&quot;http://www.youtube.com/watch?v=JUUvq48Gb3w&quot;&gt;youtube&lt;/a&gt; and checking out his work on Mustache and Sinatra and Github (he is a co-founder). At this point I&amp;#8217;ve got a fairly stable list of my own going and on most days I come across something cool or something new that&amp;#8217;s fun and helps keep things fresh and interesting.&lt;/li&gt;
	&lt;li&gt;I found out who features in searches for local Rails consultancies and using them as a starting point for discovering local Rubyists. Should be useful to identify what&amp;#8217;s on peoples&amp;#8217; minds locally and when they might be hiring.&lt;/li&gt;
	&lt;li&gt;I located my local Ruby and Rails meetup.  It&amp;#8217;s affectionately called &lt;a href=&quot;http://rubyonrails.com.au/&quot;&gt;rorosyd&lt;/a&gt; &amp;#8211; it meets every month at a nice pub and features talks that occasionally include the speaker bursting into song (MJ&amp;#8217;s &lt;cite&gt;Thriller&lt;/cite&gt; in one very amusing instance)! A lot of experienced members of the community attend and you also invariably find more than the occasional recruiter and tech curioso. Newcomers are required to introduce themselves and after the talks there is an opportunity to match available work with available people. I&amp;#8217;ve attended three of these so far and am looking forward to the next one.  Oh and there is a bit of beer drinking that goes on as well!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Satish Talim (mentioned also in the &lt;a href=&quot;/2010/04/Books-and-tutorials/&quot;&gt;previous&lt;/a&gt; post) has a &lt;a href=&quot;http://rubylearning.com/blog/2008/10/29/50-rubyists-to-follow-on-twitter/&quot;&gt;blog post&lt;/a&gt; on Rubyists to follow &amp;#8211; this might also be useful to those starting out.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Ruby reading material and courses</title>
   <link href="http://novemberkilo.com/2010/04/Books-and-tutorials"/>
   <updated>2010-04-12T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/04/Books-and-tutorials</id>
   <content type="html">&lt;h1&gt;Books and tutorials&lt;/h1&gt;
&lt;p&gt;Owing to the popularity of Rails, there are an incredible number of books out there that promise introductions, expertise and Ruby super powers.  I haven&amp;#8217;t read most of them and obviously, am not in a position to comment on any beyond the few that I have.  Perhaps I missed a few gems (pun intended, sorry!) in my brief search and I make no claim that I found the best of the crop.  Anyway, what follows is a short description of the way in which I went about deciding on which books were right for me.&lt;/p&gt;
&lt;p&gt;I chose to start off with an introduction to Rails.  It was pretty clear that I would also need an introduction to Ruby and so I looked for a Rails book that provided this as well.  Having had some exposure to the excellent &lt;a href=&quot;http://www.pragprog.com&quot;&gt;Pragmatic Programmer&lt;/a&gt; series, I was tempted to pick up &lt;a href=&quot;http://pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition&quot;&gt;Agile Web Development with Rails.&lt;/a&gt; After all, one of the authors, David Heinemeier Hansson, is the creator of the Rails framework. I did buy this book eventually but owing to some advice from &lt;a href=&quot;http://www.matthew-sinclair.com&quot;&gt;@matthewsinclair,&lt;/a&gt; it wasn&amp;#8217;t the book that I chose to get me started.&lt;/p&gt;
&lt;p&gt;I spent some time on Amazon reading reviews of Rails books and based mainly on what I read there, chose to start off with Patrick Lenz&amp;#8217;s, &lt;a href=&quot;http://www.sitepoint.com/books/rails2/&quot;&gt;Simply Rails 2.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Patrick&amp;#8217;s book is fun!  It is written in a relaxed style and concentrates on getting the beginner to the point where they have quickly built a simple Rails app (modelled on Digg).  It fits the ethos of Rails in that it provides near-real-time gratification and the reader is encouraged by the fact that they&amp;#8217;re getting their hands dirty and have something to show for it.  His here-hold-my-hand-while-we-connect-the-dots approach has the obvious problem of needing to gloss over the detail.  Nevertheless, this is what this beginner needed so as to avoid getting bogged down early.  Patrick&amp;#8217;s chapter on Ruby basics is good, but basic. I read his book over a couple of sittings, working through the code that he presents and building the app that he uses to illustrate the main aspects of Rails.&lt;/p&gt;
&lt;p&gt;@matthewsinclair also recommended Michael Hartl&amp;#8217;s work-in-progress tutorial, &lt;a href=&quot;http://railstutorial.org&quot;&gt;&amp;#8220;The Ruby on Rails Tutorial Book&amp;#8221;&lt;/a&gt; and referred to here as &lt;cite&gt;Rails Tutorial.&lt;/cite&gt; Michael&amp;#8217;s &lt;a href=&quot;http://michaelhartl.com/about.html&quot;&gt;bio&lt;/a&gt; mentions his accolades as a teacher at Caltech.  Having taught for 8 years or so myself, I can spot a passion for good teaching from ten paces and Michael&amp;#8217;s got it! He has successfully ported his teaching abilities to the written word and is developing a tutorial that is simply excellent.  &lt;cite&gt;Rails Tutorial&lt;/cite&gt; is written for the complete newbie while containing enough detail and secondary content to make it quite useful to the curious (non Rails) programmer as well.  When I came across his tutorial, I had already started on Patrick&amp;#8217;s book.  I wanted to finish my first foray into Rails, so I put off tackling Michael&amp;#8217;s tutorial until after I had finished &lt;cite&gt;Simply Rails 2.&lt;/cite&gt;  I don&amp;#8217;t regret doing this but suggest to the newbie reader that they will likely benefit from using Michael&amp;#8217;s tutorial as a starting point. Some of the highlights include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Using git from the start (so you learn about version control)&lt;/li&gt;
	&lt;li&gt;Consistently pushing &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; (test driven development)&lt;/li&gt;
	&lt;li&gt;Getting you started with an account on Github and Heroku before the end of Chapter 1&lt;/li&gt;
	&lt;li&gt;Building a non-trivial mock up of a social micro-blogging site&lt;/li&gt;
	&lt;li&gt;Integrating with &lt;a href=&quot;http://gravatar.com&quot;&gt;Gravatar&lt;/a&gt; and other fun tidbits &amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Michael had written 4 chapters (there are a total of 11) when I worked through his tutorial the first time.   Chapter 3 is &lt;cite&gt;Rails-flavored Ruby,&lt;/cite&gt; in which he starts off by asserting that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ruby is a big language, but fortunately the subset needed to be productive as a Rails developer is relatively small. Moreover, this subset is different from the usual approaches to learning Ruby, which is why, if your goal is making dynamic web applications, I recommend learning Rails first, picking up bits of Ruby along the way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, instictively this clashed with my need to connect with first principles.  I&amp;#8217;m not suggesting that Michael is wrong &amp;#8211; it&amp;#8217;s just that at that point in my journey, I felt I needed to shore up my foundations and spend some time with Ruby.  Michael makes some suggestions for further reading in the early part of his book and I just followed his recommendation and bought a copy of Peter Cooper&amp;#8217;s, &lt;cite&gt;Beginning Ruby, Second Edition.&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Michael recommends Peter&amp;#8217;s book saying,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I recommend that newer programmers read &lt;cite&gt;Beginning Ruby&lt;/cite&gt; by Peter Cooper, which shares the same basic instructional philosophy as Rails Tutorial. After finishing &lt;cite&gt;Beginning Ruby,&lt;/cite&gt; you’ll be ready for &lt;cite&gt;Agile Web Development with Rails&lt;/cite&gt; by Dave Thomas and David Heinemeier Hansson and &lt;cite&gt;The Rails Way&lt;/cite&gt; by Obie Fernandez.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Peter&amp;#8217;s writing style is simply delightful! He is funny, relaxed and conversational as he leads you through the basics of Ruby.  Using some excellent and non-trivial examples and exercises he gets the reader beyond the reading and into the doing.  His book is sub-titled, &lt;cite&gt;From Novice to Professional&lt;/cite&gt; and he achieves this by splitting the book into two parts.  The first half is focussed on foundational elements of the language and the second half covers topics like web application frameworks (Rails, Sinatra, etc.), desktop application development etc. This section also provides a whirlwind tour of some of ruby&amp;#8217;s main libraries. I find that I use the first half as a reference and when I want to learn about something new (e.g. Shoes), the second half provides for an excellent starting point.  There aren&amp;#8217;t any formal exercises in the book but he closes the first half with a chapter that builds a large application that pulls together individual facets of Ruby. Peter is also the author of one of Ruby&amp;#8217;s chief sources of information on the web, &lt;a href=&quot;http://rubyinside.com&quot;&gt;RubyInside&lt;/a&gt; and is quite active on &lt;a href=&quot;http://twitter.com/peterc&quot;&gt;twitter.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve also acquired the pickaxe book or  &lt;a href=&quot;http://pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition&quot;&gt;Agile Web Development with Rails.&lt;/a&gt; I expect that I will spend more time with it as I get my hands dirty with a Rails project or two.  At this point in time the print version of this book covers Rails 2 and a beta version refactoring the book to Rails 3 is in progress.  I suggest holding off until this version is complete and/or picking up a second hand copy of the Rails 2 version.&lt;/p&gt;
&lt;h2&gt;Courses&lt;/h2&gt;
&lt;p&gt;Learning a programming language by getting in there and writing some code is far more effective than (just) reading a book about its foundational elements.  If you are an experienced programmer and have a project in mind, cracking open an &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; (or in the case of Ruby, an editor!) is an effective first step.  I had a couple of projects in mind (more on this later) but wanted to find something a bit more bite sized and guided.  There are some excellent resources targeted at providing exercises to the beginning and intermediate Rubyist and all of them appear to have some form of support or guidance so that you can have questions answered and a critique provided of your solution.  My (limited) research uncovered the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://rubylearning.org&quot;&gt;rubylearning.org&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://rubyproblems.com&quot;&gt;rubyproblems.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://projecteuler.net&quot;&gt;Project Euler&lt;/a&gt; &amp;#8211; Mathematical and computer programming problems &amp;#8211; not Ruby specific&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I signed up for the Core Ruby course at &lt;a href=&quot;http://rubylearning.org&quot;&gt;rubylearning.org&lt;/a&gt; and worked through 8 weeks of tutorials, exercises and quizzes.  The format of the course is described &lt;a href=&quot;http://rubylearning.com/satishtalim/faq.html#q5&quot;&gt;here.&lt;/a&gt;  In summary, it is free, based on &lt;a href=&quot;http://rubylearning.com/satishtalim/tutorial.html&quot;&gt;notes&lt;/a&gt; and exercises written by Ruby Learning&amp;#8217;s creator, &lt;a href=&quot;http://satishtalim.com/&quot;&gt;Satish Talim&lt;/a&gt; and supported by an international cast of mentors. I really got a lot out of doing the exercises every week and getting feedback from the mentors.  They suggested variations that I could explore and mistakes that I could try and fix!  The interaction with the mentors provided something that books rarely do &amp;#8211; I began to get learn more about &lt;cite&gt;the ruby way&lt;/cite&gt;  of doing things and (anti) patterns relating to efficiency.  I learned some of Ruby&amp;#8217;s idioms and my confidence in Ruby programming increased significantly. More than anything, I think Satish delivered on his mission to demonstrate that &lt;cite&gt;Ruby helps programmers have more fun!&lt;/cite&gt; I really did have a lot of fun over the 8 weeks I spent with the course and thank Satish and his merry Rubyists for a great time! Check out Satish&amp;#8217;s &lt;a href=&quot;http://rubylearning.com/blog/&quot;&gt;blog&lt;/a&gt; for more information on what he is up to (courses on Clojure, Git, etc.) and for some interesting interviews with top Rubyists exploring their views on effective ways of learning Ruby.&lt;/p&gt;
&lt;p&gt;I am excited about exploring &lt;a href=&quot;http://rubyproblems.com&quot;&gt;rubyproblems.com&lt;/a&gt; and the dormant mathematician in me is very curious about checking out the goings on at &lt;a href=&quot;http://projecteuler.net&quot;&gt;Project Euler.&lt;/a&gt;  I expect that I will write about any adventures I have with these sites.&lt;/p&gt;
&lt;p&gt;I hope that this article provides some useful points of reference for other newbies looking for books, tutorials and/or courses to help them on their way.  In my next post I will write about the role that virtual and physical networks play in my continuing journey with Ruby and Rails.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Overview: Adventures of a Ruby newbie (12/'09 - 04/'10)</title>
   <link href="http://novemberkilo.com/2010/04/Dec-2009-to-April-2010"/>
   <updated>2010-04-09T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/04/Dec-2009-to-April-2010</id>
   <content type="html">&lt;p&gt;When I was starting out on my project to learn Ruby and Rails, I found several anecdotes, snippets of information, and personal recommendations that helped me make some decisions about how to proceed.  In the hope that it will be of some value to other Ruby newbies, I am going to catalogue some of my experiences and put together information that I collected during these early months. This information will include lists of books, web sites, blogs, tutorials, and some tips for dos and donts (that worked for me anyway).&lt;/p&gt;
&lt;h2&gt;A bit of background&lt;/h2&gt;
&lt;p&gt;Knowing the perspective and experience of the writer is generally useful &amp;#8211; helps understand why they may have chosen this over that.  So, while you can read about my background &lt;a href=&quot;/about.html&quot;&gt;here,&lt;/a&gt; it&amp;#8217;s worth adding that it&amp;#8217;s been about 8 years since &lt;a href=&quot;http://github.com/typerlc&quot;&gt;@typerlc&lt;/a&gt; introduced me to Ruby and python. Shamefully, until very recently, I never really got beyond occasionally perusing a &lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt; of an early version of the &lt;a href=&quot;http://pragprog.com/titles/ruby/programming-ruby&quot;&gt;pickaxe book.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Having spent a few years in management, I was beginning to feel like I was living in increasingly rarer layers of the administrosphere. I felt the growing urge to do what I was trained to do as a mathematician, i.e. to return to first principles.  Last year I found myself checking the version of Ruby on my macbook and wondering whether I could balance work-life-thethingsyouwasteyourtimeon to ground myself by getting back into development.  In December 2009, it seems that I managed to get on with it!&lt;/p&gt;
&lt;h2&gt;The overview&lt;/h2&gt;
&lt;p&gt;About 4 months have passed and I have spent an average of 10-12 hours a week at the keyboard.  I have also found myself filling the cracks of the day running thought experiments and ruminating on the coding problem of the hour.  I set myself a short list of projects to tackle and (as this blog attests), have completed some of them.  In other words, I feel that I have some momentum as a beginning Rubyist and am keen to gather more of it!&lt;/p&gt;
&lt;p&gt;The top five things I have done to contribute to this outcome:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Found a list of Rubyists to follow on twitter&lt;/li&gt;
	&lt;li&gt;Connected with my local Ruby and Rails user group&lt;/li&gt;
	&lt;li&gt;Worked through &lt;a href=&quot;http://rubylearning.org&quot;&gt;rubylearning.org&amp;#8217;s&lt;/a&gt; 8 week foundation course&lt;/li&gt;
	&lt;li&gt;Developed a flickr-notifier app using Ruby and Growl&lt;/li&gt;
	&lt;li&gt;Constructed this blog using open source first principles&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Coming up next&lt;/h2&gt;
&lt;p&gt;Having put up an overview, the next post in this series will be about the detail of the adventure that has been the past 4 months.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Hello World</title>
   <link href="http://novemberkilo.com/2010/04/Hello-World"/>
   <updated>2010-04-05T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/04/Hello-World</id>
   <content type="html">&lt;p&gt;Hello and welcome to my first post in a long while.  For the very few of you who have read previous incarnations of the iNK blot, things are likely to look and feel a little different around here.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m all fired up to begin by cataloging my experiences thus far with ruby and rails.  I have been wanting to get to know these technologies for a while now and have finally found an opportunity to get on with it. Since December 2009 I have worked my way through a few books, tutorials and an online course, and, I am going to share my experiences in the next few posts.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
</feed>