<?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>2012-02-18T23:04:40-08:00</updated>
 <id>http://novemberkilo.com/</id>
 <author>
   <name>Navin Keswani</name>
   <email>navin@novemberkilo.com</email>
 </author>
 
 <entry>
   <title>Simple Design</title>
   <link href="http://novemberkilo.com/2011/12/principle-of-simple-design"/>
   <updated>2011-12-04T00:00:00-08:00</updated>
   <id>http://novemberkilo.com/2011/12/principle-of-simple-design</id>
   <content type="html">&lt;p&gt;Yesterday I attended the &lt;a href='http://coderetreat.org/events/global-day-of-coderetreat-2011'&gt;&lt;em&gt;Global Day of Code Retreat, 2011&lt;/em&gt;&lt;/a&gt; in Sydney. We were incredibly privileged to have the creator of Code Retreat, &lt;a href='http://twitter.com/coreyhaines'&gt;Corey Haines&lt;/a&gt; facilitating.&lt;/p&gt;

&lt;p&gt;I found the experience to be really very profound and recommend it without reserve to developers of all levels.&lt;/p&gt;

&lt;p&gt;Here are some of the things I took from the day:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My C++/RUP based thinking of OO really needs a makeover&lt;/li&gt;

&lt;li&gt;I thought I was practising Test Driven Development (TDD) but I now see how narrow my understanding of TDD was. The &lt;em&gt;evil coder&lt;/em&gt; or &lt;em&gt;Mute with Find the Loophole&lt;/em&gt; session of the retreat was simultaneously hilarious, frustrating and enlightening on how well tests actually serve as a specification for code&lt;/li&gt;

&lt;li&gt;The principles of &lt;em&gt;Simple Design&lt;/em&gt; (attributed to the best of my knowledge to Kent Beck and Ron Jeffries in the Extreme Programming book)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;ve come across each of the 4 principles of simple design but when I heard Corey talk through them in sequence, it really made a difference to the way I understand them. I know that this understanding will change as I practice with them and I will not remember them as well when I am in the thick of the work day, so I&amp;#8217;m writing them down here as a note to self:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs all the tests&lt;/li&gt;

&lt;li&gt;Expresses every idea that we need to express&lt;/li&gt;

&lt;li&gt;Says everything once and only once&lt;/li&gt;

&lt;li&gt;Has no superfluous parts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I look forward to practicing the principles I learned at code retreat. I have no doubt that I have had a step change in my perspective as a programmer - more power to Corey&amp;#8217;s efforts at &lt;a href='http://coderetreat.org'&gt;coderetreat.org&lt;/a&gt; I say!&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>A Top Down Operator Precedence parser for algebraic expressions</title>
   <link href="http://novemberkilo.com/2011/10/tdop-math"/>
   <updated>2011-10-07T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2011/10/tdop-math</id>
   <content type="html">&lt;p&gt;In my &lt;a href='/2011/10/Polar-curve-grapher/'&gt;previous post&lt;/a&gt; I wrote about a polar curve grapher and its use of Kevin Mehall&amp;#8217;s &lt;code&gt;tdop_math.js&lt;/code&gt; to parse a user input algebraic expression into a javascript eval(uable) string. I ended up spending some time with &lt;code&gt;tdop_math.js&lt;/code&gt; - you can find the source &lt;a href='https://github.com/kevinmehall/EquationExplorer/blob/master/tdop_math.js'&gt;here&lt;/a&gt; - and I fell into the magical rabbit hole of Top Down Operator Precedence (TDOP) parsers. This post describes how I ended up writing a TDOP parser for algebraic expressions in Ruby.&lt;/p&gt;

&lt;p&gt;Some facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vaughan Pratt first wrote about Top Down Operator Precedence parsers in 1973&lt;/li&gt;

&lt;li&gt;Douglas Crockford wrote about them in Beautiful Code, and in &lt;a href='http://javascript.crockford.com/tdop/tdop.html'&gt;an article&lt;/a&gt; that includes an implementation of a parser for a Simplified Javascript - he went on to use this in &lt;a href='http://jslint.com'&gt;JSlint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='overview_of_tdop_parsers'&gt;Overview of TDOP parsers&lt;/h4&gt;

&lt;p&gt;In a nutshell, Top Down Operator Precedence parsers are similar to &lt;a href='http://en.wikipedia.org/wiki/Recursive_descent_parser'&gt;Recursive Descent parsers,&lt;/a&gt; but, as claimed by Vaughan Pratt, simpler to understand, implement, and providing of better performance. Borrowing from &lt;a href='http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/'&gt;this&lt;/a&gt; excellent article by Eli Bendersky, the main features of a TDOP parser are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;binding power&lt;/em&gt; mechanism to handle precedence levels - e.g. the binding power of multiplication &lt;code&gt;&amp;#39;*&amp;#39;&lt;/code&gt; is higher than that of addition &lt;code&gt;&amp;#39;+&amp;#39;&lt;/code&gt; in arithmetic&lt;/li&gt;

&lt;li&gt;A means of implementing different functionality of tokens depending on their position relative to their neighbors: &lt;em&gt;prefix&lt;/em&gt; or &lt;em&gt;infix.&lt;/em&gt; For example, the minus &lt;code&gt;&amp;#39;-&amp;#39;&lt;/code&gt; operator is behaving as a prefix operator in &lt;code&gt;-2&lt;/code&gt; but in its infix form, it is subtraction &lt;code&gt;4 - 2.&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;As opposed to classic Recursive Descent, where semantic actions are associated with grammar rules (BNF), TDOP associates them with tokens. Tokens have a binding power, and know how to handle themselves in infix and/or in prefix situations. Expressions are then evaluated recursively by evaluating them at each &amp;#8216;precedence&amp;#8217; level and returning the result to its caller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compilers are difficult to understand at the best of times and most articles I have come across on TDOP parsers are by very bright people finishing (or pausing) on their journey to get to know Pratt&amp;#8217;s work. At my current stage of comfort with TDOP parsers, I cannot come close to explaining the parser any better than Eli Bendersky.&lt;/p&gt;

