<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Vermonster's Blog</title>
 <link type="application/atom+xml" rel="self" href="http://vermonster.com/atom.xml"/>
 <link type="text/html" rel="alternate" href="http://vermonster.com/"/>
 <updated>2010-09-08T19:30:09-04:00</updated>
 <id>http://vermonster.com/</id>
 <author>
   <name>Brian, Jay and Steve</name>
 </author>
 
 
 <entry>
   <title>Survey says: require 'work' && require 'training'</title>
   <link href="http://vermonster.com/2010/05/19/require-work--require-training/"/>
   <updated>2010-05-19T00:00:00-04:00</updated>
   <id>http://chrononaut.net/2010/05/19/require-work--require-training</id>
   <content type="html">&lt;p&gt;If you are from the Boston -area and are interested in one, some or all of the following:&lt;/p&gt;
&lt;pre&gt;
    [ ] Professional Development
    [ ] Looking for Job Opportunities 
    [ ] Looking for Ruby Talent 
    [ ] Ruby Culture
&lt;/pre&gt;
&lt;p&gt;Take about 5 minutes to fill out &lt;a href='http://spreadsheets.google.com/viewform?hl=en&amp;amp;formkey=dFJRMGpJNXdVdWxNODlLWHNxZ2V0ZEE6MQ'&gt;the real survey&lt;/a&gt;. Do it; it&amp;#8217;s good for your karma.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>NoSQL Workshop - Featuring Riak and CouchDB</title>
   <link href="http://vermonster.com/2010/03/31/nosql-workshop-featuring-riak-and-couchdb/"/>
   <updated>2010-03-31T00:00:00-04:00</updated>
   <id>http://chrononaut.net/2010/03/31/nosql-workshop-featuring-riak-and-couchdb</id>
   <content type="html">&lt;p&gt;This past Tuesday we (Vermonster and &lt;a href='http://gregsterndale.com'&gt;Greg&lt;/a&gt;) hosted the fourth installment of Newer Yankee Workshop. This one was on the über-trendy topic of NoSQL data stores. We covered two - &lt;a href='http://riak.basho.com/'&gt;Basho&amp;#8217;s Riak&lt;/a&gt; and &lt;a href='http://couchdb.apache.org/'&gt;Apache&amp;#8217;s CouchDB&lt;/a&gt;. After this past &lt;a href='http://nosqlboston.eventbrite.com/'&gt;NoSQL Live&lt;/a&gt; event, I personally became very exited about Riak, a relatively new player in NoSQL. CouchDB is a nice RESTful document data and has been around longer than Riak.&lt;/p&gt;

&lt;h4 id='rain_rain_go_away'&gt;Rain, Rain, go Away!&lt;/h4&gt;

&lt;p&gt;The weather was crap, another day of solid rain. Although we filled our capacity on &lt;a href='http://www.eventbrite.com/event/632163819'&gt;EventBrite&lt;/a&gt;, I wasn&amp;#8217;t actually expecting many to trudge through a soggy walk to &lt;a href='http://vermonster.com/contact'&gt;our office&lt;/a&gt;. But I was pleasantly surprised with a solid showing &amp;#8211; we had about 17 people in attendance.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-scene.jpg' alt='Scene' /&gt;&lt;/p&gt;

&lt;h4 id='the_setup'&gt;The Setup&lt;/h4&gt;

&lt;p&gt;Using a crude &lt;a href='http://www.slideshare.net/bkaney/newer-yankee-workshop-nosql'&gt;slide show&lt;/a&gt; as a guide, we had a super brief overview of NoSQL, &lt;a href='http://en.wikipedia.org/wiki/CAP_theorem'&gt;Brewer&amp;#8217;s CAP theorem&lt;/a&gt;, and an introduction to our two data stores. Most everyone in the crowd was armed with OS X, outside of a few running Ubuntu, so installing and starting &lt;a href='https://wiki.basho.com/display/RIAK/Getting+Started'&gt;Riak&lt;/a&gt; and &lt;a href='http://wiki.apache.org/couchdb/Installing_on_OSX'&gt;CouchDB&lt;/a&gt; (for development) was a snap. I recommended people use the Riak binaries (although I think some built from source), and Greg instructed folks to use a &lt;a href='http://wiki.apache.org/couchdb/Installing_on_OSX'&gt;simple one-click-installer for CouchDB&lt;/a&gt;. We got our &lt;a href='http://rvm.beginrescueend.com/'&gt;RVM&lt;/a&gt; on, built a gemset for the workshop and loaded a few gems.&lt;/p&gt;

&lt;h4 id='modeling_a_simple_business_requirement'&gt;Modeling a Simple Business Requirement&lt;/h4&gt;

&lt;p&gt;After everyone was up and running with two shiny NoSQL databases, we presented a simple business problem. The context is a project we are working on here at Vermonster called &lt;em&gt;OpenDocket&lt;/em&gt;. It is still very early on, and respecting brevity, I won&amp;#8217;t go into too many details in this post. But this did introduce two concepts we modeled - 1) Docket Items and 2) Motions. A docket item could have several motions. And a motion belongs to a docket item. A motion also has a number of yea&amp;#8217;s and nay&amp;#8217;s (such that more yea&amp;#8217;s then nay&amp;#8217;s means the motion has passed).&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-orm.png' alt='ORM' /&gt;&lt;/p&gt;

&lt;p&gt;We modeled things in both data stores; using Ripple as an ORM for Riak and Couch Potato for CouchDB. You can see the two versions of the code at &lt;a href='http://github.com/neweryankee/no-sql'&gt;github&lt;/a&gt; (see the &lt;code&gt;riak&lt;/code&gt; and &lt;code&gt;couch&lt;/code&gt; branches). Everyone cloned the repo, ran &lt;code&gt;spec ./spec&lt;/code&gt; in each branch and saw green. Excellent!&lt;/p&gt;

&lt;p&gt;Next we walked through the code describing some of the features of each database.&lt;/p&gt;

&lt;h4 id='mapreduce'&gt;MapReduce&lt;/h4&gt;

&lt;p&gt;Both CouchDB and Riak feature MapReduce functionality. As the data is distributed in these kinds of data stores, collecting and searching (i.e. mapping) also needs to be distributed. Reduction is a phase after map and aggregates the results. Someone made a nice analogy (and I apologize for forgetting your name) with ruby, and &lt;a href='http://twitter.com/hgimenez'&gt;Harold&lt;/a&gt; suggested a once for SQL:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-analogy.png' alt='Analogy' /&gt;&lt;/p&gt;

&lt;p&gt;For those &lt;a href='http://www.nytimes.com/2005/03/13/opinion/13sun3.html'&gt;too young to have missed&lt;/a&gt; (or too old to to remember) analogies on their SATs &amp;#8211; these read &amp;#8220;map is to reduce&amp;#8221; as &amp;#8220;enumerable is to inject in ruby&amp;#8221; and &amp;#8220;map is to reduce&amp;#8221; as &amp;#8220;where clause is to aggregate functions in SQL&amp;#8221;. Examples of aggregate functions in SQL are things like &lt;code&gt;COUNT&lt;/code&gt; and &lt;code&gt;SUM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementing MapReduce functions in both data stores can be written in Javascript. In fact, it is probably worth mentioning that both use a nice RESTful interface with JSON encoded data to do their business. So using Javascript is a natural choice. Also related, Riak can process MapReduce functions in Erlang.&lt;/p&gt;

&lt;h5 id='riak_mapreduce'&gt;Riak MapReduce&lt;/h5&gt;

