<?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-03-11T17:30:06-05:00</updated>
 <id>http://vermonster.com/</id>
 <author>
   <name>Brian, Jay and Steve</name>
 </author>
 
 
 <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.google.com/url?sa=D&amp;amp;q=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>
