<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>stevengharms.com &#187; Ruby</title>
	<atom:link href="http://stevengharms.com/category/ruby/feed" rel="self" type="application/rss+xml" />
	<link>http://stevengharms.com</link>
	<description>My Blog</description>
	<lastBuildDate>Sat, 21 Apr 2012 19:06:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>A Season of New Beginnings:  Joining Carbon Five</title>
		<link>http://stevengharms.com/a-season-of-new-beginnings-joining-carbon-five</link>
		<comments>http://stevengharms.com/a-season-of-new-beginnings-joining-carbon-five#comments</comments>
		<pubDate>Wed, 12 Oct 2011 17:39:01 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruminations]]></category>
		<category><![CDATA[San Francisco]]></category>
		<category><![CDATA[Technology and Computers]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=2342</guid>
		<description><![CDATA[Probably the most significant constant in the entire history of this blog has been where I have spent several hours of my day each work-day. For a great many years, I have been an employee of Cisco Inc. As of the 19th of this month, that will end. I will commence employment at Carbon Five, [...]]]></description>
			<content:encoded><![CDATA[<p>Probably the most significant constant in the entire history of this blog has
been where I have spent several hours of my day each work-day.  For a great
many years, I have been an employee of <a href="http://cisco.com">Cisco Inc</a>.  As of
the 19<sup>th</sup> of this month, that will end.</p>

<div style="background-color:black; margin: 0px 20px; padding 5px 10px">
<div style="text-align:center">
<a href="http://stevengharms.com/wp-content/uploads/2011/10/carbonfive.png"><img src="http://stevengharms.com/wp-content/uploads/2011/10/carbonfive.png" alt="" title="Carbon Five Logo" width="237" height="110" class="aligncenter size-full wp-image-2344" /></a>
</div>
</div>

<p><br/></p>

<p>I will commence employment at <a href="http://carbonfive.com">Carbon Five</a>, a
consulting and application development firm in San Francisco, on the 24th of
this month.  I am elated about joining Carbon Five&#8217;s team of energetic and
innnovative developers.  I will be doing Ruby and Rails development and I hope
to learn more about mobile development, async server technologies, and sexy
Javascript front-ends.</p>

<p>Since last Winter Carbon Five has hosted a fortnightly &#8220;hack night.&#8221;  Through
the winter and spring they saw me struggle and batter my way through the
rewrite of my LatinVerb library and my metaprogramming presentation.
Ultimately this co-working session facilitated a relationship which is about
to turn into a working relationship.  Here are the things I like about them:</p>

<ol>
<li>Team

<ol>
<li>Management:  Friendly but clearly with a sense of standards and high
expectations but with great trust in the developers to do what&#8217;s right,
well</li>
<li>Staff:  Excited, energetic, motivated, funny on Twitter</li>
<li>Size:  Forty-ish or souls with whom I can have actual relationships</li>
</ol></li>
<li>Culture

<ol>
<li>Standardized hours (exceptions allowed)</li>
<li>Fancy coffee machine that scares me</li>
<li>Developer-sensitive culture:  don&#8217;t burn out, do good work on good
equipment in a nice place</li>
</ol></li>
<li>Agile Methodologies:  Paired programming (flexibly), User Stories</li>
<li>Client Engatement:  I&#8217;ve never worked whith a money-paying customer, I
think that&#8217;s an experience to have!</li>
<li>Technology:  The team there is trying out new ideas and tools all the
time. </li>
<li>Proximity:  They&#8217;re a 3 block walk from my home.  Granted, two of those
are SoMa wide north-east/south-west blocks, but it beats the heck out of
driving or taking the train anywhere.  They&#8217;re also surrounded by several gyms so I can get some fitness work in.</li>
<li>Type of Work

<ol>
<li>Application development (including &#8220;heavy lifting&#8221; of the back end)</li>
<li>Startup / Idea bootstrapping</li>
<li>Design</li>
</ol></li>
</ol>

<p>When the door opened, I felt that the time was right for me to make a change.</p>

<p>I will miss my friends and contacts from Cisco terribly.  The people at Cisco
and my experiences there defined many of my friends and many years of great
memories.  Nevertheless I am so excited about my future with Carbon Five.  I
find so much peace in Ovid these days that I&#8217;ll repeat the quote I gave in my
&#8220;sign off&#8221; email:</p>

<blockquote>
  <p>&#8220;As pliable wax, stamped with new designs, it is no longer what it was; does
  not keep the same form; but is still one and the same;&#8221;</p>
</blockquote>

<p><em>Quoque mutabo</em></p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/a-season-of-new-beginnings-joining-carbon-five/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Practical Metaprogramming&#8221; presentation from RubyConf XI</title>
		<link>http://stevengharms.com/practical-metaprogramming-presentation-from-rubyconf-xi</link>
		<comments>http://stevengharms.com/practical-metaprogramming-presentation-from-rubyconf-xi#comments</comments>
		<pubDate>Sat, 01 Oct 2011 17:19:14 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology and Computers]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=2335</guid>
		<description><![CDATA[On the 30th of September I presented at Rubyconf XI in New Orleans, LA. My topic was &#8220;Practical Metaprogramming.&#8221; This presentation was very special for me. Having spent some of my childhood in New Orleans, speaking there was very special. Further, one year ago, inspried by Chad Fowler&#8217;s book The Passionate Programmer, I resolved that [...]]]></description>
			<content:encoded><![CDATA[<p>On the 30<sup>th</sup> of September I presented at Rubyconf XI in New Orleans, LA.  My topic was &#8220;Practical Metaprogramming.&#8221;</p>

<p>This presentation was very special for me.  Having spent some of my childhood in New Orleans, speaking there was very special.  Further, one year ago, inspried by Chad Fowler&#8217;s book <em>The Passionate Programmer</em>, I resolved that &#8220;One year from now, I <em>will</em> speak at Rubyconf.&#8221;  I am filled with joy to say that I attained my dream.</p>

<p>I spoke on one of the more complicated aspects of the Ruby programming language:  Metaprogramming.  Ruby&#8217;s constructs allow you to fundamentally and flexibly re-direct calls at runtime and change the object model.  While it is generally believed that this is complicated or a weird bolt-on to Ruby, I contend that <em>all</em> programming in Ruby is metaprogramming &mdash; from the get-go!  I also present a path for learners so that they can level-up.  Lastly I show some examples of heavily, and justifiably heavily used, metaprogramming code courtesy of my library <strong>LatinVerb</strong>.</p>

<p>Here are resources for those in attendance or for those who could not make it.</p>

<ul>
<li><a href="http://stevengharms.com/MP_talk.pdf">The slides to my presentation</a></li>
<li><a href="http://spkr8.com/t/8534">My SpeakerRate.com page</a></li>
<li><a href="http://pragprog.com/book/cfcar2/the-passionate-programmer">The Passionate Programmer</a></li>
<li><a href="https://github.com/sgharms/LatinVerb">LatinVerb GitHub Home</a></li>
</ul>

<p>Or, here are the slides in-line:</p>

<p>Please, if you were inspired by this talk, please leave a comment. If you would like to provide criticism of the talk, please visit the speaker8 page.</p>

<script src="http://speakerdeck.com/embed/4e8766b26ea0ae00530077e0.js?size=preview"></script>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/practical-metaprogramming-presentation-from-rubyconf-xi/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Presentation from Lone Star Ruby Conf V</title>
		<link>http://stevengharms.com/presentation-from-lone-star-ruby-conf-v</link>
		<comments>http://stevengharms.com/presentation-from-lone-star-ruby-conf-v#comments</comments>
		<pubDate>Sun, 14 Aug 2011 18:08:03 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Latin]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=2329</guid>
		<description><![CDATA[On the 12th of this month I presented at Lone Star Ruby Conf V I have been working on a project for the last few years that conjugates regular Latin verbs into specific, as well as aggregated, results (Code). While coding this library, I had some ideas about the tools and techniques that made it [...]]]></description>
			<content:encoded><![CDATA[<p>On the 12<sup>th</sup> of this month I presented at Lone Star Ruby Conf V</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/08/lsrc-speaker-badge.png"><img src="http://stevengharms.com/wp-content/uploads/2011/08/lsrc-speaker-badge.png" alt="" title="lsrc-speaker-badge" width="300" height="100" class="aligncenter size-full wp-image-2330" style="text-align:center"/></a></p>

<p>I have been working on a project for the last few years that conjugates regular Latin verbs into specific, as well as aggregated, results (<a href="https://github.com/sgharms/LatinVerb">Code</a>).  While coding this library, I had some ideas about the tools and techniques that made it possible for me to handle the complexity of this issue.  From these ideas I derived some guidelines about how to decide &#8220;when to metaprogram and how.&#8221;  I presented this.</p>

<p>Here are the slides <a href='http://stevengharms.com/wp-content/uploads/2011/08/MP_talk.pdf'>slides</a> from the presentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/presentation-from-lone-star-ruby-conf-v/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fear and Expectations and the Ruby Job Market</title>
		<link>http://stevengharms.com/fear-and-expectations-and-the-ruby-job-market</link>
		<comments>http://stevengharms.com/fear-and-expectations-and-the-ruby-job-market#comments</comments>
		<pubDate>Wed, 15 Jun 2011 03:11:58 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruminations]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=2305</guid>
		<description><![CDATA[When involved in the Ruby frequently one hears things about how great the job market for Ruby programmers is. It is great &#8212; especially when compared with the stagnation in other markets, regions, and disciplines. Recruiters bombard the Meetup groups, attend the meetups, show up at hackathons, and contact you via LinkedIn. It&#8217;s nice. Matsumoto-san [...]]]></description>
			<content:encoded><![CDATA[<p>When involved in the Ruby frequently one hears things about how great the job market for Ruby programmers is.  It is great &mdash; especially when compared with the stagnation in other markets, regions, and disciplines.  Recruiters bombard the Meetup groups, attend the meetups, show up at hackathons, and contact you via LinkedIn.  It&#8217;s nice.</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/06/yukihiro-matz-matsumoto-invented-created-ruby-language-pic.jpg"><img src="http://stevengharms.com/wp-content/uploads/2011/06/yukihiro-matz-matsumoto-invented-created-ruby-language-pic-300x181.jpg" alt="" title="yukihiro-matz-matsumoto-invented-created-ruby-language-pic" width="300" height="181" class="aligncenter size-medium wp-image-2309" /></a></p>

<p><em>Matsumoto-san created Ruby, and present with a slide reading &#8220;Great Pleasure&#8221; &mdash; happy runs deep</em></p>

<p>Given the numbers of Ruby jobs, or, &#8220;opportunities,&#8221; I frequently see other Rubyists touting happiness in the job as the <em>ne plus ultra</em> of work motivation.  The commentary is frequently of the form:  &#8220;Leave your <em>present</em> situation for a Ruby situation because there is a great <em>quantity</em> of opportunity for Ruby jobs and, let&#8217;s face it, if you were to write Ruby all day how could you <em>not</em> be happy?&#8221;  The happiness-as-virtue-in-extremis is further encouraged since one of the community&#8217;s most visible luminaries wrote a <a href="http://pragprog.com/titles/cfcar2/the-passionate-programmer">wonderful book that described how to have &#8220;a remarkable career in software development</a>&#8221; and encourages developers to think long and hard about the happiness and peace generated (or not) by their current position.</p>

<p>In sum, Rubyists think it&#8217;s pretty darn important to be happy at your work.  I&#8217;m proud to be part of a community that has &#8220;taken the red pill&#8221; but some of the commentary promulgated can, betimes, seem a bit insensitive if not na&iuml;ve.  Let me say first, <code>nzkoz</code> is <em>not</em> insensitive or callous, but it&#8217;s the example that got my gears turning on this topic.</p>

<p>&#8220;If you&#8217;re a developer doing a job you hate, you are useless or <em>totally</em> doing it wrong.  So many people hiring right now&#8230;&#8221;</p>

<p><a href="http://twitter.com/#!/nzkoz/status/80412529871958016">Source</a> @nzkoz</p>

<p>There are many good reasons to <em>not</em> leave something you hate (i.e. that which earns you your daily bread) besides being useless or &#8220;doing it wrong.&#8221;  Furthermore this tweet may just oversimplify between the extremes of &#8220;like&#8221; and &#8220;hate.&#8221;  Make no doubt, I understand the spirit (yes, it was funny!) of the tweet and the 140-character limitation.</p>

<p>I think it would be a a worthy feature-add to this discussion for the brave Rubyists who have followed their bliss to tell the story of the form:</p>

<blockquote>
Yes, I left my job at BigCo as a senior developer after 15 years.  It was the scariest thing I had done to leave that comfort and to joing RubyRazzle.com, not least of which because my autistic son Jeb requires private education and my eldest daughter, Jenny, required orthodontics after a freak crocodile wrestling accident.  While RubyRazzle seemed likely to succeed, there were no guarantees.  Heck, while some people were thinking about &#8220;Will I use Redis&#8221; I was thinking &#8220;How much extra is it to get my wife Suzy medical coverage deriving from that skiing accident she had years ago.  Obviously, RubyRazzle didn&#8217;t have the cash inflow that BigCo had.  Less salary, less generous benefits, risk&#8230;.but on the other hand I couldn&#8217;t see that same faded pine-colored carpet again where my chair had worn grooves in without thinking that I had somehow thrown important years of my life away.  So on June 12th, I walked out the door of BigCo to a job that gave me a small house worth of options, and a salary 15K smaller&#8230;
</blockquote>

<p>I believe <em>this</em> is the mental conversation that keeps our fellow Rubyists locked in positions they don&#8217;t leave.  It&#8217;s easy for <a href="http://www.paulgraham.com/ramenprofitable.html">Paul Graham</a> to grab college grads and stuff them into a loft with a half-dozen MacBooks and <a href="http://www.huffingtonpost.com/2011/06/09/y-combinator-harvard-silicon-valley_n_874245.html">create a startup</a>: there&#8217;s no lifestyle to lose.  But as a recent thread on <a href="http://news.ycombinator.com">Hacker News</a> shows, <a href="http://www.google.com/url?sa=t&amp;source=web&amp;cd=2&amp;ved=0CB8QFjAB&amp;url=http%3A%2F%2Fapps.ycombinator.com%2Fitem%3Fid%3D2649749&amp;ei=rSL4TbOmLsjXiAKEjOX9DA&amp;usg=AFQjCNEWQG1f1z7nkNUkKM0ENMeAI0VQnw">better developers</a> are out of the Ramen-and-IPA phase of life and need to see how they, too, can follow their happy without feeling unduly irresponsible to their spouse and/or children.</p>

<p>If we in the Ruby community are committed to this as a standard, we need to talk about how to make things work for all those in the tent.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/fear-and-expectations-and-the-ruby-job-market/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>I Won the Podio API Release Hackathon Competition</title>
		<link>http://stevengharms.com/i-won-the-podio-api-release-competition</link>
		<comments>http://stevengharms.com/i-won-the-podio-api-release-competition#comments</comments>
		<pubDate>Sun, 22 May 2011 18:51:24 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[San Francisco]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology and Computers]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=2248</guid>
		<description><![CDATA[Introduction On May 14th, I competed at a Hackfest hosted by Podio. Podio is a customizable social networking application delivered as a service (aaS). After 8 hours of coding, I placed first in the competition and won a beautiful Apple Cinema Display. In this post I will cover my hack, how it was done, and [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>

<p>On May 14<sup>th</sup>, I competed at a Hackfest hosted by <a href="http://podio.com">Podio</a>.
Podio is a customizable social networking application delivered as a service
(aaS).  After 8 hours of coding, I placed first in the competition and won a
beautiful Apple Cinema Display.  In this post I will cover my hack, how it was
done, and lessons learned.</p>

<p><a href="http://www.flickr.com/photos/podio/5724215201/" title="Steven G.
Harms with his first prize by Team Podio, on Flickr"><img
class="aligncenter size-full"
src="http://farm4.static.flickr.com/3124/5724215201_34a6023095.jpg"
width="500" height="333" alt="Steven G. Harms with his first prize"></a></p>

<p><em>Victori pretium it</em></p>

<p><em><a href="http://blog.podio.com/2011/05/25/interview-with-steven-g-harms-winner-of-the-podio-api-release-hackathon/">Or, you can watch my video interview</a></em></p>

<p><span id="more-2248"></span></p>

<h2>Background</h2>

<p>Let me first introduce the various companies involved and technologies
provided or implemented in the solution.  I think of these as the ingredients
in the recipe that allowed me to code my offering.</p>

<h3>Podio</h3>

<p>In case you haven&#8217;t noticed, people are spending phenomenally large amounts of
time on social networks.  These applications have their own vocabulary of
interactions and provide certain defined workflows that, thanks to their
popularity, are teaching the population certain workflows for successful
collaboration.  As younger employees enter the workforce, their models of
collaboration will be informed by these social networks whose existence and
interaction vocabulary are presumed to be ubiquitous.  Accordingly, it would
be wise for businesses to adjust <em>their</em> workflows to look something like
these social sites.</p>

<p>The traditional solution to this has been to acquire servers, place them in a
data center, and build your own social networking clone which, invariably,
would be perceived as a dismal dog in comparison to the glittery product like
Facebook, Linked In, et al. distilled in the market crucible.  In short,
building a social platform is probably not your core competency.</p>

<p>Enter Podio who offers a software solution that behaves &#8220;like Facebook&#8221; and
which can be used <em>as a service</em>.</p>

<p>Traditionally, when using  an aaS solution, one loses the ability to create
highly specfic applications (&#8220;Podio&#8217;s not going to build an app to show what&#8217;s
in our cafeteria today&#8221;).  Or one might expect that to get a specific app one
would have to pay Podio a handsome consulting engagement fee.  Podio has seen
a way around these drawbacks of using an aaS service by providing an
<strong>in-application, friendly, web-based, drag-and-drop application builder</strong>.
This is the first key element in my solution.</p>

<p>While a well-conceived application builder is great, certain behaviors are
unique to certain businesses (e.g. &#8220;SMS the sales manager if no one takes
ownership of the customer complaint within 24 hours.&#8221;) and don&#8217;t have an
obvious integration point in a web interface.  To remedy this concern, Podio
provides <strong>a rich API (Application Program Interface) that&#8217;s a pleasure to
use</strong>.  It allows 3<sup>rd</sup> parties to extend and share functionality
between the Podio core and their own custom applications.  It was the public
release of this API on Saturday that occasioned the Hackfest.  It was also
the second key element in my solution.</p>

<p>On the topic of the API, let me add that
many technical entities develop an API as an afterthought and the reliability
and consideration (or lack thereof) shows.  Podio bravely (!) decided to
re-implement their web interface as a client of their own API.  This is a
brave move, but by testing whether they themselves could work with the API
they were providing, they wound up creating a better, more-intuitive app.</p>

<p><a href="http://www.flickr.com/photos/podio/5553727063/" title="Work 2.0
Hackday at The Podio Store by Team Podio, on Flickr"><img
src="http://farm6.static.flickr.com/5225/5553727063_3ea610da89.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Work 2.0 Hackday at The Podio Store"></a></p>

<p>Incidentally Podio is not purely a virtual experience, they have the Podio
Store in San Francisco&#8217;s SoMa districit where you can go and talk to their
staff about what you could do with Podio.  They&#8217;ve made the &#8220;app store&#8221;
software conceit physical.  It&#8217;s revolutionarily transgressive in a good way <img src='http://stevengharms.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Twilio</h3>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/twilio-logo.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/twilio-logo-300x100.png" alt="" title="twilio-logo" width="300" height="100" class="aligncenter size-medium wp-image-2255" /></a></p>

<p><a href="http://www.twilio.com/">Twilio</a> is a service vendor who provides an
exceedingly simple-to-use API for interacting with phones:  setting up
phone menus (&#8220;Press 1 for &#8230;, Press 2 for&#8230;&#8221;), making phone
calls, bridging calls, setting up conference calls, setting up answer
menus, etc. is a breeze.  If you need to do something that touches a phone,
Twilio&#8217;s rich, well-documented API will make it easy.</p>

<p>I had gotten a Twilio developer key and $30.00 of free minutes that I hadn&#8217;t
touched since it was given to me at the Social Apps workshop held at Heroku in
January 2010 (<em>ulp</em>).  <strong>Twilio&#8217;s API was the third component</strong> in my solution.</p>

<h3>Heroku</h3>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/heroku-logo-light-300x100.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/heroku-logo-light-300x100.png" alt="" title="heroku-logo-light-300x100" width="300" height="100" class="aligncenter size-full wp-image-2251" /></a></p>

<p><a href="http://heroku.com">Heroku</a> makes it incredibly easy to stand up and host web
applications.  I have only ever used it to deploy Rails and Sinatra
applications.  Heroku makes a very complex process managable, but it is not
without some complexity.  <strong>Heroku&#8217;s service was the fourth and final vended
technology involved in my solution</strong>.</p>

<h3>Previous Experience</h3>

<p>It is fair to say that I probably spent the most of my time on the
hack day trying to figure out the right way to develop with Heroku.  However,
if you read through this post and reference the <a href="http://devcenter.heroku.com/articles/quickstart">implementation process</a>, while not
completely <em>effortless</em>, you will capture the value proposition posed by
Heroku&#8217;s use.</p>

<p>Previously I had used Heroku to host my <a href="http://verbalatina.heroku.com">Verba Latina in Viis Ferrorum (Latin
on Rails)</a> application that I used in a failed
bid to get into grad school (<em>Cue violins and tears</em>).  As such I was familiar
with their streamlined, <a href="http://git-scm.com/">git</a>-based deployment design as
well as with the concept that you must configure your app to have a
configuration manifest so that Heroku builds the application the right way.</p>

<p>Last January <a href="http://blog.heroku.com/archives/2010/8/20/social_app_workshop_videos/">Heroku and Twilio hosted an
introduction</a>
to using Twilio and Heroku to create social, phone-based applications.  Here a
pattern emerged whose introduction was very important to my Podio solution:</p>

<ol>
<li>Acquire a Heroku instance</li>
<li>Run a web framework (the lighter the better, for debugging purposes)</li>
<li>Use your instance to bridge communications between API&#8217;s</li>
<li>Violà, mashup</li>
</ol>

<p>However at the Social Apps workshop, I didn&#8217;t really do this, instead I
learned about some other Ruby tools described below.  While the pattern would
have been good to have had some experience with, the following tools were
also essential to my success at Podio, so it was good that I spent time
learning a bit about them.</p>

<h3>Ruby Tooling</h3>

<h4>Sinatra</h4>

<p>Sinatra is a very light language for describing a web server.  You say:  hey,
when someone points to you with <code>/</code> at the end, send back some text generated
by executing some code.  It&#8217;s incredibly simple, incredibly clear and I had
done a &#8220;hello Heroku&#8221; on it as part of the Social Apps get-together.</p>

<h4>Ruby</h4>

<p>Sinatra is written in Ruby, so, I&#8217;m glad I know Ruby.</p>

<h4>RVM</h4>

<p><a href="http://rvm.beginrescueend.com/">RVM</a> is a way to have multiple Ruby
interpreters installed on a machine at the same time such that their various
libraries and dependencies don&#8217;t interfere with one another.  It also has a
wonderful tool called &#8220;gemsets&#8221; which allow you to store all your Ruby gems
(libraries for specific tasks) in a single sandbox so that you know what you
have when it comes time to deploy.</p>

<h4>git</h4>

<p><a href="http://git-scm.org">Git</a> is for revision control.  More than once I screwed
up a file and needed to get back to a working state quickly, specifically
because the competition was timed.  The ability to not have to do dozens of
&#8216;undo&#8217; operations was critical.</p>

<h4>vim</h4>

<p>A fast editor for editing text.  &#8216;Nuff said.</p>

<h2>Ingredient List</h2>

<p>Having shown the background above, I had the following ingredients when I
showed up:</p>

<ol>
<li>Podio:

<ol>
<li>In-application, web-based, drag-and-drop application builder</li>
<li>API</li>
</ol></li>
<li>Twilio

<ol>
<li>API</li>
<li>Free developer minutes from Social Apps workshop</li>
</ol></li>
<li>Heroku</li>
<li>Sinatra</li>
<li>Other development tools</li>
</ol>

<p>As of Saturday morning, I would rate my proficiency with Podio, Twilio, and
Heroku, and Sinatra as being very low.  It is a tribute to the designers of
these systems that I was able to stitch them all together in just a few hours.</p>

<h2>The Hack</h2>

<h3>Kick-Off</h3>

<p>First things first I arrived at Podio&#8217;s <a href="https://store.podio.com/">beautiful
storefront</a> on 6<sup>th</sup> street, SoMa, SF, CA,
but 2 blocks from my house, at 8am and was treated to some great brain-food
for breakfast.  The interior is beautuful with Scandinavian sensibility and
with several ukelele&#8217;s decorating the wall.  The loft-style space is modern
and tasteful and a great place to visit.</p>

<p><a href="http://www.flickr.com/photos/podio/5553731133/" title="IMG_5782 by
Team Podio, on Flickr"><img
src="http://farm6.static.flickr.com/5141/5553731133_32029ddb43.jpg"
class="aligncenter size-full"
width="500" height="333" alt="IMG_5782"></a></p>

<p><em>The ukelele wall</em></p>

<p>The morning started off with <a href="http://blog.podio.com/author/phil/">Phil
Chambers</a> (CTO,
<a href="http://twitter.com/#!/filchambers">@filchambers</a>) and
Christian Holm (Developer, <a href="http://twitter.com/#!/hlmrn">@hlmrn</a>) showing off
what the Podio drag and drop tool and API is capable of.</p>

<p><a href="http://www.flickr.com/photos/podio/5724806926/" title="Christian Holm
by Team Podio, on Flickr"><img
src="http://farm6.static.flickr.com/5268/5724806926_8cb74ce8b8.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Christian Holm"></a></p>

<p><em>Christian demonstrates</em></p>

<p>Now here&#8217;s a bit of a sheepish confession I have to make:  <em>I hadn&#8217;t really
even considered there was a competition</em>.  I thought it was going to be a meet
and greet, code some, and get some tasty food and / or beverages&#8230;but then
Phil mentioned that there were prizes for the best use of the API!  To sweeten
the deal with the spectre of avarice, Podio had brought in some great prizes:
Dr.  Dre headphones, an iPad2, and a beautiful Apple Cinema Display.  I
figured going home with headphones wouldn&#8217;t be bad for a day&#8217;s work.  I
half-flirted with maybe even getting the iPad but didn&#8217;t put much store by it.
Besides, I had work to do.</p>

<h3>Ideation</h3>

<p>After the &#8220;Go!&#8221; bell was rung, I thought about something that had been on my
mind.  They day before I&#8217;d had a frustrating visit with my HOA.  I found
myself wishing that there were some way for us to keep better track of our
&#8220;shared&#8221; maintenance tickets (handled via email).  The first thing I did was use
Podio&#8217;s drag-and-drop application builder to build a basic ticket tracker.
While most tickets are private and bonded to a single resident, there should
be &#8220;shared / public&#8221; tickets for shared issues:  water stains in a hallway,
Insanity Wolf in the garage, etc.</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/insanity_wolf.jpg"><img src="http://stevengharms.com/wp-content/uploads/2011/05/insanity_wolf-300x300.jpg" alt="" title="insanity_wolf" width="300" height="300" class="aligncenter size-medium wp-image-2254" /></a></p>

<p><em>A fearsome menace!  Insanity wolf does not read your Tumblr blog</em></p>

<p>I called this app &#8220;Is It Done Yet?&#8221; &mdash; a common-enough thought among most
urban flat-dwellers when considering the state of their work orders with their
property management companies.</p>

<p>By using the Podio app builder &#8230;</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/app_builder.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/app_builder-300x262.png" alt="" title="app_builder" width="300" height="262" class="aligncenter size-medium wp-image-2250" /></a></p>

<p><em>Click for larger view</em></p>

<p>I was able to create &#8220;IIDY?&#8221; tickets&#8230;</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/IIDY_ticket.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/IIDY_ticket-271x300.png" alt="" title="IIDY_ticket" width="271" height="300" class="aligncenter size-medium wp-image-2253" /></a></p>

<p><em>Click for larger view</em></p>

<p>This took me all of about 15 minutes to put together.  It was about this time
that Jon Froda, one of the founders, came by to talk to me about how things
were going.  I explained the work-order tracking idea and he suggested that
maybe I could add an alerting system for &#8220;Emergency&#8221; requests and that I could
have that page out.  Having been a sysadmin, I knew about pager notifications
and while I thought it might be a bit too simple to be a real competitor, I
knew that it was implementable in a few hours&#8230;provided I use Heroku and
Twilio.  I was a bit daunted since I was not too familiar with these peer
components and I certainly had no experience in tying them to the Podio API.</p>

<p><em>&#8230;But</em> Jon&#8217;s idea seemed audacious to win a prize but was slim enough to do
in a few hours.  I went with it.</p>

<p>I thought the idea over and sketched up a basic schematic for the design with
the help of Christian.  I worked from right to left.</p>

<pre>
Podio                    Heroku-hosted Custom App               Twilio
 Web Hook On Create -->    Receives event                  |-->API sends SMS
                           Evaluates emergency Status      |
                           If emergency, paged via Twilio -|
</pre>

<h3>Set Up the Development Space</h3>

<pre><code>$ mkdir podio
$ cd podio
$ git init
$ echo '\*.sw\*' &gt;&gt; .gitignore
$ touch Gemfile Gemfile.lock
$ echo 'rvm use ruby-1.9.2-p180@podio' &gt;&gt; .rvmrc
$ cd ~
$ rvm use ruby-1.9.2-p180
$ rvm gemset create podio
$ cd - 

info: Using ruby 1.9.2 p180 with gemset podio
$
</code></pre>

<p>As I mentioned earlier, knowing some core Ruby / Unix tools made getting
started and working efficiently an edge for a team of one.  These command set
creates a directory, a primitive git ignore file, and creates a Gemfile that
will be used for defining the apps&#8217; gem dependenices via
<a href="http://gembundler.com/v1.0/index.html">bundler</a> as required by Heroku.  It
also specifies an RVM gemset which will sandbox all the dependencies.</p>

<h3>Send an SMS via Twilio from the CLI</h3>

<p>Twilio provides an Ruby wrapper for dealing with their API. The first thing I
did was get the <code>twiliolib</code> gem.  I then found the <a href="http://www.twilio.com/docs/howto/sms-notifications-and-alerts">Twilio SMS
example</a> that,
although written in PHP, was sufficient to give me a place to start.</p>

<p>I implemented this code like so:</p>

<pre><code>#!/usr/bin/env ruby

require 'twiliolib' 
require 'pp'

# Twilio REST API version 
API_VERSION = '2010-04-01'

# Twilio AccountSid and AuthToken 
ACCOUNT_SID = 'MY-SID' 
ACCOUNT_TOKEN = 'MY-AUTH-TOKEN'

# Outgoing Caller ID previously validated with Twilio 
CALLER_ID = 'MY-VALIDATED CALLER ID';

# Create a Twilio REST account object using your Twilio account ID and token
account = Twilio::RestAccount.new(ACCOUNT_SID, ACCOUNT_TOKEN)

d = { 'From' =&gt; CALLER_ID, 'To' =&gt; 'MY-CELL-PHONE', 'Body' =&gt; ARGV.empty? ?
'An EMERGENCY severity task has been opened!  Please check PODIO task list.'
: ARGV[0] }

resp =
account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/SMS/Messages",
'POST', d) resp.error! unless resp.kind\_of? Net::HTTPSuccess

puts "code: %s\nbody: %s" % [resp.code, resp.body]
</code></pre>

<p>What could be easier!?  Well, I got killed by a bug here that took a lot of
debugging.  I had put in the wrong <code>CALLER_ID</code> value.  Make sure you <strong>cut and
paste</strong> the validated phone number value into your code.  You can find the
number on your <a href="https://www.twilio.com/user/account/phone-numbers">Twilio user
page</a>.</p>

<p><em>Tip:</em>  In the last puts of the code, there is a call to <code>resp.code</code> and
<code>resp.body</code>.  Twilio provides another value <code>resp.moreinfo</code>.  This additional
property of the response object is described in the <a href="http://www.twilio.com/docs/api/rest/response">response
API</a>.  It will give your a more
verbose explanation of why a REST request failed.  I wound up finding out that
my approved number was incorrect from this property (see previous paragraph) by
tracing through the stack using <code>rdebug</code>.  Again, familiarity with the
lanaguge&#8217;s facets and debugging tools will make your race much easier.
Unfamiliarity with <code>moreinfo</code> cost me time and thus functionality :-/.</p>

<p><a href="http://www.flickr.com/photos/podio/5724247967/" title="Alan Davis by
Team Podio, on Flickr"><img
src="http://farm4.static.flickr.com/3457/5724247967_879907f893.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Alan Davis"></a></p>

<p><em>Alan Davis, when not being harrassed on GChat by yours truly</em></p>

<p>As I was debugging that issue I had help from Alan Davis and Andrew Benton on
the Twilio team via GChat.  With a simple Twilio paging app completed, I was
ready for a midday snack.  After that I needed to put the logic of my
stand-alone app into a web framework: both on my local MacBook Pro as well as
a remote system reachable by Podio as well as Twilio, i.e. on Heroku.</p>

<h3>Building the Middleware: Heroku and Sinatra</h3>

<p>I started off small in Sinatra, basically cloning the Sinatra tutorial by
<a href="http://titusd.co.uk/2010/04/07/a-beginners-sinatra-tutorial">Joe Yates</a> with
additional support from <a href="http://sinatra-book.gittr.com/">The Sinatra Book</a>.
This set me up with a small web service on my local machine as a proving
ground for what I would deploy onto the <em>real</em> Internet on a Heroku node.</p>

<p>In about a half hour I had a Sinatra app running on my localhost that blended
in the Twilio logic from the previous step.  This file is <code>podio.rb</code>.</p>

<pre><code>require 'sinatra'
require 'twiliolib'


# Twilio REST API version
API_VERSION = '2010-04-01'

# Twilio AccountSid and AuthToken
ACCOUNT_SID = 'XXXXXXX'
ACCOUNT_TOKEN = 'XXXXXXX'

# Outgoing Caller ID previously validated with Twilio
CALLER_ID = 'XXXXXXX';


before do
  # Great debugging!
  pp params
end

helpers do
  def send_a_page(rest,num)
      account = Twilio::RestAccount.new(ACCOUNT_SID, ACCOUNT_TOKEN)

      d = {
          'From' =&gt; CALLER_ID,
          'To' =&gt; rest[0].nil? ? 'XXX-XXX-XXXX' : rest[0],
          'Body' =&gt; "Emergency page"
      }

     resp = 
     account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/SMS/Messages",
                               'POST', d)
     puts "#### code: %s\nbody: %s" % [resp.code, resp.body]
   end


  end
end

get '/' do
  'Minimal Sinatra Hello World!'
end


get '/razzle' do
  'You have been razzled!'
end

get '/simplenotify/' do
 'Paging out simple'
 send_a_page [ nil, 'simple notify', nil, nil ] 
end
</code></pre>

<p>As you can see, given my inexperience with Sinatra I kept things simple.  The
first routes I added were &#8216;<code>/</code>&#8217; and &#8216;<code>/razzle</code>&#8217; (Old joke from the Perl camel
book&#8230;).  Having tested those locally, I was sure I had the right approach.  I
then wrote <code>/simplenotify</code> to see if I could page myself.  This basically
harvested the previous CLI implementation and had me underway.  I next needed
to get this code up into Heroku.</p>

<h3>Heroku</h3>

<p>As I said before, Heroku is not difficult.  But Heroku is not easy either.
Heroku deployments have a number of dependencies on constituent technologies
that are not easily understood unless you are already familiar with the
requisite, supporting technologies preferably in a realm where you have used
each of them independently where their dependencies don&#8217;t cloud the issue.
Regrettably, it doesn&#8217;t seem like there is much documentation that helps take a
developer through that process (although this post might fill that void).</p>

<p>That said, deploying to Heroku once you know these pieces is a snap, but before
then it is daunting, and especially so under time pressure!  For first timers,
your time will principally be spent here (<em>yes, I did just split that
infinitive</em>).</p>

<p>Let me try to simplify things as much as possible:</p>

<ol>
<li>Follow the <a href="http://devcenter.heroku.com/articles/quickstart">quickstart</a>, steps 1-3:</li>
<li>Get Heroku on Ruby 1.9: <code>heroku stack:migrate bamboo-mri-1.9.2</code> in your
working directory</li>
<li>Edit code in podio.rb that worked on localhost, commit it to the local git
repository</li>
<li>Execute step 4 and push to heroku; your code is now on Heroku!</li>
<li>Fail</li>
</ol>

<p>When I started I didn&#8217;t understand two critical constituent technologies that
are needed to make Heroku work.  Here they are.</p>

<h4>Bundler and Gemfile</h4>

<p>Bundler allows you to specify gems your app needs (on local development) in a
Gemfile.  Heroku respects this definition set when it gets your application
pushed to it.  Therefore <strong>any gem you need should be specified in the
Gemfile</strong>.  Thus my Gemfile looks like:</p>

<pre><code>source "http://rubygems.org"

gem "nokogiri"
gem "rack"
gem "sinatra", "1.2.6"
gem "twiliolib"
gem "podio"
</code></pre>

<p>What does this mean?  It means that I want you, Heroku, to install nokogiri,
rack, sinatra, twiliolib, podio into this instance&#8217;s (be it local or Heroku)
gemset repository.  On the local system, thanks to my <code>.rvmrc</code> this will ALSO
be in the <code>podio</code> gemset I specified when I set up the workspace.  Thus I can
issue <code>bundler install</code> and the gems will be downloaded and, thanks to RVM,
be stored in the <code>podio</code> gemset.  This is very cool.  When this directive goes to
Heroku the <em>same thing</em> will happen.  Heroku will grab all the gems specified
in the Gemfile and store it in your app&#8217;s gem repository.  If you want to
<code>require</code> it, make sure its gem is loaded in the <code>Gemfile</code>.  Speaking of
<code>require</code>&#8230;</p>

<h4>Rack and config.ru</h4>

<p>Sinatra uses &#8216;rack&#8217; as middleware.  To configure how a Rack instance is to be
launched, you specify the criteria in <code>config.ru</code>.  Here&#8217;s mine:</p>

<pre><code>require 'sinatra'
require 'twiliolib'
require 'pp'
require './podio.rb'

run Sinatra::Application
</code></pre>

<p>It is the logical complement to the Gemfile.  It says, given those gems that
are now available (thanks to bundler and <code>Gemfile</code>), I want to require these
libraries into the namespace:</p>

<ul>
<li><code>sinatra</code>:  (obviously!)</li>
<li><code>twiliolib</code>:  For use in Twilio operations</li>
<li><code>pp</code>:  pretty-print debugging</li>
<li><code>./podio.rb</code>:  My code!</li>
</ul>

<p>The last step is a command to run a <code>Sinatra::Application</code>.</p>

<p>With these two files in place and in the git repository, we&#8217;re good to run a
Heroku-based simple-page out.  With a simple <code>git push heroku master</code> I was
able to get my code up on Heroku.  The <code>heroku logs (-n lineCount)</code> command
was a good friend during this process.  Pointing a browser at
<code>http://my-heroku-instance.heroku.com/simplenotify</code> sent my phone a page.  Next
was to tie the other half in:  link into Podio.</p>

<p><a href="http://www.flickr.com/photos/podio/5724245617/" title="Neil Mansilla
and Andreas Haugstrup by Team Podio, on Flickr"><img
src="http://farm4.static.flickr.com/3624/5724245617_5101f91113.jpg"
class="aligncenter size-full"
width="407" height="500" alt="Neil Mansilla and Andreas Haugstrup"></a></p>

<p><em>Neil uses Skype to contact Podio home-base in Copenhagen for Andreas&#8217; help
and Journey playlist</em></p>

<h3>Podio API</h3>

<p>First, I went back to my app editor and added a field called &#8220;Emergency&#8221; with
values of &#8220;Yes&#8221; and &#8220;No.&#8221;  Then I saved the app.  This would be my signal of
whether to page out.</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/webhook.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/webhook-300x145.png" alt="" title="webhook" width="300" height="145" class="aligncenter size-medium wp-image-2256" /></a></p>

<p>Next I clicked the &#8220;Settings &gt; WebHooks&#8221; menu.  I added a new hook and
specified that <code>item.create</code> tasks should trigger the URL to my Heroku
instance called <code>/verify</code>.  This name is a bad name, but I was in too much of
a hurry to change it.  I should have called it something else.  I specified,
thus, a URL of the form <code>http://my-heroku-instance/verify</code>.</p>

<p><a href="http://stevengharms.com/wp-content/uploads/2011/05/hookspecify.png"><img src="http://stevengharms.com/wp-content/uploads/2011/05/hookspecify-288x300.png" alt="" title="hookspecify" width="288" height="300" class="aligncenter size-medium wp-image-2252" /></a></p>

<p>The next step is to verify your URL.  To accomplish this Podio will send a
form-encoded data blob (POST) to your URL.  You must catch this and send back
the <a href="https://developers.podio.com/doc/hooks/validate-hook-verificated-215241">validation information specified per the
spec</a>.</p>

<p>At this time I was encouraged by Christian to make use of the 
<a href="https://developers.podio.com/clients/ruby">Ruby client API</a> to handle the
validation.  Ergo I added <code>podio</code> to my Gemfile and required <code>podio</code> in my
<code>config.ru</code>.  I then ran <code>bundler install</code> and viola, I had the gem I needed.
I then did another <code>git push heroku master</code> and Heroku built in the new
dependency.  I was now able to get validation working via API.</p>

<p>Getting validation set up took me a while, but it basically boils down to
this.</p>

<p>In my <code>podio.rb</code>, in the listener for the route I specified in the WebHook
configuration to use I added the following logic:</p>

<p>require &#8216;sinatra&#8217;
  require &#8216;twiliolib&#8217;</p>

<p>post &#8216;/verify&#8217; do
    if params[&#8220;type&#8221;] == &#8220;hook.verify&#8221;
      Podio.setup( :api_key => &#8216;MY API KEY&#8217;, :api_secret => &#8216;SECRET_STUFF&#8217;)<br />
      Podio.client.authenticate_with_credentials(&#8216;MY_PODIO_EMAIL_LOGIN&#8217;, &#8216;PW&#8217;)
      Podio::Hook.validate params[&#8220;hook_id&#8221;],  params[&#8220;code&#8221;]
    end
  end</p>

<p>Then you hit the &#8220;Verify&#8221; button in Podio.  If you watch your Heroku logs,
you&#8217;ll see the request come through and the validation trigger occur.
<strong>NOTE:</strong>  I lost a lot of time because I had &#8216;get&#8217; as the first word for
/verify.  Verification happends as a <strong>POST</strong> operation.  It was getting late
at that point and I was completely blind to that error.</p>

<p><a href="http://www.flickr.com/photos/podio/5724781980/" title="Podio
Hackathon by Team Podio, on Flickr"><img
src="http://farm3.static.flickr.com/2791/5724781980_11d41ea4c8.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Podio Hackathon"></a></p>

<p><em>Probably about this point I got stuck on this stupid bug&#8230;</em></p>

<p>Now that the hook was validated, all I needed was a means to catch
<code>item.create</code> operations.  So I added:</p>

<pre><code>if params["type"] == "item.create"
 send_a_page [ nil, 'simple notify', nil, nil ], params["item_id"]
end
</code></pre>

<p>This would pass the configuration message as well as the critical item_id
for the newly-created item to a helper method which would implement the
Twilio bridge to place a page.</p>

<p>Here&#8217;s that method, it should look familiar based on the content presented
thus far.</p>

<pre><code>helpers do
  def send_a_page(rest,num)

   Podio.setup( :api_key =&gt; 'XXXXXX', :api_secret =&gt; 'XXXXXX')   
   Podio.client.authenticate_with_credentials('XXXXXX', 'XXXXX')

   # The ID passed in from /verify
   anItem=Podio::Item.find(num)

   # Very ugly JSON hash dereferencing
   theField=
     anItem["fields"].detect{|x| x["external_id"] == "is-this-an-emergency" }
   theRes=anItem["tasks"].first["created_by"]["name"]

   # If the emergency value field is set to use
   if  theField["values"].first["value"] =~ /yes/i 
     # Cheap Heroku logging <img src='http://stevengharms.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> 
     puts "YES!  It is an emergency" 

      account = Twilio::RestAccount.new(ACCOUNT_SID, ACCOUNT_TOKEN)

      d = {
          'From' =&gt; CALLER_ID,
          'To' =&gt; rest[0].nil? ? 'XXX-XXX-XXXX' : rest[0],
          'Body' =&gt; "Emergency page: Task: #{params["item_id"]}" +
                          " from resident "+ 
                           "#{theRes} has been reported in Podio!"
      }

     resp = 
     account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/SMS/Messages", 
                               'POST', d)
     puts "#### code: %s\nbody: %s" % [resp.code, resp.body]
   else
     puts "NO"
   end
  end
end
</code></pre>

<p><a href="http://www.flickr.com/photos/podio/5724240261/" title="The demo that
never was.  by Team Podio, on Flickr"><img
src="http://farm3.static.flickr.com/2673/5724240261_e6fdbd2397.jpg"
class="aligncenter size-full"
width="500" height="333" alt="The demo that never was. "></a></p>

<p><em>Caleb invited me to show up via the SF Ruby group</em></p>

<h2>Finish Line</h2>

<p>At this point all the pieces were in place and I created a test item, set to
emergency, and had it page my cell phone.  It worked!  I finished about 10
minutes ahead of time and did something revolutionary.</p>

<p><strong>I STOPPED WORKING</strong></p>

<p>A failing app is a non-competitor, so I decided to quit with a small bit
of functionality in place.  I had planned for more, but learning Heroku,
Sinatra, Twilio, and Podio had taken more time than I had expected.  I credit
knowing when to stop to be the result of 10 years hard experience in coding
before deadlines or change request endings.</p>

<h2>Comments</h2>

<p>The story I tell here is pretty straight-forward and linear, but in reality
(and I have the git commit logs to prove it!) it was much messier.  I hope
anyone interested can follow this post for didactic purposes not narratorial
veracity.</p>

<h2>Demo</h2>

<p>I grabbed a beer and started talking with some of the guests who had come for
the demos.  The beer was necessary because my furious coding had left my
nerves shot and my hands shaking.  We sat down and were called upon to
demonstrate in order.  When my turn came I explained about the need for case
tracking and alert systems.  I created a new &#8220;Is It Done Yet&#8221; item, set the
flag to emergency, and submitted the item.  And as I talked I felt a buzz and
ring from my chest pocket:  I pulled out my phone and showed that the alert
had worked!</p>

<p><a href="http://www.flickr.com/photos/podio/5724795210/" title="Winner Steven
G. Harms by Team Podio, on Flickr"><img
src="http://farm4.static.flickr.com/3100/5724795210_34b7d5772d.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Winner Steven G. Harms"></a></p>

<p><em>I demonstrate&#8230;</em></p>

<p>It was a good feeling to get down from the presentation with a working app.
The other entrants were all great.  Alas, several good ideas were also presented
where the developers couldn&#8217;t <em>quite</em> get all the pieces working in the time
allotted.</p>

<p><a href="http://www.flickr.com/photos/podio/5724793064/" title="Ching Mey and
John Fan by Team Podio, on Flickr"><img
src="http://farm6.static.flickr.com/5087/5724793064_4d3a7f3a85.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Ching Mey and John Fan"></a></p>

<p><em>Cardinal Blue did a great job</em></p>

<h2>The Winner, Me?</h2>

<p>When the judges&#8217; delibrations had finished they returned and announced that
3rd prize was going to Nick who had worked with us remotely from Copenhagen
(home of Podio).  He won the sweet headphones as his application was designed
to catalog entrants in the Eurovision contest.</p>

<p><a href="http://www.flickr.com/photos/podio/5724209323/" title="Andreas
Haugstrup and Nick Barnwell  by Team Podio, on Flickr"><img
src="http://farm3.static.flickr.com/2363/5724209323_db0771a8ee.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Andreas Haugstrup and Nick Barnwell "></a></p>

<p>Coming up next, for the iPad 2, was the team from Cardinal Blue.  I thought their conference call bridging app (also using Twilio!) between Podio contacts was really great.</p>

<p><a href="http://www.flickr.com/photos/podio/5724214565/" title="Ching Mey and
John Fa by Team Podio, on Flickr"><img
src="http://farm6.static.flickr.com/5265/5724214565_58d4f21337.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Ching Mey and John Fa"></a></p>

<p>But I was very surprised when Phil Chambers announced that the
winner was &#8220;Team Solo&#8221; that is, me.  I was awarded the beautiful cinema
display on which, even now, I type this document.</p>

<p><a href="http://www.flickr.com/photos/podio/5724220057/" title="Winner Steven
G. Harms by Team Podio, on Flickr"><img
src="http://farm4.static.flickr.com/3481/5724220057_a58c974d62.jpg"
class="aligncenter size-full"
width="500" height="333" alt="Winner Steven G. Harms"></a></p>

<p><em>Checking my iPhone for an update as triggered from Podio for the camera</em></p>

<p>I gave a little speech, thanking the Twilio guys and the Podio guys who helped
me.  I was thankful to all of them for creating systems that had openness and
hybridization at their heart.  With such a good design principle at their
core, all apps can be integrated for great and surprising effect.</p>

<p>After that it was time for more beer and a great lasagne dinner.  Podio is
first-class all the way through.</p>

<p>I had a great night talking with contacts who urged me to take the idea
further and I hope to talk with all of them again soon.</p>

<h2>Thanks</h2>

<p>I am so thankful to everyone who helped me on the way and am thankful to Podio
for their generosity and initiative in setting this up.  I urge all of you to
try to make a hack fest.  It really gels your skills and, who knows, you
might win!</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/i-won-the-podio-api-release-competition/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating a Ruby Gem for the Uninitiated</title>
		<link>http://stevengharms.com/creating-a-ruby-gem-for-the-uninitiated</link>
		<comments>http://stevengharms.com/creating-a-ruby-gem-for-the-uninitiated#comments</comments>
		<pubDate>Sat, 11 Dec 2010 18:15:53 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/creating-a-ruby-gem-for-the-uninitiated</guid>
		<description><![CDATA[Introduction One of the problems with gem authorship is that the various tools for gem generation all seem to stomp upon one another and seem to have varying states of freshness. Toss into this the questions about whether a given gem-generation framework eases the sharing via Gemcutter (or is it still pointing to Github?) and [...]]]></description>
			<content:encoded><![CDATA[<h2> Introduction</h2>

<p>One of the problems with gem authorship is that the various tools for gem
generation all seem to stomp upon one another and seem to have varying states
of freshness. Toss into this the questions about whether a given
gem-generation framework eases the sharing via Gemcutter (or is it still
pointing to Github?) and it&#8217;s a confusing start for the uninitiated.</p>

<p>I will detail the process that ultimately got me to re-structure some old code of mine as <a href="https://rubygems.org/gems/macronconversions">my first gem</a>.</p>

<p><span id="more-2108"></span></p>

<h2> Getting started</h2>

<p>After an <span class="caps">IRC</span> discussion, <a href="https://github.com/radar">radar</a> pointed me to using
<code>bundler</code> to accomplish a skeletal gem layout. Both I as well as other <span class="caps">IRC</span>
lurkers were surprised by this recommendation. The popular opinion up to that
time seemed to hold that bundler was a much more heavyweight or was a deploy
time dependency tool. The <a href="http://gembundler.com/rubygems.html">bundler guide</a>
I was pointed to explains the use of bundler to get the skeletal layout.</p>

<p>An abridged version looks like <code>gem install bundler &amp;&amp; bundle gem new_gem_name</code>, edit your gemspec, edit your code, <code>gem build</code> when it&#8217;s good
to go.</p>

<h2> Limited Raking</h2>

<p>You can now run `rake -T` and see the skeletal set of tasks.</p>

<pre>rake build    
rake install  
rake release</pre>

<p>What about running tests, locally deploying, or clobbering old gems? To do
that we need to make the Rakefile <em>mas macho</em>. Normally this would entail
writing several Rake tasks. Fortunately the <code>gem-this</code> gem makes this
augmentation easy.</p>

<h2> Gem This</h2>

<p>After getting and installing gem-this, you can, from within the
bundle-generated directory, run `gem this`:</p>

<p><pre>$ gem this</pre>
Appended to existing Rakefile</p>

<p>Now <pre>rake -T</pre> gives you many additional tasks:</p>

<pre>
build
clean
clobber_package
clobber_rdoc
gem
gemspec
install
package
rdoc
release
repackage
rerdoc
</pre>

<h2> YAGNI</h2>

<p>The odd thing was that I didn&#8217;t really need those additional tasks.  At the
end, all I wound up keeping was the rdoc tasks.  My Rakefile wound up looking
like:</p>

<pre>
require 'bundler'
require "rubygems" 
require "rake/rdoctask" 

# Add the bundler tasks, this comes because I used `bundle gem`.
Bundler::GemHelper.install_tasks

# `gem this` tasks

# Generate documentation
Rake::RDocTask.new do |rd| 
rd.rdoc_files.include("lib/**/*.rb")
rd.rdoc_dir = "rdoc" 
end   

</pre>

<h2> Ignorance Is Bliss</h2>

<p>I would also add that it&#8217;s important to make sure you have a .gitignore in
place when you start development.  This was generated by <code>bundler</code> in the
first step automagically.</p>

<h2> Write Some Code</h2>

<p>Once you have completed these steps, you are ready to get coding.</p>

<h2> Jeweler</h2>

<p>Another tool in the ecosystem is
<a href="https://github.com/technicalpickles/jeweler">Jeweler</a>. When I initally started
this work, I was unsure as to whether the <code>bundler</code> approach was better than
then <code>jeweler</code> apporoach. The main differece seems to be in the approach to
the gemfile. Bundler integrates tightly with <code>git</code>. Assuming git&#8217;s presence
allows <code>bundler</code> to derive things that, in a <code>jeweler</code>-generated <code>gemspec</code>,
require explicit definition.</p>

<p><em>In a bundler gemspec:</em>
<pre>s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")</code></pre></p>

<p>Which means that it&#8217;s deriving a file list based on the <span class="caps">SCM</span>, that&#8217;s nice.</p>

<p>versus</p>

<p><em>a jeweler gemspec</em></p>

<pre>
s.files = [
".document",
"Gemfile",
"LICENSE.txt",
"README.rdoc",
"Rakefile",
</pre>

<p> As you can see there&#8217;s a difference in approach.  At the end of the day,
the approach that works for me is to use <code>bundle gem</code> and then to add the
following methods into the Rakefile.</p>

<pre>
# Generate documentation
Rake::RDocTask.new do |rd| 
rd.rdoc_files.include("lib/**/*.rb")
rd.rdoc_dir = "rdoc" 
end

#Added to get testing working
require 'rake/testtask'
Rake::TestTask.new(:test)
</pre>

<p> I&#8217;m still working through understanding these tools, but I believe either are a solid help in setting up your intital Rubygem.  Thanks to these tools I was able to commit my first RubyGem:  <a href="http://rubygems.org/gems/macronconversions">macronconversions</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/creating-a-ruby-gem-for-the-uninitiated/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL database automatic launch on OSX 10.6 Snow Leopard</title>
		<link>http://stevengharms.com/postgresql-database-automatic-launch-on-osx-10-6-snow-leopard</link>
		<comments>http://stevengharms.com/postgresql-database-automatic-launch-on-osx-10-6-snow-leopard#comments</comments>
		<pubDate>Fri, 05 Feb 2010 04:58:47 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[apple]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=1934</guid>
		<description><![CDATA[It took a while to find this, but here&#8217;s my solution Add this file: /Library/LaunchDaemons/org.postgres.launchd.plist &#60;?xml version="1.0" encoding="UTF-8"?&#62; &#60;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd";&#62; &#60;plist version="1.0"&#62; &#60;dict&#62; &#60;key&#62;Label&#60;/key&#62; &#60;string&#62;org.postgres.launchd&#60;/string&#62; &#60;key&#62;Disabled&#60;/key&#62; &#60;false/&#62; &#60;key&#62;UserName&#60;/key&#62; &#60;string&#62;_pgsql&#60;/string&#62; &#60;key&#62;GroupName&#60;/key&#62; &#60;string&#62;_pgsql&#60;/string&#62; &#60;key&#62;Program&#60;/key&#62; &#60;string&#62;/usr/local/pgsql/bin/postmaster&#60;/string&#62; &#60;key&#62;EnvironmentVariables&#60;/key&#62; &#60;dict&#62; &#60;key&#62;PGDATA&#60;/key&#62; &#60;string&#62;/usr/local/pgsql/data/&#60;/string&#62; &#60;/dict&#62; &#60;key&#62;RunAtLoad&#60;/key&#62; &#60;true/&#62; &#60;/dict&#62; &#60;/plist&#62; You can then load it and unload [...]]]></description>
			<content:encoded><![CDATA[<p>It took a while to find this, but here&#8217;s my solution</p>

<p>Add this file:  /Library/LaunchDaemons/org.postgres.launchd.plist</p>

<pre>
<code >&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
        "http://www.apple.com/DTDs/PropertyList-1.0.dtd";&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    <!-- Following the launchd man page enumeration of keys -->
    &lt;key&gt;Label&lt;/key&gt;
      &lt;string&gt;org.postgres.launchd&lt;/string&gt;
    &lt;key&gt;Disabled&lt;/key&gt;
      &lt;false/&gt;
    &lt;key&gt;UserName&lt;/key&gt;
      &lt;string&gt;_pgsql&lt;/string&gt;
    &lt;key&gt;GroupName&lt;/key&gt;
      &lt;string&gt;_pgsql&lt;/string&gt;
    &lt;key&gt;Program&lt;/key&gt;
      &lt;string&gt;/usr/local/pgsql/bin/postmaster&lt;/string&gt;
      &lt;key&gt;EnvironmentVariables&lt;/key&gt;
      &lt;dict&gt;
              &lt;key&gt;PGDATA&lt;/key&gt;
              &lt;string&gt;/usr/local/pgsql/data/&lt;/string&gt;
      &lt;/dict&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
      &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code>
</pre>

<p>You can then load it and unload it by issuing:</p>

<pre>
$ sudo launchctl load /Library/LaunchDaemons/org.postgres.launchd.plist
$ sudo launchctl unload /Library/LaunchDaemons/org.postgres.launchd.plist
</pre>

<p>Now get to making some great Rails stuff!</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/postgresql-database-automatic-launch-on-osx-10-6-snow-leopard/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Product Announcement</title>
		<link>http://stevengharms.com/product-announcement</link>
		<comments>http://stevengharms.com/product-announcement#comments</comments>
		<pubDate>Sun, 11 Jan 2009 18:23:36 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Latin]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/product-announcement</guid>
		<description><![CDATA[My blogging has been light for the last several months because I&#8217;ve been focused on trying to get admitted to graduate school. Included in the portfolio of &#8220;why Steven is a special snowflake and you should admit him&#8221; argumentation is reference to a project which demonstrates the fusion of my interests in Latin, linguistics, Ruby, [...]]]></description>
			<content:encoded><![CDATA[<p>My blogging has been light for the last several months because I&#8217;ve been focused on trying to get admitted to graduate school.  Included in the portfolio of &#8220;why Steven is a special snowflake and you should admit him&#8221; argumentation is reference to a project which demonstrates the fusion of my  interests in Latin, linguistics, Ruby, metaprogramming, and Rails.</p>

<p>To find out more about my project, visit <a href="http://verbalatina.blackbeardev.com">The Verba Latina website</a>.  As a warning, the initial load is a bit pokey.  I&#8217;m going to move to a more robust host later.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/product-announcement/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LatinIRB</title>
		<link>http://stevengharms.com/latinirb</link>
		<comments>http://stevengharms.com/latinirb#comments</comments>
		<pubDate>Sun, 05 Oct 2008 05:17:56 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Latin]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/latinirb</guid>
		<description><![CDATA[As I mentioned previously, I&#8217;ve been working on a library in Ruby used to model Latin Verbs. Here&#8217;s a 5 minute demo of what you can do: My Latin::LatinVerb + Ruby&#8217;s IRB environment produces this: It&#8217;s easier on the eyes if you watch the full-size version at blip.tv I&#8217;m working on building a site around [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned previously, I&#8217;ve been working on a library in Ruby used to model Latin Verbs.</p>

<p>Here&#8217;s a 5 minute demo of what you can do:  My Latin::LatinVerb + Ruby&#8217;s IRB environment produces this:</p>

<p><embed src="http://blip.tv/play/AdGNJgA" type="application/x-shockwave-flash" width="485" height="290" allowscriptaccess="always" allowfullscreen="true"></embed></p>

<p><em>It&#8217;s easier on the eyes if you watch the <a href="http://blip.tv/file/1322366">full-size version at blip.tv</a></em></p>

<p>I&#8217;m working on building a site around this code base.  I hope to release it within the next month, but for the moment, I can give you a small sample of my recondite study.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/latinirb/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Life, not blogging</title>
		<link>http://stevengharms.com/life-not-blogging</link>
		<comments>http://stevengharms.com/life-not-blogging#comments</comments>
		<pubDate>Sun, 21 Sep 2008 16:00:59 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Latin]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://stevengharms.com/?p=1431</guid>
		<description><![CDATA[I&#8217;ve been taking a bit of a hiatus from blogging thanks to: Car accident drama Latin III postponed GRE from this weekend to the 24th of October Work The LatinVerb library. Most of these don&#8217;t produce much in the way of visual artifacts, but here&#8217;s a short demonstration of the LatinVerb library ( it&#8217;s coherently [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been taking a bit of a hiatus from blogging thanks to:</p>

<ol>
<li>Car accident drama</li>
<li>Latin III</li>
<li>postponed GRE from this weekend to the 24<sup>th</sup> of October</li>
<li>Work</li>
<li>The LatinVerb library.</li>
</ol>

<p>Most of these don&#8217;t produce much in the way of visual artifacts, but here&#8217;s a short demonstration of the LatinVerb library ( it&#8217;s coherently working, but still needs some refactoring to get it to 0.1 release state&#8230; ).  Here&#8217;s the video:</p>

<p><embed src="http://blip.tv/play/Ac6jTAA" type="application/x-shockwave-flash" width="480" height="293" allowscriptaccess="always" allowfullscreen="true"></embed></p>

<p>What&#8217;s going on here is that I have a  Ruby debugger ( RDebug ) session open where I&#8217;ve created an instance of Latin::LatinVerb.  I then proceed to execute some of the &#8220;vectors&#8221; that uniquely identify a single conjugation of a verb or a collection of verb tenses.</p>

<p>It&#8217;s not too pretty yet, my main work has been on getting the thinking working.  The displaying part comes next.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevengharms.com/life-not-blogging/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