&lt;p&gt;We used MapReduce to demonstrate the &lt;code&gt;has many&lt;/code&gt; relationship between Docket Item and Motion. In Riak, using the Ripple ORM, this is expressed as:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='n'&gt;motions&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Riak&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;MapReduce&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;new&lt;/span&gt;(&lt;span class='no'&gt;Ripple&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;client&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
    &lt;span class='n'&gt;add&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
    &lt;span class='n'&gt;map&lt;/span&gt;(&lt;span class='n'&gt;motions_map_function&lt;/span&gt;, &lt;span class='ss'&gt;:keep&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To take a step back, Riak&amp;#8217;s MapReduce specification comprises of two components, an &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt;. The &lt;code&gt;add&lt;/code&gt; method allows you to add bucket and tags as the &lt;code&gt;input&lt;/code&gt;. The &lt;code&gt;map&lt;/code&gt; method adds to the &lt;code&gt;query&lt;/code&gt; portion (others include &lt;code&gt;link&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s probably worth mentioning some naming conventions. In Riak there are &lt;code&gt;buckets&lt;/code&gt; that contain objects, identified by &lt;code&gt;keys&lt;/code&gt;. This is similar to other key-store databases, including Amazon S3 (which you may already be familiar with and using).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;motions_map_function&lt;/code&gt; is this method (which is essentially Javascript):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;motions_map_function&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;JAVASCRIPT&lt;/span&gt;
&lt;span class='sh'&gt;      function(v){&lt;/span&gt;
&lt;span class='sh'&gt;        var results = [];&lt;/span&gt;
&lt;span class='sh'&gt;        var motion = JSON.parse(v.values[0].data); motion[&amp;quot;key&amp;quot;] = v.key;&lt;/span&gt;
&lt;span class='sh'&gt;        if(motion.docket_item_key == &amp;#39;#{self.key}&amp;#39;) results.push(motion);&lt;/span&gt;
&lt;span class='sh'&gt;        return results;&lt;/span&gt;
&lt;span class='sh'&gt;      }&lt;/span&gt;
&lt;span class='sh' /&gt;&lt;span class='no'&gt;      JAVASCRIPT&lt;/span&gt;
&lt;span class='no' /&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The map function in Riak can actually be expanded a bit (something we should have spent more time on in the workshop). There are three inputs to the function:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nx'&gt;javascript&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;function&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;item&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;keydata&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arg&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Where &lt;code&gt;item&lt;/code&gt; is the value found at the current key. It has 4 attributes: &lt;code&gt;bucket&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, &lt;code&gt;vclock&lt;/code&gt;, and &lt;code&gt;values&lt;/code&gt;. NOTE: &lt;code&gt;values&lt;/code&gt; is an array because there could be siblings, like during a vclock conflict.&lt;/li&gt;

&lt;li&gt;The second argument, &lt;code&gt;keydata&lt;/code&gt; is the data passed in the &lt;code&gt;input&lt;/code&gt; portion of the call.&lt;/li&gt;

&lt;li&gt;And &lt;code&gt;arg&lt;/code&gt; are any &lt;code&gt;:arg =&amp;gt; ...&lt;/code&gt; values passed in the actual map method.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Riak reduce (not shown for this has_many example) takes in two arguments:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nx'&gt;javascript&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;function&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;valueList&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arg&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;valueList&lt;/code&gt; is the output of the map phase&lt;/li&gt;

&lt;li&gt;&lt;code&gt;arg&lt;/code&gt; is what&amp;#8217;s passed into the &lt;code&gt;reduce&lt;/code&gt; method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both have an optional &lt;code&gt;:keep&lt;/code&gt; parameter that tells Riak whether to save the results of the phase or not. For example, if you had both a map and reduce function, you would likely not keep the map results, but would keep the reduce.&lt;/p&gt;

&lt;p&gt;Additional note, Ripple uses an attribute &lt;code&gt;_type&lt;/code&gt; to track the klass of the object, so it knows what to instantiate when processing retrieved documents.&lt;/p&gt;

&lt;h4 id='couchdb_mapreduce'&gt;CouchDB MapReduce&lt;/h4&gt;

&lt;p&gt;With CouchDB and Couch Potato as our ORM, any time you would like to view results, you first create a view spec. View specs contain map and reduce methods. Couch Potato provides some syntactic sugar that automatically creates MapReduce methods for common views.&lt;/p&gt;

&lt;p&gt;For instance, we have a view called &lt;code&gt;by_id&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='ss'&gt;:by_id&lt;/span&gt;,    &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:_id&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You might notice the key is &lt;code&gt;_id&lt;/code&gt;, this is a convention in CouchDB as the identifier for the document. As &lt;a href='http://gregsterndale.com'&gt;Greg&lt;/a&gt; pointed out, this is kinda nice, where in ActiveRecord, there&amp;#8217;s lots of effort making docket_item.id marry up to the primary id field in the database, all without colliding with Ruby&amp;#8217;s built-in object#id. Additionally, Couch Potato will generate a MapReduce function with this key syntax. In this case, in CouchDB the map looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nx'&gt;javascript&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;function&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ruby_class&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ruby_class&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;DocketItem&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;_id&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='m'&gt;1&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the reduce looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nx'&gt;javascript&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;function&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;values&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;values&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You will notice in Ripple, &lt;code&gt;_type&lt;/code&gt; was used to identify the ruby class type, Couch Potato uses the key &lt;code&gt;ruby_class&lt;/code&gt;. To retrieve data, we pass the view spec as an argument to a &lt;code&gt;#view&lt;/code&gt; method:&lt;/p&gt;

&lt;p&gt;And we have docket items!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;docket_item.motions&lt;/code&gt; has-many relationship to motions was demonstrated by creating a view in the Motion class.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='ss'&gt;:by_docket_item_id&lt;/span&gt;, &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:docket_item_id&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The auto-generated map function looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nx'&gt;javascript&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;function&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ruby_class&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ruby_class&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Motion&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;docket_item_id&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='m'&gt;1&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;(The reduce looks the same as above)&lt;/p&gt;

&lt;p&gt;So then in the DocketItem, we have a method that calls this passing in the docket_item&amp;#8217;s id as a key:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;motions&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;_id&lt;/span&gt;
      &lt;span class='n'&gt;view_spec&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Motion&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;by_docket_item_id&lt;/span&gt;( &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;_id&lt;/span&gt; )
      &lt;span class='no'&gt;CouchPotato&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;database&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt;(&lt;span class='n'&gt;view_spec&lt;/span&gt;)
    &lt;span class='k'&gt;else&lt;/span&gt;
      &lt;span class='o'&gt;[]&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='link_walking_riak'&gt;Link Walking (Riak)&lt;/h4&gt;

&lt;p&gt;One Riak feature I am very excited about is &lt;a href='http://wiki.basho.com/display/RIAK/Links'&gt;link walking&lt;/a&gt;. This feature lets you create links from one object to another, while tagging. It is similiar to having named edges in graph databases.&lt;/p&gt;

&lt;p&gt;Consider the relationship Docket Item has many Motions. Previously we showed this with a MapReduce method. But this could have just been implemented using links. This technique was shown by first creating links in an &lt;code&gt;after_save&lt;/code&gt; in motion.rb.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='n'&gt;after_save&lt;/span&gt; &lt;span class='ss'&gt;:create_links&lt;/span&gt;
  
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create_links&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;docket_item_key&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;robject&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;links&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Riak&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Link&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;new&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;/riak/docket_items/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;docket_item_key&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;, &lt;span class='s2'&gt;&amp;quot;docket_item&amp;quot;&lt;/span&gt;)
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;robject&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;store&lt;/span&gt;
 
      &lt;span class='n'&gt;d&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;docket_item&lt;/span&gt;
      &lt;span class='n'&gt;d&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;send&lt;/span&gt;(&lt;span class='ss'&gt;:robject&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;links&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Riak&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Link&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;new&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;/riak/motions/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;, &lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;)
      &lt;span class='n'&gt;d&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;send&lt;/span&gt;(&lt;span class='ss'&gt;:robject&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;store&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;One curve here is &lt;code&gt;robject&lt;/code&gt;. This is the Riak object (in Ripple, there are two namespaces, Riak and Ripple, the former is a lower-level interface to the Riak server). This allows us access to the links getter/setter. Also worth noting is the &lt;code&gt;robject&lt;/code&gt; saves with a &lt;code&gt;store&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So let&amp;#8217;s examine what&amp;#8217;s going on here. Basically, we create two links after each motion is saved.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-link-1.png' alt='Link 1' /&gt;&lt;/p&gt;

&lt;p&gt;And this sort of thing would happen for any number of motions for Docket Item 1.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-link-2.png' alt='Link 2' /&gt;&lt;/p&gt;

&lt;p&gt;Link walking is preformed by starting at a document object, then indicating which bucket to enter. Riak will follow any link that connects the object to any object in the specified bucket. To restrict which links to follow, a tag parameter can be supplied when walking. This basically means &amp;#8220;follow any link to this bucket that are tagged that&amp;#8221;. As Riak uses REST, you can actually test this in your web browser:&lt;/p&gt;

&lt;p&gt;This would follow any links from docket item with the specified key to the motions bucket with any tag (the first &lt;code&gt;_&lt;/code&gt;, the last &lt;code&gt;_&lt;/code&gt; is a keep flag). Using Ripple, we can preform a link-walk with a simple &lt;code&gt;walk&lt;/code&gt; as seen in the &lt;code&gt;motions_via_link&lt;/code&gt; method:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;motions_via_links&lt;/span&gt;
    &lt;span class='n'&gt;motions&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;robject&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;walk&lt;/span&gt;(&lt;span class='ss'&gt;:bucket&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatten&lt;/span&gt;
 
    &lt;span class='n'&gt;motions&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;{&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;instantiate&lt;/span&gt;(&lt;span class='n'&gt;m&lt;/span&gt;) }
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;:bucket&lt;/code&gt; and &lt;code&gt;:tag&lt;/code&gt; are parameters.&lt;/p&gt;

&lt;p&gt;To build on this, suppose we created a link when a motion passes, with a &lt;code&gt;passed_motions&lt;/code&gt; tag (and could also create one for &lt;code&gt;failed_motions&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/nosql-link-3.png' alt='Link 3' /&gt;&lt;/p&gt;

&lt;p&gt;That would allow us to do things like&lt;/p&gt;

&lt;p&gt;This allows for very interesting slicing and dicing of how data is related without writing methods in the application layer. &lt;em&gt;AND&lt;/em&gt; link walking can be part of a MapReduce method, way cool indeed! Here&amp;#8217;s an example getting the all the passing motion titles.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='no'&gt;Riak&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;MapReduce&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;new&lt;/span&gt;(&lt;span class='n'&gt;client&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
    &lt;span class='n'&gt;add&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
    &lt;span class='n'&gt;link&lt;/span&gt;(&lt;span class='ss'&gt;:bucket&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;, &lt;span class='ss'&gt;:tag&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;passed_motions&amp;quot;&lt;/span&gt;, &lt;span class='ss'&gt;:keep&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
    &lt;span class='n'&gt;map&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;function(v){ return [JSON.parse(v.values[0].data).title]; }&amp;quot;&lt;/span&gt;, &lt;span class='ss'&gt;:keep&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='the_challenge'&gt;The Challenge&lt;/h4&gt;

&lt;p&gt;After all this, we issued a challenge, &amp;#8220;Find the difference between yeas and nays&amp;#8221;. Some used CouchDB and others used Riak and everyone had their hands on creating actual MapReduce functions.&lt;/p&gt;

&lt;h4 id='outcome'&gt;Outcome&lt;/h4&gt;

&lt;p&gt;&lt;a href='http://twitter.com/victor_costan'&gt;Victor&lt;/a&gt; was quick at the draw and came up with the following Riak solution:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;delta_yeas_nays&lt;/span&gt;
    &lt;span class='n'&gt;motions&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Riak&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;MapReduce&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;new&lt;/span&gt;(&lt;span class='no'&gt;Ripple&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;client&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='n'&gt;add&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;motions&amp;quot;&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='n'&gt;map&lt;/span&gt;(&lt;span class='n'&gt;delta_map_function&lt;/span&gt;, &lt;span class='ss'&gt;:keep&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='n'&gt;reduce&lt;/span&gt;(&lt;span class='n'&gt;delta_reduce_function&lt;/span&gt;, &lt;span class='ss'&gt;:keep&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='n'&gt;run&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='kp'&gt;private&lt;/span&gt;

  &lt;span class='c1'&gt;# A map function to get the motions given a docket item key&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;delta_map_function&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;JAVASCRIPT&lt;/span&gt;
&lt;span class='sh'&gt;    function(v){&lt;/span&gt;
&lt;span class='sh'&gt;        var results = [];&lt;/span&gt;
&lt;span class='sh'&gt;        var motion = JSON.parse(v.values[0].data);&lt;/span&gt;
&lt;span class='sh'&gt;        results.push((motion.yeas || 0) - (motion.nays || 0));&lt;/span&gt;
&lt;span class='sh'&gt;        return results;&lt;/span&gt;
&lt;span class='sh'&gt;    }&lt;/span&gt;
&lt;span class='sh' /&gt;&lt;span class='no'&gt;    JAVASCRIPT&lt;/span&gt;
&lt;span class='no' /&gt;  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;delta_reduce_function&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;JAVASCRIPT&lt;/span&gt;
&lt;span class='sh'&gt;    function(results){&lt;/span&gt;
&lt;span class='sh'&gt;        var sum = 0;&lt;/span&gt;
&lt;span class='sh'&gt;        for(var i = 0; i &amp;lt; results.length; i++) { sum += results[i]; }&lt;/span&gt;
&lt;span class='sh'&gt;        return sum;&lt;/span&gt;
&lt;span class='sh'&gt;    }&lt;/span&gt;
&lt;span class='sh' /&gt;&lt;span class='no'&gt;    JAVASCRIPT&lt;/span&gt;
&lt;span class='no' /&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the following CouchDB solution:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;ruby&lt;/span&gt; &lt;span class='o'&gt;--&lt;/span&gt;

  &lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='ss'&gt;:delta_yeas_nays&lt;/span&gt;,
       &lt;span class='ss'&gt;:map&lt;/span&gt;            &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;function(doc){ emit(doc._id, (doc.yeas || 0) - (doc.nays || 0)); }&amp;quot;&lt;/span&gt;,
       &lt;span class='ss'&gt;:reduce&lt;/span&gt;         &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;function(keys, values){ return sum(values) }&amp;quot;&lt;/span&gt;,
       &lt;span class='ss'&gt;:type&lt;/span&gt;           &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:raw&lt;/span&gt;,
       &lt;span class='ss'&gt;:include_docs&lt;/span&gt;   &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;,
       &lt;span class='ss'&gt;:results_filter&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nb'&gt;lambda&lt;/span&gt; {&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;results&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;results&lt;/span&gt;[&lt;span class='s1'&gt;&amp;#39;rows&amp;#39;&lt;/span&gt;]&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;first&lt;/span&gt;[&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;] }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='takeaways'&gt;Take-aways&lt;/h4&gt;

&lt;p&gt;As some attendees dove into TDD mode, it was quickly obvious that without database transactions, it is difficult to test without manually clearing the database. I think that a simple extension to &lt;a href='http://github.com/bmabey/database_cleaner'&gt;database_cleaner&lt;/a&gt; to support Riak would go a long way.&lt;/p&gt;

&lt;p&gt;Also, working on TDD for the reduce functions themselves using jspec would also be terrific.&lt;/p&gt;

&lt;p&gt;This was a really fun workshop to put on, it really pressed our learning of NoSQL in preparation. And I&amp;#8217;d like to thank everyone that made it out through the sogginess.&lt;/p&gt;

&lt;p&gt;One thing not covered was embedded documents. Partially because we ran out of time in our preparation and partially because we ran out of time in the workshop.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Build-a-Gem Workshop Recap</title>
   <link href="http://vermonster.com/2010/02/26/build-a-gem-workshop-recap/"/>
   <updated>2010-02-26T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2010/02/26/build-a-gem-workshop-recap</id>
   <content type="html">&lt;p&gt;We had another Newer Yankee Workshop on Tuesday, following the success of our previous &lt;a href='/2009/12/16/cucumber-workshop-recap'&gt;Cucumber&lt;/a&gt; session in our &lt;a href='/2010/01/27/we-moved-to-71-broad-st-in-boston'&gt;new office&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/build-a-gem-1.jpg' alt='Build-a-Gem 1' /&gt; &lt;img src='/images/blog/build-a-gem-2.jpg' alt='Build-a-Gem 2' /&gt;&lt;/p&gt;

&lt;p&gt;We started by &lt;a href='http://www.slideshare.net/bkaney/buildagem-workshop'&gt;reviewing gem basics&lt;/a&gt; &amp;#8211; what it is, how it&amp;#8217;s made, how it&amp;#8217;d distributed, etc. Then we jumped into a simple hello-world project using the venerable &lt;a href='http://github.com/technicalpickles/jeweler'&gt;Jeweler&lt;/a&gt;. Greg Sterndale then took the driver&amp;#8217;s seat and walked us through &amp;#8220;gemifying&amp;#8221; an &lt;a href='http://rubygems.org/gems/nextbus'&gt;existing project&lt;/a&gt; (which happens to be a &lt;a href='http://github.com/neweryankee/nextbus'&gt;pretty useful library&lt;/a&gt; to talk to &lt;a href='http://www.nextbus.com'&gt;Nextbus&lt;/a&gt;, the provider of future MBTA bus data, among &lt;a href='http://www.nextbus.com/predictor/simpleRegionSelector.shtml'&gt;many other agencies&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We then paired up and started hacking our own gems. There were are few that used the Massachusetts RMV wait time feed (like &lt;a href='http://rubygems.org/gems/bouvier'&gt;Bouvier&lt;/a&gt;, by yours truly and Jay). I saw one team playing with Last.fm&amp;#8217;s API and one that even ran python code (for some reason).&lt;/p&gt;

&lt;p&gt;It was a good session and I&amp;#8217;m looking a next one on a topic TBD.. Maybe using a NoSQL database, Rails 3, Rack-ifying a feature, or something else?&lt;/p&gt;

&lt;p&gt;UPDATE: &lt;a href='http://rubygems.org/gems/simple-twilio'&gt;simple-twilio&lt;/a&gt; is another one by Pascal and Jeff&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>We Moved to 71 Broad St in Boston</title>
   <link href="http://vermonster.com/2010/01/27/we-moved-to-71-broad-st-in-boston/"/>
   <updated>2010-01-27T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2010/01/27/we-moved-to-71-broad-st-in-boston</id>
   <content type="html">&lt;p&gt;After 8ish years on Stuart St, we moved our office. We are still unpacking, setting things up and starting to settle in.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/pages/move.png' alt='Move' /&gt;&lt;/p&gt;

&lt;p&gt;Our new office is an open floor space in what I believe is a building that once was used as a candle factory some 150+ years ago (yea, it&amp;#8217;s that old). We will be posting pictures soon. In the meantime, update your address books:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Vermonster LLC
71 Broad St, 4th Floor
Boston, MA  02109&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We have a new phone number too:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;617-482-2020&lt;/code&gt;&lt;/pre&gt;</content>
 </entry>
 
 <entry>
   <title>Recommended Omnigraffle Guide for Rails ORM</title>
   <link href="http://vermonster.com/2009/12/29/recommended-omnigraffle-guide-for-rails-orm/"/>
   <updated>2009-12-29T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/12/29/recommended-omnigraffle-guide-for-rails-orm</id>
   <content type="html">&lt;p&gt;We recently developed a work-in-progress style guide for using &lt;a href='http://www.omnigroup.com/applications/OmniGraffle'&gt;Omnigraffle&lt;/a&gt; to describe Object Relationship Mappings (ORMs) in our Rails applications. We wanted to use simple, standard stencils while being able to exhaustively describe relationships. We also wanted to have them be fairly obvious to developers.&lt;/p&gt;

&lt;h3 id='has_one__belongs_to'&gt;Has One / Belongs To&lt;/h3&gt;

&lt;p&gt;One of the more common relationships is &lt;a href='http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001835'&gt;&lt;code&gt;belongs_to&lt;/code&gt;&lt;/a&gt;. We decided to show this as a line on the connector toward the belonging model. The sometimes-ambiguous sibling, &lt;a href='http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001834'&gt;&lt;code&gt;has_one&lt;/code&gt;&lt;/a&gt; is shown as a block toward the belonging model. In both cases, we use the unfilled circle/square to show optional.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/has_one_belongs_to.png' alt='Has One and Belongs To' /&gt;&lt;/p&gt;

&lt;h3 id='has_many'&gt;Has Many&lt;/h3&gt;

&lt;p&gt;The &lt;a href='http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001833'&gt;&lt;code&gt;has_many&lt;/code&gt;&lt;/a&gt; relationship is shown as &amp;#8220;crows feet&amp;#8221; stretching toward the child model. We use the unfilled circle to show optional relationship. The fairly common combination of a &lt;code&gt;belongs_to&lt;/code&gt; and &lt;code&gt;has_many&lt;/code&gt; is shown as as a combination of the crows feet and line connector.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/has_many_belongs_to.png' alt='Has Many and Belongs To' /&gt;&lt;/p&gt;

&lt;h3 id='through_habtm_and_polymorphic'&gt;Through, HABTM and Polymorphic&lt;/h3&gt;

&lt;p&gt;The through relationship, or one that uses a joining table, is show shown as a block using the double -greater and -less than symbols &amp;#60;&amp;#60;through&amp;#62;&amp;#62;. Then we use an arrow to point at the joining model.&lt;/p&gt;

&lt;p&gt;The &lt;a href='http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001836'&gt;has and belongs to many relationship&lt;/a&gt; is shows as double crows-feet with a perpendicular line on each end.&lt;/p&gt;

&lt;p&gt;The &lt;a href='http://wiki.rubyonrails.org/howtos/db-relationships/polymorphic'&gt;polymorphic relationship&lt;/a&gt; is shown as a rectangle, like a model class, but the name of the relationship is shown in &amp;#60;brackets&amp;#62;. This lets us know the object is not an actual model.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/polymorphic_through.png' alt='Polymorphic and Through Relationships' /&gt;&lt;/p&gt;

&lt;p&gt;And finally, a combination of all the relationships discussed here.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/orm_combination.png' alt='Combination' /&gt;&lt;/p&gt;
&lt;p class='callout'&gt;UPDATE: Jan 8, 2010 -- Changed the way through relationships are described.  Swapped the 
&lt;code&gt;belongs_to&lt;/code&gt; and &lt;code&gt;has_many&lt;/code&gt; symbols to make room for the 
&lt;code&gt;has_and_belongs_to_many&lt;/code&gt; (habtm) relationship.&lt;/p&gt;
&lt;h3 id='links'&gt;Links&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.omnigroup.com/applications/OmniGraffle'&gt;Omnigraffle&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/bkaney/omnigraffle_rails_orm_examples'&gt;Source Files&lt;/a&gt; (Github)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to &lt;a href='http://gregsterndale.com'&gt;Greg Sterndale&lt;/a&gt; for his feedback.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Cucumber Workshop Recap</title>
   <link href="http://vermonster.com/2009/12/16/cucumber-workshop-recap/"/>
   <updated>2009-12-16T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/12/16/cucumber-workshop-recap</id>
   <content type="html">&lt;p&gt;Thanks to Greg Sterndale for running the show and &lt;a href='http://plectix.com'&gt;Plectix&lt;/a&gt; for footing the food bill, we had a fantastic hands-on workshop last evening on &lt;a href='http://cukes.info'&gt;Cucumber&lt;/a&gt;. The turnout was much better than expected &amp;#8211; I think nearly 20 people attended!&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/cucumber-workshop-3.jpg' alt='Cucumber 3' /&gt; &lt;img src='/images/blog/cucumber-workshop-2.jpg' alt='Cucumber 2' /&gt;&lt;/p&gt;

&lt;p&gt;Greg did a great job taking us through the &lt;a href='http://cukes.info'&gt;Cucumber&lt;/a&gt; basics &amp;#8211; walking through an example demonstrating pending and unimplemented features. Here are some take-aways and interesting conversation points.&lt;/p&gt;

&lt;h4 id='gem_bundler'&gt;Gem Bundler&lt;/h4&gt;

&lt;p&gt;We attempted to use modern tools and techniques for this project. The workshop project, called &lt;a href='http://github.com/neweryankee/codestache'&gt;Code Stache&lt;/a&gt;, uses &lt;a href='http://github.com/neweryankee/codestache/tree/title'&gt;Rails 2.3.5&lt;/a&gt; and the soon-to-be-de-facto &lt;a href='http://github.com/wycats/bundler'&gt;gem bundler&lt;/a&gt; for gem specifying and inventorying (um, but it doesn&amp;#8217;t work in ruby1.9). Gem bundler is fairly new, so it was not surprising that there was some discussion on this topic. The folks who use gem bundler seem to agree it is awesome but there are some missing features, including more usage instructions and visibility to what is actually going on during the bundle process.&lt;/p&gt;

&lt;p&gt;After &lt;code&gt;rake bundle&lt;/code&gt;, we were good to go. One important aspect (and feature) of gem bundler is any &amp;#8220;binaries&amp;#8221; that gems create (like &lt;code&gt;cucumber&lt;/code&gt; or &lt;code&gt;rspec&lt;/code&gt;) will end up in &lt;code&gt;RAILS_ROOT/bin&lt;/code&gt;. These should be used instead of the system gems to ensure the correct version is being executed. So from &lt;code&gt;RAILS_ROOT&lt;/code&gt;, instead of issuing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cucumber&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bin/cucumber&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id='machinist_vs_factory_girl_vs_fixtures'&gt;Machinist vs. Factory Girl (vs. Fixtures)&lt;/h4&gt;

&lt;p&gt;Fairly quickly our of the gate, we had a discussion on using object factories instead of fixtures. Examples of object factories include &lt;a href='http://github.com/thoughtbot/factory_girl/'&gt;factory_girl&lt;/a&gt; and &lt;a href='http://github.com/notahat/machinist'&gt;Machinist&lt;/a&gt; - both work really well with Cucumber. In our example, we used factory_girl.&lt;/p&gt;

&lt;p&gt;Some of the Machinist fans found the integration of Sham and Faker for completely random data, along with simple association declarations makes it a solid choice. It was also brought up that factory_girl could use the Machinist API (at least I think this was mentioned).&lt;/p&gt;

&lt;p&gt;But without getting into a religious war, using an object factory pattern is clearly a win.&lt;/p&gt;

&lt;h4 id='features__consumable_by_nonprogrammers'&gt;Features - Consumable by Non-Programmers?&lt;/h4&gt;

&lt;p&gt;The discussion of what the actual value of human-readable features is and if it&amp;#8217;s worth the effort go through this DSL. Some developers out there &lt;a href='http://blog.voxdolo.me/given-due-consideration.html'&gt;believe it is not worth the effort&lt;/a&gt;, but the consensus at the workshop was cucumber human-readable features are worth it. It also seemed that developers are primarily responsible for authoring feature files; then QA or stakeholders review and provide acceptance.&lt;/p&gt;

&lt;h4 id='using_ivars'&gt;Using IVARs&lt;/h4&gt;

&lt;p&gt;Along with non-programmer interaction with feature files, the use of instance variables is a common topic when discussing cucumber. Using instance vars does make individual steps less modular &amp;#8211; you can&amp;#8217;t cherry-pick a step if it relies on something being set, for one. But setting up a state, like an actor or current user, can simplify features with intentional and calculated deviation from pure &amp;#8220;no-ivar&amp;#8221; philosophy.&lt;/p&gt;

&lt;p&gt;In the end, it seemed that being pragmatic and trying to minimize the use of instance variables was the consensus.&lt;/p&gt;

&lt;h4 id='pickle__making_life_less_cucumbersum'&gt;Pickle - Making Life less &amp;#8220;Cucumbersum&amp;#8221;&lt;/h4&gt;

&lt;p&gt;&lt;a href='http://ianwhite.github.com/pickle/'&gt;Pickle&lt;/a&gt; is a nice way to interact with your object factories in cucumber. Steve created a &lt;a href='http://github.com/neweryankee/codestache/tree/pickle'&gt;pickle branch in codestache&lt;/a&gt; where the &lt;a href='http://github.com/neweryankee/codestache/commit/18c4cacfdcf3ef3b5e41b0d25200cc9eab5c450e'&gt;manual factory step was replaced with Pickle steps&lt;/a&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;features/share_code.feature
&lt;span class='gu'&gt;@@ -17,6 +17,6 @@ Scenario: Create a code snippet&lt;/span&gt;
&lt;span class='gu' /&gt;     And I should be on the &amp;quot;sudo rm -rf /&amp;quot; snippet page

 Scenario: View a code snippet
&lt;span class='gd'&gt;-  Given a snippet exists with a body of &amp;quot;sudo rm -rf /&amp;quot;&lt;/span&gt;
&lt;span class='gd' /&gt;&lt;span class='gi'&gt;+  Given a snippet exists with body: &amp;quot;sudo rm -rf /&amp;quot;&lt;/span&gt;
&lt;span class='gi' /&gt;
features/step_definitions/share_code_steps.rb
&lt;span class='gu'&gt;@@ -1,3 +0,0 @@&lt;/span&gt;
&lt;span class='gu' /&gt;&lt;span class='gd'&gt;-Given /^a snippet exists with an? (.*) of &amp;quot;([^&amp;quot;]*)&amp;quot;$/ do |attr, value|&lt;/span&gt;
&lt;span class='gd'&gt;-  Factory(:snippet, attr.gsub(&amp;#39; &amp;#39;, &amp;#39;_&amp;#39;) =&amp;gt; value)&lt;/span&gt;
&lt;span class='gd'&gt;-end&lt;/span&gt;
&lt;span class='gd' /&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Later today in IRC (#boston.rb), &lt;a href='http://enlightsolutions.com'&gt;Dan Pickett&lt;/a&gt; pointed out that factory_girl actually has &lt;a href='http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/step_definitions.rb'&gt;some undocumented pickle-like step definitions&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id='xpath_selectors_instead_of_css_selectors'&gt;XPath Selectors (instead of CSS Selectors)&lt;/h4&gt;

&lt;p&gt;In the &lt;a href='http://github.com/neweryankee/codestache/tree/title'&gt;original codestache &lt;code&gt;title&lt;/code&gt; branch&lt;/a&gt;, we had a feature like this to help us specify there ought to be two fields, &lt;code&gt;body&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt;, using some webrat CSS selectors:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Visit the home page
	Given I am on the home page
	 Then I should see &amp;quot;New snippet&amp;quot;	
	  And I should see &amp;quot;Title&amp;quot; within &amp;quot;label[for=snippet_title]&amp;quot;
	  And I should see &amp;quot;Body&amp;quot; within &amp;quot;label[for=snippet_body]&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Arguably, this exposes internal view implementation and not business requirements. Fortunately, &lt;a href='http://github.com/ajvargo'&gt;ajvargo&lt;/a&gt; was in attendance and provided this step definition that uses XPath to marry up semantic form labels to their respective fields. It is still work-in-progress, and won&amp;#8217;t work with the non-for, &lt;code&gt;&amp;lt;label&amp;gt;Label&amp;lt;input id=&amp;quot;foo&amp;quot; name=&amp;quot;foo&amp;quot;/&amp;gt;&amp;lt;/label&amp;gt;&lt;/code&gt; style, but removes the CSS selector from the feature (and I believe he also mentioned this works well with Selenium).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;    &lt;span class='c1'&gt;# Uses xpath to check for a form element based on the label,&lt;/span&gt;
    &lt;span class='c1'&gt;# instead of using a css selector.&lt;/span&gt;
    &lt;span class='no'&gt;Then&lt;/span&gt;&lt;span class='sr'&gt; /^I should see a &amp;quot;([^\&amp;quot;]*)&amp;quot; for &amp;quot;([^\&amp;quot;]*)&amp;quot;$/&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;type&lt;/span&gt;, &lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;

      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nb'&gt;type&lt;/span&gt;
        &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Button&amp;#39;&lt;/span&gt;
          &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_xpath&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;//input[@type=&amp;#39;submit&amp;#39; and @value=&amp;#39;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;#39;]&amp;quot;&lt;/span&gt;)
        &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Text Field&amp;#39;&lt;/span&gt;
          &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_xpath&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;//input[@type=&amp;#39;text&amp;#39; and @id=..//label[normalize-space(text())=&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;]//@for]&amp;quot;&lt;/span&gt;)
        &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Text Area&amp;#39;&lt;/span&gt;
          &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_xpath&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;//textarea[@id=..//label[normalize-space(text())=&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;]//@for]&amp;quot;&lt;/span&gt;)
        &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Radio Button&amp;#39;&lt;/span&gt;
          &lt;span class='n'&gt;pending&lt;/span&gt;
        &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Select Field&amp;#39;&lt;/span&gt;
          &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_xpath&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;//select[@id=..//label[normalize-space(text())=&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;]//@for]&amp;quot;&lt;/span&gt;)
        &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;pending&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So with this step definition, our feature could now like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Visit the home page
  Given I am on the home page
   Then I should see &amp;quot;New snippet&amp;quot;	
    And I should see a &amp;quot;Text Field&amp;quot; for &amp;quot;Title&amp;quot;
    And I should see a &amp;quot;Text Area&amp;quot; for &amp;quot;Body&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id='feedback'&gt;Feedback&lt;/h4&gt;

&lt;p&gt;One area we didn&amp;#8217;t get to much into was the reuse of scenarios in step definitions. For instance, some login feature could be cuke&amp;#8217;d with ample of detail, then consolidated and referenced as a &amp;#8216;When I successfully login&amp;#8217; step for subsequent new features.&lt;/p&gt;

&lt;p&gt;Another item we missed talking about was cucumber tagging. As cucumber test suites can grow in size and run-time, using tagging can be a way to isolate tests locally during development (continuous integration should continue to run the entire suite). Also, we didn&amp;#8217;t really cover the special &lt;code&gt;@wip&lt;/code&gt; tag, which marks features as works-in-progress.&lt;/p&gt;

&lt;p&gt;Other feedback included better instructions getting people setup before-hand. Our internet pipe was laboring as everyone was cloning the project at the same time.&lt;/p&gt;

&lt;p&gt;The balance of roughly 50% discussion and 50% hands-on coding, seems to resonate well.&lt;/p&gt;

&lt;p&gt;All-in-all, it was a very successful maiden &amp;#8220;Newer Yankee Workshop&amp;#8221; &amp;#8211; we are looking forward (and looking for topic suggestions) for future ones!&lt;/p&gt;

&lt;h4 id='related_links'&gt;Related Links&lt;/h4&gt;

&lt;p&gt;Cucumber: &lt;a href='http://cukes.info'&gt;http://cukes.info&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Webrat: &lt;a href='http://wiki.github.com/brynary/webrat'&gt;http://wiki.github.com/brynary/webrat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Background on BDD and user stories: &lt;a href='http://dannorth.net/whats-in-a-story'&gt;http://dannorth.net/whats-in-a-story&lt;/a&gt; &lt;a href='http://www.infoq.com/news/2008/06/new-user-story-format'&gt;http://www.infoq.com/news/2008/06/new-user-story-format&lt;/a&gt; &lt;a href='http://sirenian.livejournal.com/47679.html'&gt;http://sirenian.livejournal.com/47679.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Handy XPath step definition: &lt;a href='http://gist.github.com/257503'&gt;http://gist.github.com/257503&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gemcutter: &lt;a href='http://gemcutter.org'&gt;http://gemcutter.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gem Bundler: &lt;a href='http://github.com/wycats/bundler'&gt;http://github.com/wycats/bundler&lt;/a&gt; &lt;a href='http://yehudakatz.com/2009/11/03/using-the-new-gem-bundler-today/'&gt;http://yehudakatz.com/2009/11/03/using-the-new-gem-bundler-today/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;factory_girl: &lt;a href='http://github.com/thoughtbot/factory_girl'&gt;http://github.com/thoughtbot/factory_girl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Machinist: &lt;a href='http://github.com/notahat/machinist'&gt;http://github.com/notahat/machinist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rubular, helpful for crafting regular expressions: &lt;a href='http://rubular.com'&gt;http://rubular.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pickle: &lt;a href='http://ianwhite.github.com/pickle/'&gt;http://ianwhite.github.com/pickle/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Railscasts (Cucumber, Webrat and Pickle): &lt;a href='http://railscasts.com/episodes?search=cucumber'&gt;http://railscasts.com/episodes?search=cucumber&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Getting setup (with link to a great Cucumber/TextMate bundle): &lt;a href='http://neweryankee.github.com/codestache/'&gt;http://neweryankee.github.com/codestache/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Greg&amp;#8217;s simple slides from last night: &lt;a href='http://www.slideshare.net/gsterndale/cucumber-2730469'&gt;http://www.slideshare.net/gsterndale/cucumber-2730469&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And of course, Code Stache &lt;a href='http://codestache.com/snippets/1'&gt;http://codestache.com/snippets/1&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mysql::Error: Lock wait timeout exceeded; try restarting transaction</title>
   <link href="http://vermonster.com/2009/12/11/mysql-error-lock-wait-timeout-exceeded-try-restarting-transaction/"/>
   <updated>2009-12-11T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/12/11/mysql-error-lock-wait-timeout-exceeded-try-restarting-transaction</id>
   <content type="html">&lt;p&gt;This post pertains to MySQL with InnoDB.&lt;/p&gt;

&lt;p&gt;With heavy concurrency it is common to see the &amp;#8220;Lock wait timeout&amp;#8221; error on some database transactions. This is a temporary error that can often be made to go away just by trying the transaction again. Here is a little helper method you can put in a Rails initializer, for instance, to give your model a concise way to retry a few times.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;retry_mysql_error&lt;/span&gt;(&lt;span class='n'&gt;tries&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;, &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;)
    &lt;span class='n'&gt;count&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
    &lt;span class='k'&gt;begin&lt;/span&gt;
      &lt;span class='n'&gt;count&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
      &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;call&lt;/span&gt;
    &lt;span class='k'&gt;rescue&lt;/span&gt; &lt;span class='no'&gt;Mysql&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Error&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;count&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;tries&lt;/span&gt;
        &lt;span class='nb'&gt;sleep&lt;/span&gt;(&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;count&lt;/span&gt;)
        &lt;span class='k'&gt;retry&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;raise&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Just pass it a block (and an optional number of tries) and it should help to reduce the number of timeouts you see. Be careful not to carry over inadvertently any assumptions across retries.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Download&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;Download&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;increment_download_count!&lt;/span&gt;(&lt;span class='n'&gt;filename&lt;/span&gt;)
    &lt;span class='no'&gt;Download&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;retry_mysql_error&lt;/span&gt;(&lt;span class='mi'&gt;5&lt;/span&gt;) &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='n'&gt;record&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Download&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_by_filename&lt;/span&gt;(&lt;span class='n'&gt;filename&lt;/span&gt;)
      &lt;span class='n'&gt;record&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;download_count&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
      &lt;span class='n'&gt;record&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save!&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It also plays nice with RSpec.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;describe&lt;/span&gt; &lt;span class='no'&gt;Download&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;

  &lt;span class='n'&gt;describe&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;increment_download_count!&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;

    &lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;retries mysql error five times&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='no'&gt;Download&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should_receive&lt;/span&gt;(&lt;span class='ss'&gt;:find_by_filename&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exactly&lt;/span&gt;(&lt;span class='mi'&gt;5&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;and_raise&lt;/span&gt;(&lt;span class='no'&gt;Mysql&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Error&lt;/span&gt;)
      &lt;span class='nb'&gt;lambda&lt;/span&gt; { &lt;span class='no'&gt;Download&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;increment_download_count!&lt;/span&gt;(&lt;span class='kp'&gt;true&lt;/span&gt;) }&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;raise_error&lt;/span&gt;(&lt;span class='no'&gt;Mysql&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Error&lt;/span&gt;)
    &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Of course, this technique should be balanced against other considerations. If it is unable to complete successfully after all the retries, it will re-raise the &lt;code&gt;Mysql::Error&lt;/code&gt;. If this happens often, you might need to make deeper changes to your application.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Fun with Tomatoi.st; the Pomodoro Technique</title>
   <link href="http://vermonster.com/2009/11/11/fun-with-tomatoist-the-pomodoro-technique/"/>
   <updated>2009-11-11T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/11/11/fun-with-tomatoist-the-pomodoro-technique</id>
   <content type="html">&lt;p&gt;I did a lightening talk at this past &lt;a href='http://bostonrb.org'&gt;Boston.rb&lt;/a&gt; meeting about the &lt;a href='http://pomodorotechnique.com'&gt;Pomodoro Technique&lt;/a&gt;, including &lt;a href='http://blog.voxdolo.me/you-say-tomato.html'&gt;Stephen Caudill&amp;#8217;s&lt;/a&gt; recently launched &lt;a href='http://tomatoi.st'&gt;Tomatoi.st&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Pomodoro Technique (PT) uses behavioral rules to help focus time and increase overall productivity. The rules attempt to build a nice mental rhythm while adding a feeling of time-importance to you and your workmates. But the main goal is to alleviating anxiety due to the perception of having not enough time via a bit of a mind hack &amp;#8211; changing the way we use time.&lt;/p&gt;

&lt;p&gt;Francesco Cirillo, creator of the technique, recommends that a modest measure of time, like 20-40 minutes, followed by a shorter break, like 5 minutes for a few cycles, then a longer break. He apparently did research to come to this time pattern.&lt;/p&gt;

&lt;p&gt;The quickstart is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a timer to 25 minutes&lt;/li&gt;

&lt;li&gt;Take a 5 minute break&lt;/li&gt;

&lt;li&gt;Repeat for 4 cycles&lt;/li&gt;

&lt;li&gt;Take a 25 minute break&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href='http://tomatoi.st'&gt;Tomatoi.st&lt;/a&gt; is a simple web-based timer to help you out. It is ideal as a &lt;a href='http://fluidapp.com'&gt;Fluid&lt;/a&gt; application if you are using OSX (it even integrates with growl). Here is an icon you could use.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/tomatoist-sm.png' alt='Thumbnail' /&gt; &lt;a href='/images/blog/tomatoist.png'&gt;Full Version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a bit over-simplified, as the PT also involves a planning and progress worksheet, along with estimation techniques &amp;#8211; I strongly recommend you read the &lt;a href='http://www.pomodorotechnique.com/resources.html'&gt;PDF book&lt;/a&gt;. From my limited use and reading on the subject, the technique is something you can pick up fairly quickly, but to master and benefit from it, plan to spend at least a few months.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Amazon ELB - Root Domain Oversight!</title>
   <link href="http://vermonster.com/2009/11/05/amazon-elb-root-domain-oversight/"/>
   <updated>2009-11-05T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/11/05/amazon-elb-root-domain-oversight</id>
   <content type="html">&lt;p&gt;&lt;a href='http://aws.amazon.com/elasticloadbalancing/'&gt;Amazon Elastic Load Balancer&lt;/a&gt;, or ELB, is a service from Amazon&amp;#8217;s webservice group that allows you to setup a load balancer in the cloud without having to run a dedicated instance (or instances if you want failover) &amp;#8211; which saves money and maintenance (it costs under $20 per month, plus bandwidth to use ELB, the smallest instance is close to $70).&lt;/p&gt;

&lt;p&gt;So we wanted to us ELB and set it up in a staging environment, where it worked like a charm. Our staging environment had the subdomain prefix &lt;code&gt;staging&lt;/code&gt;. But when we switched to production, we ran into a bit of a snafu.&lt;/p&gt;

&lt;p&gt;From the ELB documentation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;You will still need a CNAME, or equivalent, in order to map 
the *generated* DNS name to a name that is meaningful to you 
and your customers (e.g. www.mywebsite.com).&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the DNS name for the loadbalancer ought to be used when mapping the actual domain of your application. This is likely because it is fairly straightforward to failover using a DNS name (verses an IP address). But the oversight is for root domains.&lt;/p&gt;

&lt;p&gt;Root domains require an A record to point at an IP address. So if your application is intended to run from a root doamin (i.e &lt;code&gt;http://myapp.com&lt;/code&gt;), using ELB out of the box is not straightforward. For now, we ended up making the application run on a &lt;code&gt;www&lt;/code&gt; subdomain and used a designated instance with an elastic IP to forward any the root traffic to it.&lt;/p&gt;

&lt;p&gt;There are a few other workarounds, including setting up DNS / named servers to use name-based failover or round-robin name resolution - but none seem that clean. This problem is apparently fairly known, and Amazon has &lt;a href='http://developer.amazonwebservices.com/connect/thread.jspa?threadID=32044'&gt;indicated they are working on a solution&lt;/a&gt;, hopefully soon.&lt;/p&gt;

&lt;p&gt;So I guess the moral of the story is if you want your application to run on a root domain, you may want to reconsider ELB, at least for the time being.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Vermonster.com, now with Jekyll</title>
   <link href="http://vermonster.com/2009/10/24/vermonstercom-now-with-jekyll/"/>
   <updated>2009-10-24T00:00:00-04:00</updated>
   <id>http://chrononaut.net/2009/10/24/vermonstercom-now-with-jekyll</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s been a few years, so we decided to redesign our site again. Our original site was running Wordpress, which is a fine blogging/CMS package. As we&amp;#8217;ve been simplifying our infrastructure, we decided to try Jekyll this time, a static site generator. We did this for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is super simple, static site is simple HTML - any ole&amp;#8217; web server will do&lt;/li&gt;

&lt;li&gt;The page sources are in markdown&lt;/li&gt;

&lt;li&gt;Everything from templates to post content fits nicely into git, so we have fantastic version control&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s written in Ruby&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few things did make us think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comments and contact form need 3rd party (WuFoo and Disqus respectively)&lt;/li&gt;

&lt;li&gt;Embedded comments and contact form needs JS (but we do have degraded links)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the yeas won, so we decided to go with it.&lt;/p&gt;

&lt;p&gt;We did implement a few tricks, via a nice Rakefile. First, we are using rsync to publish the site (which is common for Jekyll -driven sites).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;desc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Build then rsync the site to the public server&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:publish&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='sx'&gt;%{ rm -rf _site }&lt;/span&gt;
  &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='sx'&gt;%{ jekyll }&lt;/span&gt;
  &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='sx'&gt;%{ rsync -av --delete -e &amp;quot;ssh -i ./.ssh/dsa_key_file&amp;quot; ./_site/ user@server:/var/path/to/webroot }&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you use this code above, your key and destination will vary when rsync&amp;#8217;ing.&lt;/p&gt;

&lt;p&gt;We also have a task that uses a template to create a new post, prompting for a title and filling in the author.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;dasherize&lt;/span&gt;(&lt;span class='n'&gt;title&lt;/span&gt;)
  &lt;span class='n'&gt;title&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gsub&lt;/span&gt;(&lt;span class='sr'&gt;/\s/&lt;/span&gt;, &lt;span class='s1'&gt;&amp;#39;-&amp;#39;&lt;/span&gt;)&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gsub&lt;/span&gt;(&lt;span class='sr'&gt;/[\|\?\+\#\!\,\.\&amp;#39;\&amp;quot;\:\;\&amp;amp;]/&lt;/span&gt;,&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;desc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Create a new post using today&amp;#39;s date, filled with instructions&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;filename&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;(&lt;span class='bp'&gt;__FILE__&lt;/span&gt;) &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/_posts/&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; \
    &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;strftime&lt;/span&gt;(&lt;span class='s2'&gt;&amp;quot;%Y-%m-%d&amp;quot;&lt;/span&gt;)

  &lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;ENV&lt;/span&gt;[&lt;span class='s1'&gt;&amp;#39;TITLE&amp;#39;&lt;/span&gt;]
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;title&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;nil&lt;/span&gt;?
    &lt;span class='nb'&gt;print&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;&amp;gt;&amp;gt; What&amp;#39;s the title? (skip by set env. var TITLE) : &amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;STDIN&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;strip&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;filename&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;-&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;dasherize&lt;/span&gt;(&lt;span class='n'&gt;title&lt;/span&gt;)&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;downcase&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;.md&amp;quot;&lt;/span&gt;

  &lt;span class='n'&gt;author&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='sb'&gt;`git config --global user.name`&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;strip&lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;author&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='kp'&gt;nil&lt;/span&gt;?
    &lt;span class='nb'&gt;print&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;QUESTION: What&amp;#39;s your name? &amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;author&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;STDIN&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;strip&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;content&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;read&lt;/span&gt;(&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;(&lt;span class='bp'&gt;__FILE__&lt;/span&gt;) &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/_posts/template&amp;quot;&lt;/span&gt;)
  &lt;span class='n'&gt;content&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nb'&gt;gsub!&lt;/span&gt;(&lt;span class='sr'&gt;/.*author:.*/&lt;/span&gt;, &lt;span class='s2'&gt;&amp;quot;author: &lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;author&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;)
  &lt;span class='n'&gt;content&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nb'&gt;gsub!&lt;/span&gt;(&lt;span class='sr'&gt;/.*title:.*/&lt;/span&gt;, &lt;span class='s2'&gt;&amp;quot;title: &lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;title&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;)
  
  &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt;(&lt;span class='n'&gt;filename&lt;/span&gt;, &lt;span class='s1'&gt;&amp;#39;w&amp;#39;&lt;/span&gt;) {&lt;span class='o'&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;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;(&lt;span class='n'&gt;content&lt;/span&gt;) }
  
  &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;Made new post by &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;author&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;:&amp;quot;&lt;/span&gt;
  &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;  &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;filename&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gsub&lt;/span&gt;( &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;(&lt;span class='bp'&gt;__FILE__&lt;/span&gt;) &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;,&lt;span class='s1'&gt;&amp;#39;./&amp;#39;&lt;/span&gt;)&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
  &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;Commit changes to git. Publish with &amp;#39;rake publish&amp;#39;&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='c1'&gt;## ./_posts/template&lt;/span&gt;
&lt;span class='cp'&gt;__END__&lt;/span&gt;
&lt;span class='cp'&gt;---&lt;/span&gt;
&lt;span class='cp'&gt;layout: post&lt;/span&gt;
&lt;span class='cp'&gt;published: false&lt;/span&gt;
&lt;span class='cp'&gt;title:&lt;/span&gt;
&lt;span class='cp'&gt;#author: &lt;/span&gt;
&lt;span class='cp'&gt;#tags:&lt;/span&gt;
&lt;span class='cp'&gt;#- &amp;quot;ruby&amp;quot;&lt;/span&gt;
&lt;span class='cp'&gt;---&lt;/span&gt;
&lt;span class='cp' /&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Last, we implemented a fun changing theme, where the background images switch from day to night. We did thing with a simple &lt;code&gt;crontab&lt;/code&gt; entry on the server that switches around a supplemental CSS style sheet.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/blog/vermonster-day-sm.png' alt='Day' /&gt; &lt;img src='/images/blog/vermonster-night-sm.png' alt='Night' /&gt;&lt;/p&gt;

&lt;p&gt;All in all, we are very happy with the new site and hopeful the simplicity of Jekyll will promote more posts from our team (because we have lots to talk about!). We haven&amp;#8217;t converted all our existing blog entries over yet, but plan to do so over the next week or so.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Shopify_API 0.0.1 Released</title>
   <link href="http://vermonster.com/2009/05/29/shopify_api-001-released/"/>
   <updated>2009-05-29T00:00:00-04:00</updated>
   <id>http://chrononaut.net/2009/05/29/shopify_api-001-released</id>
   <content type="html">&lt;p&gt;You can see &lt;a href='http://github.com/steve9001/shopify_api/tree'&gt;Shopify_API&lt;/a&gt; for a small library for driving the &lt;a href='http://www.shopify.com'&gt;Shopify.com&lt;/a&gt; &lt;abbr title='Application Programming Interface'&gt;API&lt;/abbr&gt;. It is adapted from the official Shopify Rails plugin, but decoupled from the controller for use outside of web requests. It depends on ActiveResource, enjoy!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>svn:mergeinfo - Addressing a Painfully Missing Subversion Feature</title>
   <link href="http://vermonster.com/2009/02/12/svnmergeinfo---addressing-a-painfully-missing-subversion-feature/"/>
   <updated>2009-02-12T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/02/12/svnmergeinfo---addressing-a-painfully-missing-subversion-feature</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ll preface this by saying article is about subversion and not git. Since release 1.5, subversion now includes a property, svn:mergeinfo, that is auto-applied when preforming merges. Before this, a merge was pretty much an ad-hoc diff between two files or lines of code. The best practice was to include the merge command used in the SVN comment, which was extremely unreliable. For clients and projects not yet on the git-train, svn:mergeinfo is a welcome and painfully overlooked feature.&lt;/p&gt;

&lt;p&gt;We, like many other teams, typically follow the TRUNK = &amp;#8220;bleeding edge&amp;#8221;, branch-releases pattern to SCM. So at the end of each iteration, we cut a release branch from TRUNK. This release is deployed and we turn our efforts toward the next sprint. However, is is atypical to not have to patch the release. This is usually done in the release branch, tested on a staging environment, the ultimately deployed to production. Afterward, the patch is merged back to the mainline development trunk. This pattern works nice, but sometimes we do a series of patches in the release and there is definitely the opportunity to miss a commit when merging. Since subversion previously didn’t have a way to see merges (merges were not directly tracked), the process involved a session of reviewing commit logs and manual comparison. Enter git, which is built to merge, and the mass movement to git is inevitable.&lt;/p&gt;

&lt;p&gt;However, with subversion 1.5, a new property is introduced svn:merginfo. This feature add merge tracking to svn. So when committing the results of a merge, this piece of metadata is recorded. This opens up many new features, like looking at the svn:merginfo property (you shouldn’t edit this property, only get it).&lt;br /&gt;And one of my favorite features is the &lt;code&gt;--reintegrate&lt;/code&gt; option. So we can now tell, with a single command, what merges in the release haven’t made their way back to trunk — no more missing merges!&lt;/p&gt;

&lt;p&gt;There are a few points, &lt;a href='http://www.collab.net/community/subversion/articles/merge-info.html'&gt;echoed here (parting thoughts section at bottom)&lt;/a&gt;, worth mentioning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The subversion server and all developer clients ought to be at least running svn 1.5+&lt;/li&gt;

&lt;li&gt;Do all the merges from a standard location, like the project root (RAILS_ROOT for RoR)&lt;/li&gt;

&lt;li&gt;Inform developers of this property. After doing a merge, the svn:mergeinfo is put on the place the merge was preformed (preferably project root). So developers should know this and make sure to commit this property change.&lt;/li&gt;
&lt;/ol&gt;</content>
 </entry>
 
 <entry>
   <title>Minimizing Software Entropy in the Agile Environment</title>
   <link href="http://vermonster.com/2009/02/06/minimizing-software-entropy-in-the-agile-environment/"/>
   <updated>2009-02-06T00:00:00-05:00</updated>
   <id>http://chrononaut.net/2009/02/06/minimizing-software-entropy-in-the-agile-environment</id>
   <content type="html">&lt;p&gt;As part of the agile process, each development sprint has a planning prerequisite. During this planning process, user stories are scored using a consensus complexity and risk estimations. It is common that some stories are deemed “to risky” and either scaled-back, re-evaluated or hit the chopping block. Minimizing risk and defects is something desirable to all - management, developers and stakeholders. This mix of risk and defects is sometimes referred to as “software entropy”. From my thermodynamics class, I vaguely remember that entropy has something to do randomness, or was it heat - or is that enthalpy?&lt;/p&gt;

&lt;p&gt;After a quick google + wiki session, I found that entropy is the amount of disorder in a system. And there is a principal that says in a closed system, one can’t decrease the amount of entropy, it either increases or could possible stay the same. So that doesn’t look good if we apply this to software. This basically says that each iteration the very best we can do is have the same unpredictability, but most likely our software will continuously get worse! Not good news for the software industry and not good news for agile practitioners.&lt;/p&gt;

&lt;p&gt;However, we know software doesn’t &lt;em&gt;always&lt;/em&gt; become more unpredictable, software &lt;em&gt;can&lt;/em&gt; become more stable. So what’s the factor and how can being agile, which embraces change and uncertainty, be used to minimize software entropy?&lt;/p&gt;

&lt;p&gt;The factor is actually &lt;em&gt;refactor&lt;/em&gt;, as in software refactoring. So we follow the laws of thermodynamics in this house, our system is not a closed one (it all depends on how you draw your boundaries). Whenever we add or removed lines of code, we are doing so as an external influence. This can actually reduce software entropy. For instance, if we have a defect rate of say 3 defects per 1000 lines of code, and we remove 500 lines of code in an iteration, we’d have 1.5 less defects, right? Well that was pretty theoretical, but the concept does work in a very tangible, and common occurrence - bug fixing.&lt;/p&gt;

&lt;p&gt;We consider any bug fix that turns out to be a software defect (i.e. one that is &lt;em&gt;not&lt;/em&gt; misimplementation of some business requirement or feature) a refactoring effort. When a defect is addressed, the existing code is altered as we add or remove bits - and we are external influence. Fixing defects can have 3 possible outcomes: 1) the system is more stable, software entropy reduced (ah!, the fix works!), 2) the system is not any more or less stable, software entropy unchanged (the fix didn’t work, but at least you didn’t break anything), or 3) the system is less stable, software entropy increases (regression! whack a mole! uh-oh!). So if we are good bug fixers, we can reduce entropy.&lt;/p&gt;

&lt;p&gt;Now for the agile part. As we work through our iterations, defects land on our plate. And properly fixing them does reduce entropy. But another way to more drastically reduce entropy is some good ole’, heads-down refactoring effort. Pure refactoring specifically targets minimization of software entropy. When we refactor, we are DRYing up methods, eliminating lines of code, cleaning and making our software more stable and manageable. We strongly recommend that each iteration ought to have some overhead earmarked for refactoring.&lt;/p&gt;

&lt;p&gt;It is sometimes difficult to justify refactoring to stakeholders and non-developers, as the business value is difficult to measure. However, if a new feature is deemed “too risky”, a trade-off could be to add a pure refactoring effort to the iteration targeting the potential risk of the feature. Then build the feature.&lt;/p&gt;

&lt;p&gt;So the moral is to minimize entropy and uncertainity in software, try to have refactoring a part of each development iteration.&lt;/p&gt;</content>
 </entry>
 
 
</feed>