&lt;p&gt;Eli&amp;#8217;s &lt;a href='http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/'&gt;article,&lt;/a&gt; elaborates on the features described above and explains the parser by setting one up to handle simple arithmetic. He then works through a simple example that illustrates it in action as it parses the expression &lt;code&gt;3 + 1 * 2 * 4 + 5.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For further detail on TDOP parsers, I refer the interested reader to this and Douglas Crockford&amp;#8217;s article referenced above.&lt;/p&gt;

&lt;h3 id='tdop_and_ruby'&gt;TDOP and Ruby&lt;/h3&gt;

&lt;p&gt;As I was working on the &lt;a href='2011/10/Polar-curve-grapher/'&gt;polar curve grapher&lt;/a&gt; I got curious about implementing &lt;code&gt;tdop_math.js&lt;/code&gt; in Ruby. I studied the source of &lt;code&gt;tdop_math.js,&lt;/code&gt; and its tokeniser &lt;code&gt;tokens.js,&lt;/code&gt; and felt that I had a decent understanding of its structure and operation (improving my Javascript skills along the way!). However, a like-for-like implementation in Ruby seemed out of the question. Well, it seemed like a hard proposition that would involve first developing new metaprogramming skills in Ruby!&lt;/p&gt;

&lt;p&gt;And then I ran into Glen Vandenburg&amp;#8217;s project &lt;code&gt;radish,&lt;/code&gt; which is now called &lt;a href='http://github.com/glv/smithereen'&gt;&lt;code&gt;smithereen&lt;/code&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;h4 id='smithereen'&gt;Smithereen&lt;/h4&gt;

&lt;p&gt;Smithereen is a result of Glen Vandenburg&amp;#8217;s meditation on TDOP parsers, during which he decided to write an implementation in Ruby. He has implemented a &lt;em&gt;library for building Top Down Operator Precedence parsers,&lt;/em&gt; using Ruby idioms that were completely unfamiliar to me, but that provided an excellent opportunity to learn. As Glen says, he has &lt;em&gt;tried to provide a well-factored set of tools to help with the core TDOP algorithm and several related problems,&lt;/em&gt; and so I decided to fork Smithereen with the intention of helping with its development, and, using it to implement &lt;code&gt;tdop_math&lt;/code&gt; in Ruby.&lt;/p&gt;

&lt;p&gt;Smithereen comes with two samples, an arithmetic parser, and the Simplified Javascript parser. I found it quite difficult to get started with Smithereen and asked Glen a question or two. To my delight, he helped me get started and I found this to be so inspiring that I made rapid progress towards implementing a simple scientific calculator. This is available on &lt;a href='http://github.com/novemberkilo/smithereen/tree/develop'&gt;my fork of Smithereen&lt;/a&gt; as &lt;a href='https://github.com/novemberkilo/smithereen/blob/develop/samples/equation_parser.rb'&gt;&lt;code&gt;equation_parser.rb&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;equation_parser.rb&lt;/code&gt; will, for instance, take strings such as &lt;code&gt;sin(cos(2pi))&lt;/code&gt; and return &lt;code&gt;0.84147&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By way of explanation, it has hardcoded hashes that declare functions and constants, and these are tokenised as &lt;code&gt;names&lt;/code&gt; and given a high binding power.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;fns&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;sin&amp;#39;&lt;/span&gt;  &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Proc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sin&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;cos&amp;#39;&lt;/span&gt;  &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Proc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;cos&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;tan&amp;#39;&lt;/span&gt;  &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Proc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;tan&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;sqrt&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Proc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sqrt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;exp&amp;#39;&lt;/span&gt;  &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Proc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exp&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='no'&gt;CONSTANTS&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;pi&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;PI&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='s1'&gt;&amp;#39;e&amp;#39;&lt;/span&gt;  &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;Math&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='n'&gt;E&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;infix&lt;/code&gt; method on the token &lt;code&gt;(&lt;/code&gt; checks for the presence of a function or a constant (essentially a key in the above hashes), and looks up the corresponding value for the definition of the function. Smithereen takes care of the rest. Well, that is, after tokens for the usual arithmetic operators are defined, with infix and prefix methods as described above.&lt;/p&gt;

&lt;h4 id='tdop_mathrb'&gt;tdop_math.rb&lt;/h4&gt;

&lt;p&gt;Completing my goal to create a Ruby equivalent to &lt;code&gt;tdop_math.js,&lt;/code&gt; I&amp;#8217;ve taken the work in the example &lt;code&gt;equation_parser.rb&lt;/code&gt; and used it to create a Ruby gem called &lt;code&gt;tdop_math.&lt;/code&gt; This takes an algebraic expression, parses it, and returns a string of Ruby that represents the expression.&lt;/p&gt;

&lt;p&gt;Because the &lt;code&gt;tdop_math&lt;/code&gt; gem depends on &lt;code&gt;smithereen&lt;/code&gt; (which has yet to be released), it is not available as a built gem.&lt;/p&gt;

&lt;p&gt;As far as I know, if you want to install this, you are going to need to pull down my &lt;a href='http://github.com/novemberkilo/tdop_math'&gt;repo&lt;/a&gt; and &lt;code&gt;include &amp;#39;&amp;lt;path-to-tdop_math.rb&amp;gt;&amp;#39;&lt;/code&gt; manually. Once you have, you use it as follows:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;sin(cos(2x))&amp;quot;&lt;/span&gt;  &lt;span class='c1'&gt;## or some user input algebraic expression&lt;/span&gt;
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;TDOPMath&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Parser&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;u&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;parse&lt;/span&gt;   &lt;span class='c1'&gt;## f == &amp;quot;Math.sin(Math.cos(2 * x))&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tdop_math&lt;/code&gt; reserves symbols &lt;code&gt;x&lt;/code&gt;,&lt;code&gt;y&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt; as variables. It also provides a basic list of functions, namely, &lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;cos&lt;/code&gt;, &lt;code&gt;tan&lt;/code&gt;, &lt;code&gt;sqrt&lt;/code&gt; and &lt;code&gt;exp&lt;/code&gt;. If you need to provide an alternate list of variables and functions, you can do so as follows:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;baz(foo(2a))&amp;quot;&lt;/span&gt;  &lt;span class='c1'&gt;## or some user input algrebraic expression&lt;/span&gt;
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;TDOPMath&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Parser&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;u&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                             &lt;span class='ss'&gt;:vars&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                             &lt;span class='ss'&gt;:functions&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
                                &lt;span class='s1'&gt;&amp;#39;foo&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Foo::foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                                &lt;span class='s1'&gt;&amp;#39;baz&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Baz::baz&amp;#39;&lt;/span&gt;
                              &lt;span class='p'&gt;})&lt;/span&gt;
    &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;parse&lt;/span&gt;   &lt;span class='c1'&gt;## f == &amp;quot;Baz::baz(Foo::foo(2 * a))&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can use &lt;code&gt;tdop_math&lt;/code&gt; wherever you need a user to input an algebraic expression, comprising of a known set of functions and variables. This could find use in apps in maths education or science/data analytics. I hope the community finds it useful, although my motivation was mainly to build it as an exercise, along my path to becoming a better programmer. I&amp;#8217;ve made a gem!&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>A polar curve grapher</title>
   <link href="http://novemberkilo.com/2011/10/Polar-curve-grapher"/>
   <updated>2011-10-02T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2011/10/Polar-curve-grapher</id>
   <content type="html">&lt;p&gt;Polar coordinates and polar functions are remarkably beautiful to people who get mathematics. I think that their &lt;a href='http://www.wolframalpha.com/input/?i=polar+curves'&gt;graphs&lt;/a&gt; are beautiful to most people. Ever since I first met them, I&amp;#8217;ve tried to draw them on different platforms and using different languages. Wanting to know more about canvas and javascript, I thought that it would be interesting to implement a polar curve grapher using these.&lt;/p&gt;

&lt;p&gt;A quick reminder - the &lt;a href='http://www.wolframalpha.com/input/?i=polar+coordinates'&gt;polar coordinates&lt;/a&gt; &lt;code&gt;( r, t )&lt;/code&gt; of a point are expressed in terms of the distance &lt;code&gt;r&lt;/code&gt; of the point from the origin and the angle &lt;code&gt;t&lt;/code&gt; that the line connecting the point to the origin makes with the &lt;code&gt;x&lt;/code&gt;-axis. Also, the way you get from a set of polar coordinates &lt;code&gt;(r, t)&lt;/code&gt; to cartesian coordinates &lt;code&gt;(x, y)&lt;/code&gt; is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    x = r * cos(t), y = r * sin(t)&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id='background'&gt;Background&lt;/h4&gt;

&lt;p&gt;Earlier on this year I had asked &lt;a href='http://avantbard.com'&gt;Gabe Hollombe&lt;/a&gt; for advice on things I could do to become a better programmer. Around the time of the conversation, I was particularly aware of my lack of knowledge of javascript and so, we chose my polar-curve-grapher as a project for Gabe to mentor me through.&lt;/p&gt;

&lt;p&gt;I started off by checking out the landscape of javascript based graphing tools and apps and came across the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kevin Mehall&amp;#8217;s &lt;a href='http://kevinmehall.net/p/equationexplorer'&gt;EquationExplorer&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;aanthony&amp;#8217;s &lt;a href='http://graph.tk'&gt;graph.tk&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Given my relative lack of experience with javascript, I found both apps difficult to understand. So, I tried to figure out how to do it by myself. I looked for javascript libraries I could use to simply plot a bunch of points and found a lot of stuff for charts but relatively few that would just take an array of points and plot them. Here are some that fit the bill:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href='http://www.jqplot.com/'&gt;jQplot&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;Keith Lawler&amp;#8217;s &lt;a href='https://github.com/lawler/raphael.graphing'&gt;raphael.graphing.js&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I played around with jqplot and a hard-coded function &lt;code&gt;r = f(t)&lt;/code&gt; to get some quick results. Essentially, I created an array of points to be plotted using the following direct approach:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    points_to_be_plotted = []
    for t in (0 ... 6*PI)
    points_to_be_plotted.push [ f(t)*cos(t), f(t)*sin(t) ]

    jqPlot( point_to_be_plotted )&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this is what jQplot did for me:&lt;/p&gt;
&lt;img src='/images/Polar_function_grapher-jqplot.jpg' style='border: solid; border-color: gray; border-width: 2px' /&gt;
&lt;p&gt;This gave me a quick proof of concept and, the project had a life! I now needed to figure out how to get user input, process it, and then plot it.&lt;/p&gt;

&lt;h4 id='parsing_user_input'&gt;Parsing user input&lt;/h4&gt;

&lt;p&gt;Getting user input turned out to be straightforward - use a form in the page with a submit button and respond to the button click by picking up the input in javascript as a string (say) &lt;code&gt;&amp;quot;input_fn&amp;quot;&lt;/code&gt;. Use &lt;code&gt;eval(&amp;quot;input_fn(t)&amp;quot;)&lt;/code&gt; to turn this into a javascript function and follow the psuedocode above to generate an array of points to be plotted (see the source of the project for the detail - more on this below).&lt;/p&gt;

&lt;p&gt;But what if you want the user to enter a function in plain, pedestrian maths (instead of the syntax required by javascript) - e.g. &lt;code&gt;2sin(x)&lt;/code&gt; instead of &lt;code&gt;2 * Math.sin(x)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Kevin&amp;#8217;s EquationExplorer did this so I set out to understand how. And this lead me to the world of Top-Down-Operator-Precedence (TDOP) parsers.&lt;/p&gt;

&lt;p&gt;I will write more about TDOP parsers in my next post but to complete the story on the polar curve grapher, these were the ingredients that went into the grapher that &lt;a href='http://github.com/novemberkilo/polar-curve-grapher'&gt;you can find here.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parsing: Kevin Mehall&amp;#8217;s &lt;code&gt;tdop_math.js&lt;/code&gt; parser (that requires &lt;code&gt;tokens.js,&lt;/code&gt; a lexer written by Douglas Crockford himself)&lt;/li&gt;

&lt;li&gt;Graphing: Keith Lawler&amp;#8217;s graphing library that is based on &lt;code&gt;raphael.js&lt;/code&gt; and called, &lt;a href='https://github.com/lawler/raphael.graphing'&gt;raphael.graphing.js&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And thanks to GitHub pages, you can see it in action here: &lt;a href='http://novemberkilo.com/polar-curve-grapher'&gt;http://novemberkilo.com/polar-curve-grapher&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the time of posting this I still needed to apply a coat or two of polish - I&amp;#8217;m not doing any graceful error handling (so try not to divide by zero!) and I&amp;#8217;m only winding around the origin three times. You should be able to play around though and get some pretty graphs.&lt;/p&gt;

&lt;p&gt;Try &lt;code&gt;r = sin(3t)&lt;/code&gt; to get started with a propeller :)&lt;/p&gt;

&lt;h4 id='acknowledgements'&gt;Acknowledgements&lt;/h4&gt;

&lt;p&gt;I had a lot of fun putting this project together and owe a debt of gratitude to &lt;a href='http://avantbard.com'&gt;Gabe Hollombe&lt;/a&gt; for encouraging me to take this on, and for answering questions and providing guidance along the way. Also, thanks to Keith Lawler and Kevin Mehall for doing the heavy lifting - this project turned out to mainly involve stitching together their libraries.&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>A simple jquery scroller</title>
   <link href="http://novemberkilo.com/2011/09/Simple-jquery-scroller"/>
   <updated>2011-09-24T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2011/09/Simple-jquery-scroller</id>
   <content type="html">&lt;p&gt;Recently we implemented a variation on a scroller. We needed to flash up a set of snippets, one by one, in the same text area of a page. Here&amp;#8217;s a &lt;a href='/examples/jquery_scroller.html'&gt;demo&lt;/a&gt; of it in action. You can view the source of the demo but here&amp;#8217;s a quick, plain-English explanation of how it works.&lt;/p&gt;

&lt;h4 id='the_markup'&gt;The markup&lt;/h4&gt;

&lt;p&gt;In the page, the snippets are list elements &lt;code&gt;li&lt;/code&gt; in a &lt;code&gt;section&lt;/code&gt;. You can make them definition elements or whatever you like. The section has an &lt;code&gt;id&lt;/code&gt; so we can find it from javascript - I&amp;#8217;ve called it &lt;code&gt;snippets&lt;/code&gt; in the example.&lt;/p&gt;

&lt;h4 id='the_css'&gt;The CSS&lt;/h4&gt;

&lt;p&gt;Pretty much the only style elements that are important to the correct operation of the scroller is &lt;code&gt;display: none&lt;/code&gt; on the list elements. This ensures that all list elements start out being invisible. Having &lt;code&gt;overflow: hidden&lt;/code&gt; on the &lt;code&gt;section&lt;/code&gt; makes it easier to deal with any stuttering in the javascript loop shown below.&lt;/p&gt;

&lt;h4 id='the_javascript'&gt;The javascript&lt;/h4&gt;

&lt;p&gt;We&amp;#8217;re using jQuery so make sure you&amp;#8217;ve got that loaded. And here&amp;#8217;s the javascript:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;    &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='nx'&gt;ready&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(){&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;loopSnippets&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;snippets&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;li&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;#snippets&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;

        &lt;span class='nx'&gt;snippets&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;each&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;index&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;element&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
          &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;element&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;delay&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nx'&gt;index&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='mi'&gt;5000&lt;/span&gt; &lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;fadeIn&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;delay&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;4500&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;fadeOut&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
          &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;index&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='nx'&gt;snippets&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;setTimeout&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nx'&gt;loopSnippets&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;index&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='mi'&gt;5000&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;5000&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
      &lt;span class='nx'&gt;loopSnippets&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So this is where all the action is of course. The variable &lt;code&gt;snippets&lt;/code&gt; collects all the list items and then we iterate over this collection, showing each list item and then hiding them again (using &lt;code&gt;fadeIn&lt;/code&gt; and &lt;code&gt;fadeOut&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;What you have to wrap your head around is that all of the code gets executed in one shot, so to get items to display in sequence and to loop around again, you have to show-and-hide each item at different times.&lt;/p&gt;

&lt;p&gt;The trick is to use &lt;code&gt;delay&lt;/code&gt; and the index of the item in the array to calculate the amount of time we need to wait before kicking off the show-and-hide routine for the item.&lt;/p&gt;

&lt;p&gt;Finally, to loop back and start over at the top, we use &lt;code&gt;setTimeout&lt;/code&gt; to kick off the &lt;code&gt;loopSnippets&lt;/code&gt; function again. Again, use the length of &lt;code&gt;snippets&lt;/code&gt; and the amount of time used up in showing and hiding each element to figure out how long you have to wait before setting off &lt;code&gt;loopSnippets&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;Keep in mind that the above code works irrespective of the length of the list of snippets - which is of course what you want if the snippets are dynamically loaded.&lt;/p&gt;

&lt;h4 id='in_summary'&gt;In summary&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;delay&lt;/code&gt; and the index of elements in an array if you want to operate on each element in sequence. Use &lt;code&gt;setTimeout&lt;/code&gt; to repeat a function call at specific time intervals.&lt;/p&gt;

&lt;p&gt;Thanks go to &lt;strong&gt;Josh Kunzmann&lt;/strong&gt; and &lt;strong&gt;Damien Le Berrigaud&lt;/strong&gt; for collaborating on this and showing me how to use &lt;code&gt;delay&lt;/code&gt; and &lt;code&gt;setTimeout&lt;/code&gt; creatively!&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Selecting an editor</title>
   <link href="http://novemberkilo.com/2011/02/Ode-to-vim"/>
   <updated>2011-02-05T00:00:00-08:00</updated>
   <id>http://novemberkilo.com/2011/02/Ode-to-vim</id>
   <content type="html">&lt;p&gt;The flame wars on the topic of editors have probably been around since, well, there was more than one editor to choose from!  An &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; or an editor is such a fundamental tool for a developer that it is no wonder we end up having very strong views on our editor of choice.  What I have never really understood is why we also tend to have strong negative opinions on editors that we choose not to use &amp;#8212; live and let live people!  This post is about my journey through the process of selecting an editor &amp;#8212; I also present a few tips and resources along the way, particularly on Vim (the editor I settled on). I am not in the slightest bit interested in fuelling the aforementioned flame war; if I say something here that could be interpreted as an insult to your favourite editor, please keep my motivation in mind and resist the temptation for such interpretation. Oh and I work on OS X so some editors mentioned here may not apply to your environment, sorry.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;I learned to write code in 1987 on green screen terminals hooked up to a &lt;a href=&quot;http://en.wikipedia.org/wiki/VAX&quot;&gt;&lt;span class=&quot;caps&quot;&gt;VAX&lt;/span&gt;.&lt;/a&gt; We were introduced to vi and I used it on a daily basis for a couple of years.  No wonder I&amp;#8217;ve got some of the basic vi commands baked into my brain stem!  We moved on to using NeXT and Apollo workstations and I got to use editors that allowed you to click around with a mouse.  Then came many years of using pencil, paper, chalk and blackboards, followed by the terrible years of only ever writing documents using MS Word and PowerPoint. So, until recently I hadn&amp;#8217;t touched a developer&amp;#8217;s editor in a very long time.&lt;/p&gt;
&lt;p&gt;When I started writing code again I noticed that TextMate, Emacs and Vim were the main contenders in the Rails community. I decided fairly early in the piece to try and give each editor a good month of serious use so that I could, with some objectivity, find the right one for me.  If you are starting out as a developer, I highly recommend this approach.&lt;/p&gt;
&lt;h3&gt;Foreground&lt;/h3&gt;
&lt;p&gt;And here is how it went. &lt;a href=&quot;http://macromates.com/&quot;&gt;TextMate&lt;/a&gt; was the easiest to work with then because I could just use the OS X shortcuts that were in muscle memory and use my mouse to click around etc. When my TextMate trial ran out I looked around again and found &lt;a href=&quot;http://aquamacs.org/&quot;&gt;AquaMacs&lt;/a&gt; &amp;#8211; a version of Emacs for OS X that, well, allows you to edit at will and not use very many Emacs commands at all!  Jokes aside, it mashes together Emacs with a Mac look-and-feel but this does get in the way of forcing any sort of discipline on oneself to learn Emacs.  &lt;a href=&quot;http://stackoverflow.com/questions/1096009/carbon-vs-aqua-vs-cocoa-emacs-builds&quot;&gt;This&lt;/a&gt; opinion piece from Stack Overflow treats this topic quite well.&lt;/p&gt;
&lt;p&gt;When I started my job I felt a lot of pressure to not be learning supporting tools like editors and instead, becoming immediately productive! This was laughable in hindsight really because I had nothing over an enthusiast&amp;#8217;s understanding of Rails at this point and needed to really just learn for a while!  My very awesome colleagues got this of course and encouraged the learning process, all the while nudging me ever so firmly towards getting a solid mind meld happening with my operating environment.  I went back to TextMate for a short while but then followed the chosen platform of two of my co-workers and adopted the &lt;a href=&quot;http://homepage.mac.com/zenitani/emacs-e.html&quot;&gt;Carbon build for Emacs.&lt;/a&gt; I did this with the very awesome &lt;a href=&quot;https://github.com/technomancy/emacs-starter-kit&quot;&gt;emacs-starter-kit&lt;/a&gt; and then things got really good!  I spent a month with Emacs and watched my productivity increase.&lt;/p&gt;
&lt;h3&gt;Vim&lt;/h3&gt;
&lt;p&gt;And then the circle closed.  Before I started, my dev team consisted of two Emacs users and one Vim devotee.  Right about when I was finishing my month with Carbon Emacs, a new guy joined the team and brought the Vim users count up to two.  At about this time I read the mighty &lt;a href=&quot;http://yehudakatz.com/2010/07/29/everyone-who-tried-to-convince-me-to-use-vim-was-wrong/&quot;&gt;Yehuda Katz on his journey from TextMate to Vim&lt;/a&gt; and decided to give &lt;a href=&quot;http://code.google.com/p/macvim/&quot;&gt;MacVim&lt;/a&gt; a go.  And that&amp;#8217;s where I&amp;#8217;ve settled! Why? Well, I really like the speed with which I can move around a Rails project with Tim Pope&amp;#8217;s terrfic Rails.vim plugin (I am told that there are similar plugins for Emacs) and I like the ease with which plugins like NERDTree allows me to look at my filesystem.  Most of all, Vim commands just fit better with my brain &amp;#8211; I like that they are about movement around a buffer and that they seem to consistently build on this philosophy. It just seems to work for me I suppose, and I think it&amp;#8217;s because I still carry some basic vi in my brain stem!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m very much a novice but I am comfortable with my environment and I am hungry to learn more.  Here are some resources that I have found very useful thus far &amp;#8212;&lt;/p&gt;
&lt;p&gt;General reference and tutorials:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://jmcpherson.org/editing.html&quot;&gt;Efficient editing with Vim&lt;/a&gt; &amp;#8211; Stellar article that is &lt;em&gt;intended to help vi novices develop their skills so that they can use vi efficiently.&lt;/em&gt; It focuses on &lt;em&gt;movements,&lt;/em&gt; the core of Vim commands&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://tottinge.blogsome.com/use-vim-like-a-pro&quot;&gt;Use Vim like a Pro&lt;/a&gt; &amp;#8211; comprehensive tutorial on some 38 different topics&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.viemu.com/a_vi_vim_graphical_cheat_sheet_tutorial.html&quot;&gt;Graphical vi-vim Cheat Sheet and Tutorial&lt;/a&gt; &amp;#8211; indispensable cheat sheets with accompanying tutorials&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Posts and screencasts that cover plugins and really make the connection with development come to life:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Steve Losh, &lt;a href=&quot;http://stevelosh.com/blog/2010/09/coming-home-to-vim/&quot;&gt;Coming Home to Vim&lt;/a&gt; &amp;#8211; well written and packed with pointers on plugins and vimrc customisations.  Steve&amp;#8217;s not a Rails guy (Python and Django I think) so nothing to do with Rails&lt;/li&gt;
	&lt;li&gt;Ben Orenstein&amp;#8217;s screencast, &lt;a href=&quot;http://www.codeulatescreencasts.com/products/vim-for-rails-developers&quot;&gt;Vim for Rails Developers.&lt;/a&gt;  Recently I was looking around for a screencast that would show me how a seasoned Rails developer uses Vim and I came across Ben&amp;#8217;s work and the &lt;em&gt;Smash into Vim&lt;/em&gt; series by &lt;a href=&quot;peepcode.com&quot;&gt;peepcode.&lt;/a&gt; I tried out the sample from peepcode and found the celebrity narrator&amp;#8217;s style to be a bit off-putting (just a personal thing, I&amp;#8217;m sure the &amp;#8216;cast lives up to the high peepcode standard).  Looked around at Ben&amp;#8217;s stuff and found that he is a Rails developer, Vim obsessive and an efficiency junkie! Ben asks bloggers to contact him for a copy of his screencast in exchange for a review and this is what I did.  I am happy to say that I was grinning like a Cheshire cat 10 minutes into the screencast and I only got happier as it went on.  What about the first 10 minutes? Well, passionate as he is about efficiency, he starts off by spending (perhaps a tad too much) time on the topic of speed typing. It&amp;#8217;s great advice, and it&amp;#8217;s possibly the only part of the screencast that will apply to the complete Vim novice (if you don&amp;#8217;t know the basics you won&amp;#8217;t find them here).  He really hit the sweet spot for me when he shows us how to effectively use Tim Pope&amp;#8217;s Rails plugin.  I use this plugin too but it became clear to me that I had only been using about 5% of its features!  Boy is my productivity about to go up!  Ben also takes us through the use of &lt;em&gt;snippets, ctags&lt;/em&gt; and the &lt;em&gt;surround&lt;/em&gt; plugins, spends some time on the wonders of &lt;em&gt;ack&lt;/em&gt; and how to use it from within Vim, and closes  with some general tips and tricks.  Something to keep in mind is that Ben appears to be a Vim purist &amp;#8211; he works within his terminal and does not use any of the bells and whistles that come with MacVim.  No mice are touched at all during this screencast!  All in all, I heartily recommend his screencast to the not-so-new-to-Vim Rails developer &amp;#8212; well worth the $11.99 price tag I think!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Plugins &amp;#8211; use them wisely&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m not going to do the traditional thing of offering my vimrc and plugin list because I&amp;#8217;m just using &lt;a href=&quot;https://github.com/carlhuda/janus&quot;&gt;janus&lt;/a&gt; (give or take a plugin or two).  &lt;em&gt;Janus&lt;/em&gt; is a vim-starter-kit for Rails types that has been put together by that mythical Carlhuda! Modifications in my local gvirmc come mainly from things I have borrowed from Steve Losh&amp;#8217;s article (referenced above).&lt;/p&gt;
&lt;p&gt;I asked Ben for a comment on &lt;em&gt;janus&lt;/em&gt; and this is what he had to say:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Actually, I&amp;#8217;m not sure I&amp;#8217;d recommend something like janus. The basic editor has so much built-in functionality that there&amp;#8217;s already plenty to learn when you start out. Additionally, new users won&amp;#8217;t know if certain behaviors are vanilla vim or accomplished through add-ons. Personally, I&amp;#8217;d recommend new users go a couple weeks with no plugins. Start tweaking your vimrc to see learn what kind of customizations you can make. Then start adding plugins one at a time and mastering them slowly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll leave it up to you to figure out whether to pick up MacVim with janus and try out Vim &amp;#8230; or whether you should do penance with the editor itself before adopting the gui version and plugins.  I think it will depend a bit on whether you are the type that regards a solid understanding of a tool to be a pre-condition to using it, or, whether you are happy to get to the most productive environment as quickly as possible.  I&amp;#8217;ve chosen a middle ground &amp;#8211; I&amp;#8217;m mainly using Rails.vim and basic editor commands and gradually picking up what the other plugins in &lt;em&gt;janus&lt;/em&gt; do.&lt;/p&gt;
&lt;p&gt;In any case, that&amp;#8217;s the story of how I ended up in smit with Vim. I hope you find some benefit from this post &amp;#8212; good luck with the process of selecting an editor and making it your own!&lt;/p&gt;
&lt;div class=&quot;update&quot;&gt; Update (Oct 2011):  Been using vim for a while now and am no longer using janus. My &lt;a href=&quot;http://github.com/novemberkilo/.vim&quot;&gt;.vim&lt;/a&gt; is now on my github &amp;#8211; forked from the remarkable Damien Le Berrigaud (vim superhero!), and updated with a few personal touches.&lt;/div&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Front end stuff - HTML, CSS, JavaScript and jQuery</title>
   <link href="http://novemberkilo.com/2011/01/jquery"/>
   <updated>2011-01-15T00:00:00-08:00</updated>
   <id>http://novemberkilo.com/2011/01/jquery</id>
   <content type="html">&lt;p&gt;When I started my job I had no &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; or JavaScript or jQuery to speak of. The first time I had to modify a page was when I realised that I had no foundation from which to learn &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; by example.  Here are some of the resources that I found very helpful in my journey to attaining enough knowledge and skills to confidently assert that I am now a novice! In the second half of this post I present an example &amp;#8211; constructing an &amp;#8220;Add&amp;#8221; button to a form to allow the user to add more rows of input fields.&lt;/p&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;p&gt;If you are an absolute beginner, I suggest starting with the following goals:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;Understand the &lt;em&gt;box model.&lt;/em&gt;&lt;/strong&gt;  This is at the heart of &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;. All elements of a web page are boxes that have standard properties like height, width, border, padding and margin. Use &lt;a href=&quot;http://getfirebug.com/&quot;&gt;Firebug&lt;/a&gt; to inspect anything on a webpage and use the &lt;a href=&quot;https://skitch.com/navink/ryudr/the-ink-blot-nks-ramblings#lightbox&quot;&gt;Layout&lt;/a&gt; tab to view its box model representation. Incidentally, you can click into the layout view, change values and see the effect that this has on the element you are inspecting. Similarly, you can click into and edit anything you see in the Styles tab &amp;#8211; a great way to experiment with what various &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; properties do.&lt;br /&gt;
There are so many tricks to the trade that you only really pick up with experience and I&amp;#8217;ve got a ways to go before I am using &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; properties effectively &amp;#8211; O&amp;#8217;Reilly&amp;#8217;s &lt;a href=&quot;http://oreilly.com/catalog/9780596005764&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; cookbook&lt;/a&gt; and &lt;a href=&quot;http://www.sitepoint.com/books/cssdesign1/&quot;&gt;The Art and Science of &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;&lt;/a&gt; come in handy when I run into a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; property or a pattern that I need to look up.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Get your head around &lt;em&gt;IDs&lt;/em&gt; and &lt;em&gt;classes.&lt;/em&gt;&lt;/strong&gt;  Simply put, IDs are unique while classes are not. Meanhwile, they are both &lt;em&gt;hooks.&lt;/em&gt; See this &lt;a href=&quot;http://css-tricks.com/the-difference-between-id-and-class/&quot;&gt;article&lt;/a&gt; by Chris Coyier for more.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Understand how &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; documents are structured.&lt;/strong&gt; For &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; 4 see this &lt;a href=&quot;http://www.w3.org/TR/html401/struct/global.html&quot;&gt;reference&lt;/a&gt; by the W3C and &lt;a href=&quot;http://html-5.com&quot;&gt;html-5.com&lt;/a&gt; looks like a good place to pick up resources for &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; 5. As I write this I realise that I am quite green on this particular topic &amp;#8211; and the reason I know this is because I don&amp;#8217;t know enough about the intention behind each structural element.  However, and at the risk of sharp intakes of breath from those who can spell &amp;#8220;semantic&amp;#8221;(!), I will admit that I am no longer using &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; to create a list (use &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; instead!).&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;JavaScript &amp;#8211; learn the basics.&lt;/strong&gt; &lt;a href=&quot;http://slash7.com/&quot;&gt;Amy Hoy&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Thomas_Fuchs&quot;&gt;Thomas Fuchs&lt;/a&gt; run a masterclass on the topic and so I asked them to suggest a book for the beginner.  Amy suggested &lt;a href=&quot;http://eloquentjavascript.net/&quot;&gt;Eloquent Javascript&lt;/a&gt; by Marijn Haverbeke &amp;#8211; it&amp;#8217;s free, well written, and really very accessible. It even works as an introduction to programming.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At work we tend to use &lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt; a lot.  The documentation on &lt;a href=&quot;http://jquery.com&quot;&gt;jQuery.com&lt;/a&gt; is terrific but here are a few other references that I have found very useful &amp;#8211; &lt;a href=&quot;http://jqfundamentals.com/book/book.html&quot;&gt;jQuery Fundamentals&lt;/a&gt; by Rebecca Murphey and &lt;a href=&quot;http://www.sitepoint.com/books/jquery1/&quot;&gt;jQuery: Novice to Ninja&lt;/a&gt; by Craig Sharkie and Earle Castledine.  When starting out with jQuery, I suggest spending time getting to understand &lt;em&gt;selectors.&lt;/em&gt; This is the hard part and gets clouded by the temptation to go shopping for jQuery actions immediately.&lt;/p&gt;
&lt;h3&gt;jQuery example &amp;#8211; dynamically adding fields to a form&lt;/h3&gt;
&lt;p&gt;Here is an example of jQuery at work in a Rails app &amp;#8211; something I learned from my colleague, Brad Wilson.  We needed to create a form to collect names and email addresses and, wanted to make the form start out with a single row of input fields, giving the user the option to add more names and email addresses if they so wished (this was part of a referral process).  Here&amp;#8217;s what we came up with (if anyone out there has a better solution, please tell me about it through a comment or via email).&lt;/p&gt;
&lt;p&gt;The partial for the three input fields looked like (this is in haml and uses the Rails form helper &lt;code&gt;fields_for&lt;/code&gt;):&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/775972.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
&lt;p&gt;And the partial setting up the form along with a &lt;strong&gt;hidden row&lt;/strong&gt; like so:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/776001.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
&lt;p&gt;The resulting form (without the submit button) looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20110115-mm1b6g672a63e2cb7qfhtm5rt3.jpg&quot; alt=&quot;Tell a Friend | ABC Reading Eggs&quot; class=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally, the jQuery that responds to a click on the &amp;#8220;Add another&amp;#8221; link:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/776005.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Clicking on &amp;#8220;Add another&amp;#8221; results in another row of input fields being added to the form as shown in the image below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20110115-jacst77s1rduxx1hemxgk1xuwf.jpg&quot; alt=&quot;Tell a Friend | ABC Reading Eggs&quot; class=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So here is what is happening:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;The form hides the simple three field &lt;code&gt;_invitee_form&lt;/code&gt; in a div with class &lt;code&gt;user_details_base&lt;/code&gt;.  It also shows the first three field row in a div with id &lt;code&gt;user_details&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;The jQuery in &lt;code&gt;form.js&lt;/code&gt; is invoked on clicking the link with id &lt;code&gt;add_user&lt;/code&gt; (i.e. the link &amp;#8220;Add another&amp;#8221;). It selects the class &lt;code&gt;user_details_base&lt;/code&gt;, clones it, appends it to the div with id &lt;code&gt;user_details&lt;/code&gt; (i.e. to the visible part of the form).  Finally, it invokes the action &lt;code&gt;show()&lt;/code&gt;, thereby ensuring that the newly appended row is displayed.&lt;/li&gt;
	&lt;li&gt;What&amp;#8217;s the &lt;code&gt;return false();&lt;/code&gt; about?  Well, this prevents the browser from jumping back to the link anchor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hope this post has proved valuable &amp;#8211; enjoy the wondrous world of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; and JavaScript!&lt;/p&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <entry>
   <title>Notes on setting up a Rails development machine</title>
   <link href="http://novemberkilo.com/2010/08/Dev-machine-setup"/>
   <updated>2010-08-14T00:00:00-07:00</updated>
   <id>http://novemberkilo.com/2010/08/Dev-machine-setup</id>
   <content type="html">&lt;p&gt;I got a job! I&amp;#8217;m a Rails developer at Blake Education, a publishing company that specialises in textbooks, study aids and other material relevant to the education sector. We develop and maintain &lt;a href=&quot;http://readingeggs.com&quot;&gt;readingeggs.com&lt;/a&gt; &amp;#8211; a Rails powered site that is cobranded with &lt;span class=&quot;caps&quot;&gt;ABC&lt;/span&gt; Online. Its goal is to help children learn to read. I&amp;#8217;m delighted to have discovered an opportunity for simultaneously feeding my passions for technology and education!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve worked for high profile consulting firms and obscenely profitable banks but never have I had an employer give me such high quality kit &amp;#8211; I was given a 24&amp;#8217;&amp;#8217; display and a brand new MacBook Pro and spent the first day setting it up. Yay! Well, I learned a few things along the way that I will document here.  Hopefully the tools mentioned here will be of benefit to other newbies looking for tips on setting up their (Rails) development machines/environments.  Seasoned Ruby/Rails/dev types, please comment if you have suggestions for improvements! And yes, some of this is OS X specific.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;XCode:&lt;/strong&gt; Unless you get into ObjectiveC or MacRuby, you are unlikely to need the &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; but package managers for OS X depend on it.  It&amp;#8217;s on the &lt;span class=&quot;caps&quot;&gt;DVD&lt;/span&gt; that came with your Mac but you may be better off just &lt;a href=&quot;http://developer.apple.com/technologies/tools/xcode.html&quot;&gt;downloading&lt;/a&gt; the latest version from Apple.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Babushka:&lt;/strong&gt; Described by its author, &lt;a href=&quot;http://twitter.com/ben_h&quot;&gt;Ben Hoskings,&lt;/a&gt; as &lt;em&gt;test-driven sysadmin,&lt;/em&gt; babushka is a great way to reliably negotiate the hitherto complex and messy installations of things like MySQL and ImageMagick. A great many useful &lt;em&gt;deps&lt;/em&gt; (think recipes) have been written in babushka&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; and I was advised by my new coworkers to use them liberally! See Ben&amp;#8217;s &lt;a href=&quot;http://benhoskin.gs/2010/08/01/getting-started-with-babushka/&quot;&gt;post&lt;/a&gt; on how to get started. Oh, babushka works on OS X and Ubuntu as well.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Homebrew:&lt;/strong&gt; &lt;a href=&quot;http://twitter.com/mxcl&quot;&gt;Max Howell&amp;#8217;s&lt;/a&gt; &lt;a href=&quot;http://mxcl.github.com/homebrew/&quot;&gt;homebrew&lt;/a&gt; is simply an awesome package manager for OS X.  I&amp;#8217;ve tried MacPorts and, well, I think Homebrew is just much more usable! I&amp;#8217;m not the only one either &amp;#8211; see this &lt;a href=&quot;http://www.engineyard.com/blog/2010/homebrew-os-xs-missing-package-manager/&quot;&gt;post&lt;/a&gt; for more.  Use babushka to get homebrew with &lt;code&gt;babushka homebrew&lt;/code&gt; (the dep will check for XCode and this is why it&amp;#8217;s up there on this list).&lt;br /&gt;
The awesomeness of homebrew is demonstrated by the ease with which you can use it to install MySQL. &lt;code&gt;brew install mysql&lt;/code&gt; will do all of the &lt;a href=&quot;http://hivelogic.com/articles/compiling-mysql-on-snow-leopard&quot;&gt;calisthenics&lt;/a&gt; involved! Installing the &lt;code&gt;mysql&lt;/code&gt; gem requires some platform specific flags to be set &amp;#8211; thanks to @defunkt&amp;#8217;s &lt;a href=&quot;http://ozmm.org/posts/homebrew___mysql___snow_leopard.html&quot;&gt;tip&lt;/a&gt; something like this should work on Snow Leopard:&lt;br /&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;sudo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ARCHFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-arch x86_64&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mysql&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/usr/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mysql_config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;rvm:&lt;/strong&gt; Wayne E. Seguin&amp;#8217;s &lt;a href=&quot;http://beginrescueend.com&quot;&gt;Ruby Version Manager,&lt;/a&gt; &lt;code&gt;rvm&lt;/code&gt; is amongst the best things to happen to Ruby in 2010 &amp;#8211; he  won a very well deserved Ruby Hero award for &lt;code&gt;rvm&lt;/code&gt; at RailsConf 2010. &lt;code&gt;rvm&lt;/code&gt; is similar to Python&amp;#8217;s &lt;code&gt;virtualenv&lt;/code&gt; in that it allows you to set up separate environments for your Ruby projects, thereby enabling multiple versions of Ruby, Rails, and other gems to conveniently coexist on the same machine. You can associate &lt;em&gt;gemsets&lt;/em&gt; to separate projects, and specify which version of Ruby and which gems belong to a gemset. Apart from the &lt;a href=&quot;http://beginrescueend.com&quot;&gt;official documentation&lt;/a&gt; there are some excellent posts out there on getting started with &lt;code&gt;rvm.&lt;/code&gt; See @ascarter&amp;#8217;s &lt;a href=&quot;http://ascarter.net/2010/05/30/ruby-version-manager.html&quot;&gt;post&lt;/a&gt; and also check out Michael Hartl&amp;#8217;s updated &lt;a href=&quot;http://railstutorial.org&quot;&gt;Rails Tutorial&lt;/a&gt; for Rails 3 &amp;#8211; it now includes the setup of a gemset for a Rails 3 environment in the first chapter.  If you are working with a project that uses &lt;a href=&quot;http://gembundler.com&quot;&gt;Bundler,&lt;/a&gt; check out Mikel Lindsaar&amp;#8217;s excellent article, &lt;a href=&quot;http://lindsaar.net/2010/3/31/bundle_me_some_sanity&quot;&gt;Bundle me some sanity&lt;/a&gt; for a quick overview of the magic that happens when &lt;code&gt;rvm&lt;/code&gt; and Bundler get together.  I was setting up a project that did not have a Bundler Gemfile associated with it so resorted instead to having one of my new colleagues export their &lt;code&gt;rvm&lt;/code&gt; gemset (associated to the project) and then using &lt;code&gt;rvm gemset import&lt;/code&gt; to simply set up all the gems I needed for my environment.&lt;/li&gt;
&lt;/ol&gt;</content>
   <author>
     <name>Navin Keswani</name>
     <uri>http://novemberkilo.com/about.html</uri>
   </author>
 </entry>
 
 <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>
 
</feed>
