<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

 <title>Corey Donohoe - atmos.org</title>
 
 <link href="http://www.atmos.org" />
 <updated>2012-01-17T13:51:18-08:00</updated>
 <id>http://www.atmos.org/</id>
 <author>
   <name>Corey Donohoe</name>
   <email>atmos@atmos.org</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/atmosdotorg" /><feedburner:info uri="atmosdotorg" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>My talk from POSSCON 2011</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/JgR_SPIYvKc/posscon-2011.html" />
   <updated>2011-03-29T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2011/03/29/posscon-2011</id>
   <content type="html">&lt;div&gt;
  &lt;h1&gt;&lt;a href="http://posscon.org"&gt;POSSCON 2011&lt;/a&gt;&lt;/h1&gt;
  &lt;p&gt;
    I posted my slides from POSSCON.  The goal of the talk to let
    student and educators know that school alone isn't going to prepare you
    for real world software development.  A few people came up to me
    after the talk and said "I don't know what school you went to, but I
    could program when I graduated."  When I asked him if he knew how to
    write software when he graduated, he paused and then he smiled.  I
    don't think Open Source or Education alone will prepare you, but I
    really think they help.  Here are my slides.
  &lt;/p&gt;

  &lt;div class="slideshare" style="width:425px" id="__ss_7436750"&gt;
    &lt;strong style="display:block;margin:12px 0 4px"&gt;
      &lt;a href="http://www.slideshare.net/atmosorg/posscon2011" title="Posscon2011"&gt;Posscon2011&lt;/a&gt;
    &lt;/strong&gt;
    &lt;object id="__sse7436750" width="425" height="355"&gt;
      &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=posscon2011-110329155923-phpapp02&amp;stripped_title=posscon2011&amp;userName=atmosorg" /&gt;
      &lt;param name="allowFullScreen" value="true"/&gt;
      &lt;param name="allowScriptAccess" value="always"/&gt;
      &lt;embed name="__sse7436750" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=posscon2011-110329155923-phpapp02&amp;stripped_title=posscon2011&amp;userName=atmosorg" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;
     &lt;/embed&gt;
    &lt;/object&gt;
    &lt;div style="padding:5px 0 12px"&gt;
      View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/atmosorg"&gt;atmosorg&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

</content>
 <feedburner:origLink>http://www.atmos.org/2011/03/29/posscon-2011.html</feedburner:origLink></entry>
 
 <entry>
   <title>The Geek Talk Interview</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/K4guFdoRKds/geektalk-interview.html" />
   <updated>2010-12-13T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2010/12/13/geektalk-interview</id>
   <content type="html">&lt;h1&gt;Interviewed by The Geek Talk&lt;/h1&gt;

&lt;p&gt;The folks over at &lt;a href="http://thegeektalk.com/interviews/corey-donohoe/"&gt;The Geek Talk&lt;/a&gt; posted an interview with me.  It&amp;rsquo;s considerably more informative than my current about page.  They&amp;rsquo;ve also interviewed a bunch of other people doing awesome shit recently too.  The format is pretty simple and it&amp;rsquo;s nice to find out a little more about people doing amazing things.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2010/12/13/geektalk-interview.html</feedburner:origLink></entry>
 
 <entry>
   <title>Joining GitHub</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/5AgOOR7qnSs/joining-github.html" />
   <updated>2010-08-30T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2010/08/30/joining-github</id>
   <content type="html">&lt;h1&gt;Joining GitHub&lt;/h1&gt;

&lt;p&gt;Today is my first day at &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.  I&amp;rsquo;m not gonna lie, it&amp;rsquo;s a little
intimidating working alongside these amazing people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://tom.preston-werner.com"&gt;tom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ozmm.org"&gt;chris&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pjhyett.com"&gt;pj&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://schacon.github.com/"&gt;scott&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tekkub.net"&gt;tekkub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://luckiestmonkey.com"&gt;melissa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tomayko.com/about"&gt;ryan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://warpspire.com"&gt;kyle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zachholman.com"&gt;zach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://techno-weenie.net"&gt;rick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I use GitHub daily.  I love open source and have for about a decade.  I love
the ecosystem that exists around sharing code for both teaching and learning.
I believe GitHub will continue to grow over the next few years and I&amp;rsquo;m
abso-fucking-lutely delighted to be a part of something I feel so passionate
about.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m hoping that they&amp;rsquo;ll keep me around for a while. :)&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2010/08/30/joining-github.html</feedburner:origLink></entry>
 
 <entry>
   <title>On Leaving Engine Yard</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/TzEn6lZfrAg/on-leaving-engine-yard.html" />
   <updated>2010-07-31T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2010/07/31/on-leaving-engine-yard</id>
   <content type="html">&lt;h1&gt;So I quit working at Engine Yard&lt;/h1&gt;

&lt;p&gt;I talked to my boss yesterday and explained that August 13th would be my last
day at &lt;a href="http://engineyard.com"&gt;Engine Yard&lt;/a&gt;.  A whole lot of crazy shit has gone down at work over the
past few months and there&amp;rsquo;s a few more amazing things they haven&amp;rsquo;t announced
yet.  About a year ago I packed up all my shit and moved to SF because the
company was in really bad shape.  Things have been shaken up recently and
Engine Yard is finally back on track to becoming a great company.&lt;/p&gt;

&lt;p&gt;As an early employee I was privy to a bunch of stock that has, for the most
part, vested.  So in the choice of &amp;ldquo;wait out for the last 25% of my stock&amp;rdquo; vs
&amp;ldquo;moving onto something new and exciting,&amp;rdquo; I&amp;rsquo;m choosing the latter.  3.5 years
is a long time to stay at any job, and I want to be a part of something new.&lt;/p&gt;

&lt;p&gt;As we grew from fewer than 10 people to almost 90, I&amp;rsquo;ve seen a lot of
organizational restructuring.  I really don&amp;rsquo;t want to work in a corporate
environment, and I have for the better part of a year.  A corporate environment
is pretty unavoidable if you&amp;rsquo;ve taken as much VC as EY has.  It&amp;rsquo;s something
I&amp;rsquo;ll think long and hard about if I ever find myself building a company that is
going to take venture capital.&lt;/p&gt;

&lt;p&gt;However, I&amp;rsquo;m grateful to have been a part of such crazy growth with so many
amazing customers and co-workers.  I&amp;rsquo;ll miss my coworkers more than anything.&lt;/p&gt;

&lt;h2&gt;The AppCloud Team&lt;/h2&gt;

&lt;p&gt;The people working on the &lt;a href="http://www.engineyard.com/products/appcloud"&gt;appcloud&lt;/a&gt; product are the best team I&amp;rsquo;ve ever been a
part of.  It currently consists of these members:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/sr"&gt;sr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/geemus"&gt;geemus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/benburkert"&gt;benburkert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/smerritt"&gt;smerritt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/larrytheliquid"&gt;larrytheliquid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/martinemde"&gt;martinemde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/adelcambre"&gt;adelcambre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/halorgium"&gt;halorgium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;They&amp;rsquo;re pretty much the shit.  They&amp;rsquo;re also &lt;a href="http://www.engineyard.com/company/careers/ruby-engineers"&gt;hiring&lt;/a&gt; if you&amp;rsquo;re interested.&lt;/p&gt;

&lt;h2&gt;Where I&amp;rsquo;m Going&lt;/h2&gt;

&lt;p&gt;I don&amp;rsquo;t actually have anything lined up.  I know I want to work less, so I&amp;rsquo;ll
prolly do some contracting for a while.  I&amp;rsquo;ll be available for contract work
starting mid August.  &lt;a href="mailto:atmos@atmos.org"&gt;Holler at me&lt;/a&gt; if you&amp;rsquo;re interested.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2010/07/31/on-leaving-engine-yard.html</feedburner:origLink></entry>
 
 <entry>
   <title>Constantly Shipping Refactorings</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/VUD00vEQ4fg/constantly-shipping-refactorings.html" />
   <updated>2010-07-28T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2010/07/28/constantly-shipping-refactorings</id>
   <content type="html">&lt;h1&gt;Constantly Shipping Refactorings&lt;/h1&gt;

&lt;p&gt;Recently, two of my favorite hackers, &lt;a href="http://github.com/martinemde"&gt;Martin&lt;/a&gt; and &lt;a href="http://github.com/halorgium"&gt;Tim&lt;/a&gt;, have been working on a
pretty big refactoring in cloud.  In the past our team probably would&amp;rsquo;ve
worked in a topic branch for a few weeks, followed by a painful
rebase/merge, followed by a deployment we really hoped we got right.  Since
this refactor requires db schema changes, we&amp;rsquo;d prolly have to take the site
down for at least a few minutes to do it.  They didn&amp;rsquo;t want to do it this, so
they approached the problem in a new way (to us).  Here&amp;rsquo;s what they&amp;rsquo;re doing.&lt;/p&gt;

&lt;h2&gt;Unicorn and Zero Downtime Migrations with DataMapper&lt;/h2&gt;

&lt;p&gt;We moved to unicorn the other month and have found the 0 downtime deploys
really liberating.  If something is ready to go out to customers, we ship it.
We have no planned day of the week or time of day that we ship.  On weekdays we
normally ship 5-6 times a day and no one ever notices.  DB schema changes currently
make things a little more difficult. When you add a new model, you create a
migration for it, and you ship the model with the migration.  This
is where Martin and Tim tried something new.  Instead of coupling the migration
and the model addition, they&amp;rsquo;re doing the migrations before the model is
introduced to the system.&lt;/p&gt;

&lt;h2&gt;Adding a New Model&lt;/h2&gt;

&lt;p&gt;So the other day they added a new model, let&amp;rsquo;s call it User.
When they wanted to introduce the User model, they did it in
two releases. In the first release they shipped a zero downtime deploy to
add the users table. The first release didn&amp;rsquo;t take advantage of
the user model, it was just a normal deploy with the migrations running AFTER
the unicorn processes had restarted. In the second release they shipped the
User model in another zero downtime deploy that actually started USING the users
tabel. Adding a table is pretty trivial if you think about it, but what about removing a column?&lt;/p&gt;

&lt;h2&gt;Data Transformation/Migration&lt;/h2&gt;

&lt;p&gt;Have you ever had to rollback a deployment that had data migrations?  You need
to go find your latest database backup, restore that, extend the outage you
took because you hadn&amp;rsquo;t planned on things going south.  It&amp;rsquo;s insanely stressful
and makes you look like a jackass to your co-workers.  Your customers won&amp;rsquo;t like
it either.&lt;/p&gt;

&lt;h2&gt;Removing a Column from a Model&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s say that during the refactoring they discovered some insanity in our
system: tokens in two places, one on the User model and one on the
associated class Customer.  First deployment they tracked down all the places
where the attribute, in this case &amp;lsquo;token&amp;rsquo;, was accessed directly and removed
it.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s an example of the User class before the changes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class User
  include DataMapper::Resource

  property :id,              Serial
  property :token,           String, :required =&amp;gt; true,
  belongs_to :customer,      Integer

  def valid_token?
    token == some_token_verification_method
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&amp;rsquo;s an example of the User class after the changes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class User
  include DataMapper::Resource

  property :id,              Serial
  belongs_to :customer,      Integer

  def valid_token?
    customer.token == some_token_verification_method
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When this code deploys, the User table still has the token field.
Shortly after that, they shipped another release with a migration that only
removed the newly unused column. Again, 0 downtime.  Guess how we do
tables?  The same way.&lt;/p&gt;

&lt;h2&gt;Renaming a column&lt;/h2&gt;

&lt;p&gt;Renaming a column is kinda weird because it takes 4 deploys.  On the first deploy,
create the new, unused column.
On the second deploy, introduce code that starts using the new column and
denormalizes the attributes as they&amp;rsquo;re accessed. This deploy also carries a zero downtime migration that copies the attribute over to the new column. All access to the attribute is now directed to the correct column. On the third deploy, remove all reference to the old
column. Finally on the fourth deploy, nuke the old column after the deploy
completes.  For an example of how the new column usage works, check this snippet out.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class User
  include DataMapper::Resource

  property :id,              Serial
  property :token,           String, :required =&amp;gt; true,
  property :tos_accepted,    Boolean, :default  =&amp;gt; false
  property :admin,           Boolean, :default  =&amp;gt; false
  property :administrator,   Boolean, :default  =&amp;gt; false

  timestamps :at

  def admin
    value = attribute_get(:admin)
    value.nil? ? copy_admin : value
  end

  def admin?
    admin
  end

  def copy_admin
    unless update(:admin =&amp;gt; adminstrator)
      raise "Could not save user: #{errors.full_messages.join(", ")}"
    end
    admin
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;It&amp;rsquo;s so simple, who cares?&lt;/h2&gt;

&lt;p&gt;One thing I really love about this is the guys are constantly shipping
incremental improvements.  There won&amp;rsquo;t be an evening where they&amp;rsquo;re forced to
work late to ship out their schema changes.  You&amp;rsquo;ll never hear them cursing
other developers for introducing changes that mess with their refactoring.
Even though they&amp;rsquo;re focused on a very large refactoring, they&amp;rsquo;re never a few
days off from having something to show.  You can watch their progress as the
commits flow by.  They never entered the mindset that it&amp;rsquo;s ok to get lost in
refactoring wonderland.  Solving a problem elegantly doesn&amp;rsquo;t mean you have to
go sit and think up the most beautiful solution ever. Break it down into little
pieces and ship &amp;lsquo;em.&lt;/p&gt;

&lt;p&gt;Tim, Martin, and I are in the process of automating these kinds of rollouts. We&amp;rsquo;re testing it right now.&lt;/p&gt;

&lt;h2&gt;Hiring&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;re also &lt;a href="http://www.engineyard.com/company/careers/ruby-engineers"&gt;hiring right now&lt;/a&gt;.  Send &lt;a href="http://github.com/atmos"&gt;me&lt;/a&gt; a message on &lt;a href="http://github.com"&gt;github&lt;/a&gt; if you&amp;rsquo;re
interested in working with a top notch group of hackers.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2010/07/28/constantly-shipping-refactorings.html</feedburner:origLink></entry>
 
 <entry>
   <title>My talk from Red Dirt Ruby Conf - Rise of Devops</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/txhqv0pcVdg/red-dirt-ruby-conf-talk-on-devops.html" />
   <updated>2010-05-07T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2010/05/07/red-dirt-ruby-conf-talk-on-devops</id>
   <content type="html">&lt;div&gt;
  &lt;h1&gt;&lt;a href="http://reddirtrubyconf.com"&gt;Red Dirt Rubyconf&lt;/a&gt;&lt;/h1&gt;
  &lt;p&gt;
    I posted my slides from red dirt rubyconf. It's about the devops movement
    that's been gaining a lot of momentum in the sysadmin circle.  A lot of
    people at the conference asked me about the source of the images in the talk,
    they're from &lt;a href="http://blackandwtf.tumblr.com"&gt;blackandwtf.tumblr.com&lt;/a&gt;.
  &lt;/p&gt;
  &lt;div class="slideshare" style="width:425px" id="__ss_3995920"&gt;
    &lt;strong style="display:block;margin:12px 0 4px"&gt;
      &lt;a href="http://www.slideshare.net/atmosorg/rise-of-devops" title="Rise of devops"&gt;Rise of devops&lt;/a&gt;
    &lt;/strong&gt;
    &lt;object id="__sse3995920" width="425" height="355"&gt;
      &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=riseofdevops-100506105551-phpapp01&amp;rel=0&amp;stripped_title=rise-of-devops" /&gt;
      &lt;param name="allowFullScreen" value="true"/&gt;
      &lt;param name="allowScriptAccess" value="always"/&gt;
      &lt;embed name="__sse3995920" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=riseofdevops-100506105551-phpapp01&amp;rel=0&amp;stripped_title=rise-of-devops" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;
    &lt;/object&gt;
    &lt;div style="padding:5px 0 12px"&gt;
      View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/atmosorg"&gt;atmosorg&lt;/a&gt;.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;p&gt;
    Red dirt was a pretty damn good conference.  The format was different than
    I'm used to and I believe it worked out quite well.  It basically took 4
    speakers on similar subjects, the first speaker had a 30 minute talk, the
    last 3 each had 15 minute talks.  During the talks a moderator, 
    &lt;a href="http://twitter.com/jeg2"&gt;@jeg2&lt;/a&gt;, collected questions in the IRC
    back channel and the presenters would answer the questions after everyone
    finished their talks.  The location was good, the food was only second to
    &lt;a href="http://twitter.com/alohaonrails"&gt;@alohaonrails&lt;/a&gt;, and the vibe
    of the attendees was overwhelmingly positive.  The only negative thing I
    have to say is that the talks are going to be sold instead of shared, I'm a
    big fan of sharing.
  &lt;/p&gt;

  &lt;p&gt;
    I really wish conferences would just stream their talks and think of the
    conference as an experience for the attendees, making it more than just the
    talks that are valuable.
  &lt;/p&gt;
&lt;/div&gt;

</content>
 <feedburner:origLink>http://www.atmos.org/2010/05/07/red-dirt-ruby-conf-talk-on-devops.html</feedburner:origLink></entry>
 
 <entry>
   <title>My talk from Aloha On Rails</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/8E6KkG7H0RA/aloha-on-rails-talk.html" />
   <updated>2010-03-21T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2010/03/21/aloha-on-rails-talk</id>
   <content type="html">&lt;h1&gt;My Aloha on Rails talk&lt;/h1&gt;


&lt;iframe src="http://player.vimeo.com/video/10877889" width="400" height="300" frameborder="0"&gt;&lt;/iframe&gt;




&lt;p&gt;
  &lt;a href="http://vimeo.com/10877889"&gt;Everything I Know About Being an Open Source Hacker I Learned From Indie Hip Hop - Corey Donohoe&lt;/a&gt; from &lt;a href="http://vimeo.com/alohaonrails"&gt;Aloha on Rails&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.
&lt;/p&gt;

</content>
 <feedburner:origLink>http://www.atmos.org/2010/03/21/aloha-on-rails-talk.html</feedburner:origLink></entry>
 
 <entry>
   <title>SF bound and down, upcoming talks</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/TPb0vuDq6h4/sf-bound-and-down-upcoming-talks.html" />
   <updated>2009-08-22T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/08/22/sf-bound-and-down-upcoming-talks</id>
   <content type="html">&lt;h1&gt;SF bound and down&lt;/h1&gt;

&lt;p&gt;I&amp;rsquo;m moving again.  As much as I love Boulder, I&amp;rsquo;m moving to SF to be closer to
&lt;a href="http://engineyard.com"&gt;Engine Yard&lt;/a&gt;.  After years of telecommuting I find
myself wanting to work with people in person more and more.  Boulder is, and
probably will remain, &amp;lsquo;home&amp;rsquo; to me now.  I don&amp;rsquo;t want to leave but &lt;a href="http://joearnold.com"&gt;joe
arnold&lt;/a&gt; has really created an attractive environment in
SF and it&amp;rsquo;s the type of development environment I feel that I&amp;rsquo;ll learn a lot
from.  Boulder is probably the most inspirational place I&amp;rsquo;ve ever lived.  From
the spiritual folks to the athletes to the artists, the community is vibrant,
creative, and caring.  I&amp;rsquo;m really gonna miss it. :&amp;lsquo;(&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to be speaking at three conferences over the next few months so I
figured I&amp;rsquo;d mention them here.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to be speaking at &lt;a href="http://rubyhoedown.com"&gt;the ruby hoedown&lt;/a&gt; in
August on &amp;ldquo;how to be simply awesome.&amp;rdquo;  It&amp;rsquo;s basically a run down of how
&lt;a href="http://github.com/halorgium"&gt;halorgium&lt;/a&gt; and I are winning on the regular.
Unfortunately I won&amp;rsquo;t be there for the full conference because I&amp;rsquo;m catching a
plane to Austin later that night.&lt;/p&gt;

&lt;p&gt;The next day in Austin I&amp;rsquo;ll be presenting at &lt;a
href="http://lonestarrubyconf.com/"&gt;Lone Star Ruby Conf&lt;/a&gt; on the same topic
with a slightly different title.  I&amp;rsquo;m hoping my connecting flights allow this
to happen because I&amp;rsquo;m pretty excited about the subject.  I just gave the talk
internally at EY and it needs a little work but I think I finally understand
how to present the topic to people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I&amp;rsquo;m speaking at &lt;a href="http://alohaonrails.com"&gt;a conference in HAWAII&lt;/a&gt;&lt;/strong&gt;,
aloha on rails.  I&amp;rsquo;m doing a talk on open source software and independent hip
hop label&amp;rsquo;s evolution over the last decade or so.  I&amp;rsquo;m gonna do my best to not
come off like a marketing douche bag, but I&amp;rsquo;m going to present a bunch of
similarities between open source craftsmanship and successful indie rappers.
You should go come!  I&amp;rsquo;m hoping to get some surfing in, let me know if you&amp;rsquo;re
interested!&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/08/22/sf-bound-and-down-upcoming-talks.html</feedburner:origLink></entry>
 
 <entry>
   <title>hoptoad for rack</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/SJb7Cbh3UmE/hoptoad-for-rack.html" />
   <updated>2009-05-15T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/05/15/hoptoad-for-rack</id>
   <content type="html">&lt;h1&gt;Rack Hoptoad&lt;/h1&gt;

&lt;p&gt;So &lt;a href="http://spork.in"&gt;Tim&lt;/a&gt; and I were talking about how we needed
&lt;a href="http://hoptoadapp.com"&gt;hoptoad&lt;/a&gt; for our rack apps the other day.  This &lt;a href="http://github.com/atmos/rack_hoptoad"&gt;rack
hoptoad notifier&lt;/a&gt; should get you going
for &lt;a href="http://github.com/rack/rack"&gt;rack&lt;/a&gt; and
&lt;a href="http://www.sinatrarb.com"&gt;sinatra&lt;/a&gt;.  Raise
&lt;a href="http://github.com/atmos/rack_hoptoad/issues"&gt;issues&lt;/a&gt; on github if you run into
problems. :D&lt;/p&gt;

&lt;p&gt;If all you want to do is install the gem you can install it like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;% sudo gem install rack_hoptoad&lt;/code&gt;&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/05/15/hoptoad-for-rack.html</feedburner:origLink></entry>
 
 <entry>
   <title>as time goes by : blabbing 'bout sinatra</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/cCUZHr71MUs/as-time-goes-by-blabbing-bout-sinatra.html" />
   <updated>2009-05-15T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/05/15/as-time-goes-by-blabbing-bout-sinatra</id>
   <content type="html">&lt;h1&gt;Sinatra 0.9&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://twitter.com/jsmestad"&gt;Justin Smestad&lt;/a&gt; invited me up to
&lt;a href="http://www.factorylabs.com/"&gt;factory labs&lt;/a&gt; to talk about
&lt;a href="http://sinatrarb.com"&gt;sinatra&lt;/a&gt; recently for one of their brown bag
lunches.  He recorded the talk from his laptop and I&amp;rsquo;m amazed you can see or
hear me.&lt;/p&gt;

&lt;p&gt;&lt;object width="400" height="300"&gt;
  &lt;param name="allowfullscreen" value="true" /&gt;
  &lt;param name="allowscriptaccess" value="always" /&gt;
  &lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=4650697&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;
  &lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=4650697&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;
  &lt;/embed&gt;
&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;My slides aren&amp;rsquo;t sync&amp;rsquo;d up but they&amp;rsquo;re here.&lt;/p&gt;

&lt;p&gt;&lt;a title="View Sinatra 0.9 - Corey Donohoe on Scribd" href="http://www.scribd.com/doc/15440443/Sinatra-09-Corey-Donohoe" style="margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block; text-decoration: underline;"&gt;
  Sinatra 0.9 &amp;ndash; Corey Donohoe
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;object id="doc_89742815376938" name="doc_89742815376938" height="500" width="100%" type="application/x-shockwave-flash" data="http://d1.scribdassets.com/ScribdViewer.swf" style="outline:none;" rel="media:document" resource="http://d1.scribdassets.com/ScribdViewer.swf?document_id=15440443&amp;access_key=key-1rytundm4w1pdeg41fow&amp;page=1&amp;viewMode=list" xmlns:media="http://search.yahoo.com/searchmonkey/media/" xmlns:dc="http://purl.org/dc/terms/"&gt;
  &lt;param name="movie" value="http://d1.scribdassets.com/ScribdViewer.swf" /&gt;
  &lt;param name="wmode" value="opaque" /&gt;
  &lt;param name="bgcolor" value="#ffffff" /&gt;
  &lt;param name="allowFullScreen" value="true" /&gt;
  &lt;param name="allowScriptAccess" value="always" /&gt;
  &lt;param name="FlashVars" value="document_id=15440443&amp;access_key=key-1rytundm4w1pdeg41fow&amp;page=1&amp;viewMode=list" /&gt;
  &lt;embed id="doc_89742815376938" name="doc_89742815376938" src="http://d1.scribdassets.com/ScribdViewer.swf?document_id=15440443&amp;access_key=key-1rytundm4w1pdeg41fow&amp;page=1&amp;viewMode=list" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="500" width="100%" wmode="opaque" bgcolor="#ffffff"&gt;
  &lt;/embed&gt;
&lt;/object&gt;&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/05/15/as-time-goes-by-blabbing-bout-sinatra.html</feedburner:origLink></entry>
 
 <entry>
   <title>Hancock-Client-Rails : Using Sinatra/Rack Middleware in Rails</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/rPWk7cJvrMU/hancock-client-rails-using-sinatrarack-middleware-in-rails.html" />
   <updated>2009-03-23T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/03/23/hancock-client-rails-using-sinatrarack-middleware-in-rails</id>
   <content type="html">&lt;h1&gt;Hancock-Client-Rails: Works with Rails &gt; 2.3.x&lt;/h1&gt;

&lt;p&gt;Recently I&amp;rsquo;ve been writing a bunch about &lt;a href="http://sinatrarb.com"&gt;sinatra&lt;/a&gt; as middleware and one of the things you always hear people glorifying is how rack middleware can be dropped into any framework that&amp;rsquo;s built on rack.  Since I&amp;rsquo;m trying to get people to try &lt;a href="http://github.com/atmos/hancock"&gt;hancock&lt;/a&gt; out, or atleast learn something from it, I figured I should investigate how you actually use the &lt;a href="http://github.com/atmos/hancock-client"&gt;hancock-client&lt;/a&gt; sinatra app inside off rails 2.3.2.&lt;/p&gt;

&lt;p&gt;One of the examples I&amp;rsquo;ve seen in quite a few presentations on using middleware in rack has something along the lines of:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090323-m4hba3yiqxdsupf389t8fxt4i3.jpg" alt="middleware" /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, I&amp;rsquo;ve yet to get a sample like this working with sinatra middleware.  For some reason sinatra always throws 404 errors instead of allowing those requests to pass through to rails.  Even if I set &amp;ldquo;disable :raise_errors&amp;rdquo; in my sinatra app, it&amp;rsquo;d still throw 404s.  So after a little googling I discovered a wonderful write up over at the &lt;a href="http://guides.rubyonrails.org/rails_on_rack.html"&gt;rails on rack&lt;/a&gt; page.  I definitely learned a lot about how rails middleware works but I still couldn&amp;rsquo;t get my sinatra app functioning properly inside of rails.&lt;/p&gt;

&lt;p&gt;I was kind of surprised to find out that there was very little documentation on using sinatra as middleware.  Sinatra is awesome for this, how could I be the first person trying to do this?  It turns out that I wasn&amp;rsquo;t. :)  &lt;a href="http://blog.ra66i.org/"&gt;Raggi&lt;/a&gt; had explained how to do this to someone in #rack on freenode a few days earlier.  I looked through his &lt;a href="http://gist.github.com/81199"&gt;gist on how he did it&lt;/a&gt;.  I didn&amp;rsquo;t understand it all but I hadn&amp;rsquo;t tried using the metal generator that rails introduced recently.  So I gave that a try and ended up with a piece of rails metal that looks like this.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090323-bw211t8spchuk6hu6tmxp7qu94.jpg" alt="hancock metal" /&gt;&lt;/p&gt;

&lt;p&gt;This actually worked perfectly for me.  All I needed to do was make a subclass of Hancock::Client::Default and set the appropriate configuration options.  Next I gave myself a little helper in application.rb to check whether I was logged in or not, you&amp;rsquo;ve probably done something like this in every other app you&amp;rsquo;ve ever used.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090323-d1qrceyie3xme7ktf54sqccd28.jpg" alt="logged_in helper" /&gt;&lt;/p&gt;

&lt;p&gt;Then there&amp;rsquo;s a simple controller that should be protected by the SSO middleware.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090323-nhhtb1wb9j6b6xb38b25347b6b.jpg" alt="protected controller action" /&gt;&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s pretty much it, hopefully this will save you some time.  One thing that I&amp;rsquo;ve noticed in trying to make this work with the larger frameworks is that I really want some sort of implicit before filter.  I&amp;rsquo;d really like to have the redirect to &amp;lsquo;/sso/login&amp;rsquo; happen anytime an unauthenticated request comes in,  I&amp;rsquo;ll try to get that working in the next release.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve created an &lt;a href="http://github.com/atmos/hancock-client-rails"&gt;example application&lt;/a&gt; that I&amp;rsquo;m hoping to keep up to date as hancock grows.  There are git tags that match up to a hancock release number as well.  If you want to see a rails client in action you can run &amp;ldquo;rake features&amp;rdquo; inside of the hancock-client-rails application.  You&amp;rsquo;ll need to be on a mac due to the &lt;a href="http://github.com/redsquirrel/safariwatir/tree/master"&gt;safariwatir&lt;/a&gt; constraint but it should drive your browser and complete a full handshake against the &lt;a href="http://hancock.atmos.org"&gt;hancock sso sandbox&lt;/a&gt;.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/03/23/hancock-client-rails-using-sinatrarack-middleware-in-rails.html</feedburner:origLink></entry>
 
 <entry>
   <title>Hancock-Client : Sinatra Middleware</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/1JBGQr6Zeis/hancock-client-sinatra-middleware.html" />
   <updated>2009-03-22T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/03/22/hancock-client-sinatra-middleware</id>
   <content type="html">&lt;h1&gt;Hancock-Client: Middleware&lt;/h1&gt;

&lt;p&gt;With the release of &lt;a href="http://sinatrarb.com"&gt;sinatra&lt;/a&gt; version 0.9.1, programmers have the option to write micro-apps that double as middleware in any other &lt;a href="http://github.com/chneukirchen/rack/tree/master"&gt;rack&lt;/a&gt; enabled application.  The beauty in this is that you can write rack middleware without getting bogged down in the details of writing rack directly.  Perhaps it&amp;rsquo;s your first time leveraging rack and you want to test the waters or perhaps you&amp;rsquo;re just wanting to slap a little bit of functionality onto someone else&amp;rsquo;s code; sinatra is emerging as a great way for folks to start really sinking their teeth into how rack functions.&lt;/p&gt;

&lt;p&gt;I recently found myself waist-deep in rack.  A lot of my co-workers at &lt;a href="http://engineyard.com"&gt;EY&lt;/a&gt; have been telling me for some time where rack made sense and where it didn&amp;rsquo;t.  I didn&amp;rsquo;t really grasp it all.  I understood it as a concept but there was nothing in my day to day work that made me say &amp;ldquo;Hey!  I&amp;rsquo;m gonna use rack here!&amp;rdquo;  At least until the other day.  &lt;a href="http://mwrc2009.confreaks.com/13-mar-2009-11-05-in-a-world-of-middleware-who-needs-monolithic-applications-jon-crosby.html"&gt;Jon Crosby rocked out with a great talk at MWRC&lt;/a&gt; and one of &lt;a href="http://github.com/abcde"&gt;my friends at work&lt;/a&gt; had written a little sinatra app that we needed to merge into our Single Sign On(SSO) infrastructure.  &lt;a href="http://github.com/halorgium"&gt;Tim&lt;/a&gt; took advantage of an existing rack &lt;a href="http://openid.net"&gt;openid&lt;/a&gt; library and made the necessary modifications to hook it in cleanly, he then went on vacation and left the gem abstraction to me.  I&amp;rsquo;m really grateful for this because it really made me sit down and acquaint myself with sinatra.  What I found was something pleasurable, elegant, and useful.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://github.com/atmos/hancock-client"&gt;hancock-client&lt;/a&gt; gem is an abstraction of our rack based SSO middleware in use at Engine Yard but modified to communicate with the &lt;a href="http://github.com/atmos/hancock/"&gt;hancock sso server&lt;/a&gt;.  The gem provides a sinatra application that can be run as a standalone application or used as middleware in &lt;a href="http://rubyonrails.org"&gt;rails&lt;/a&gt; or &lt;a href="http://merbivore.org"&gt;merb&lt;/a&gt;.  The application itself encompasses all of the logic required to negotiate the SSO protocol with a provider and populate session variables.  You can pretty much expect that the sinatra app provided by the hancock-client gem will integrate well with a hancock provider of the same version.&lt;/p&gt;

&lt;p&gt;So when I started trying to get the middleware going I decided on three things that were necessary for it:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;you need to be able to login&lt;/li&gt;
    &lt;li&gt;you need to be able to logout&lt;/li&gt;
    &lt;li&gt;after you login you should be greeted&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This makes sense for the simplest possible consumer that does something useful.  The &lt;strong&gt;login&lt;/strong&gt; and &lt;strong&gt;logout&lt;/strong&gt; actions are mapped to &lt;strong&gt;/sso/login&lt;/strong&gt; and &lt;strong&gt;/sso/logout&lt;/strong&gt; respectively.  Does the &amp;ldquo;after you login you should be greeted&amp;rdquo; step really make sense for middleware though?  I feel like the answer is no in this situation and it&amp;rsquo;s where the beauty of rack really comes to light.  Since my code shares the same rack session that my framework code will share, maybe I should leave that greeting page up to the app that&amp;rsquo;s using the middleware.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090323-b69yget8ijmcs35ys8eqmsd1y4.jpg" alt="Middleware" /&gt;&lt;/p&gt;

&lt;p&gt;The SSO middleware handles the authentication earlier in the stack than your framework and all you need to do is rely on a set of conventions that the middleware provides to the framework layer.  In the case of hancock-client it sets the &lt;strong&gt;:user_id&lt;/strong&gt; session variable.  Depending on your middleware ordering this happens way before your framework is hit.  The basic approach for the initial release of hancock-client went something like this, &amp;ldquo;only implement login and logout but provide examples of how you might use it in your framework of choice.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;What we created was a class that inherited from &lt;strong&gt;Sinatra::Default&lt;/strong&gt; called &lt;strong&gt;Hancock::Client::Default&lt;/strong&gt;.  This class was created with the idea that an application developer would inherit from it and implement the greeting page at &amp;ldquo;&lt;strong&gt;/&lt;/strong&gt;&amp;rdquo;.  So in its simplest form you can implement a hancock-client app in the following fashion:&lt;/p&gt;

&lt;script src="http://gist.github.com/83061.js"&gt;&lt;/script&gt;


&lt;p&gt;Notice how the middleware can be extended to support requests to &lt;strong&gt;/&lt;/strong&gt; in sinatra with ease and you can simply let those requests pass through in frameworks that implement them at a higher level.&lt;/p&gt;

&lt;p&gt;Notice the usage of the configuration option &lt;strong&gt;sso_url&lt;/strong&gt;.  You need to set this to the url of your SSO server.  If you ever need to reference this in the markup it&amp;rsquo;s available as &lt;strong&gt;options.sso_url&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re using this as middleware in other frameworks you&amp;rsquo;ll have to make sure that you set &lt;strong&gt;disable :raise_errors&lt;/strong&gt; on your &lt;strong&gt;Hancock::Client::Default&lt;/strong&gt; subclass.  Otherwise you&amp;rsquo;ll get 404s and that&amp;rsquo;s kind of annoying.  Checkout &lt;a href="http://blog.ra66i.org/"&gt;raggi&lt;/a&gt;&amp;rsquo;s &lt;a href="http://gist.github.com/81199"&gt;gist&lt;/a&gt; too.&lt;/p&gt;

&lt;p&gt;Believe it or not, the standalone sinatra apps are hella useful.  I love when we want to try out some new 3rd party application that offers remote authentication and we can hook the two apps up with a simple sinatra app in no time.  Seriously, &lt;strong&gt;do not disregard sinatra&lt;/strong&gt; as a possible solution because you think you might need big feature X in framework Y.  Maybe you shouldn&amp;rsquo;t extend that monolith app that&amp;rsquo;s getting more complex by the day.  Maybe some micro-apps will be just what the doctor ordered. I might be crazy or living some sheltered developer lifestyle, but it is a pleasure to write sinatra code.&lt;/p&gt;

&lt;p&gt;If you investigate the tests in hancock-client you&amp;rsquo;ll find that there aren&amp;rsquo;t many unit tests.  I think there&amp;rsquo;s 2 and one is currently pending.  If you checkout the cucumber tests though you&amp;rsquo;ll find &lt;a href="http://safariwatir.rubyforge.org/"&gt;safariwatir&lt;/a&gt; tests that drive your browser and test against the &lt;a href="http://hancock.atmos.org"&gt;hancock sso sandbox&lt;/a&gt;.  All you need to do is investigate the &lt;strong&gt;&lt;a href="http://github.com/atmos/hancock-client/blob/master/examples/dragon/config.ru"&gt;examples/dragon&lt;/a&gt;&lt;/strong&gt; directory in hancock-client and run the following command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;% rackup -p 4567 config.ru&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In another terminal you should be able to run the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;% rake features&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A browser should appear, you should see that you successfully signed up for an SSO account, and that your consumer application has access to a few session variables.  I chose safariwatir in this case because it allowed me to blackbox test the appserver and I chose cucumber because I was pretty sure I could copy this functionality over to merb and rails as I created examples for those frameworks.  If you&amp;rsquo;re on a mac, please try to run these specs and let me know if they work for you.&lt;/p&gt;

&lt;p&gt;One thing that I&amp;rsquo;m really hoping to handle in the next release is the ability to make the SSO before filters in rails/merb a thing of the past.  I actually need to get the merb example working&amp;hellip;  If any of this interests you, you&amp;rsquo;re welcome to fork my projects on github or hook me up with patches.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/03/22/hancock-client-sinatra-middleware.html</feedburner:origLink></entry>
 
 <entry>
   <title>Hancock : A Single Sign On Server in Sinatra</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/hyFxMbCzzX8/hancock-a-single-sign-on-server-in-sinatra.html" />
   <updated>2009-03-20T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2009/03/20/hancock-a-single-sign-on-server-in-sinatra</id>
   <content type="html">&lt;h1&gt;Hancock: SSO&lt;/h1&gt;

&lt;p&gt;A while back I blogged about the &lt;a href="http://github.com/atmos/flatirons"&gt;flatirons&lt;/a&gt; &lt;a href="http://openid.net"&gt;openid&lt;/a&gt; provider and how it was inspired by something we were doing at Engine Yard.  We needed a single sign on provider and chose to use OpenID as the sso protocol.  Since this is heavily influenced by openid I will often use the word &amp;ldquo;&lt;strong&gt;provider&lt;/strong&gt;&amp;rdquo; to describe an SSO server.  I also use the word &amp;ldquo;&lt;strong&gt;consumer&lt;/strong&gt;&amp;rdquo; to describe an SSO enabled application.&lt;/p&gt;

&lt;p&gt;So we pretty much drew up a diagram of how openid works and removed the steps we felt were unnecessary(decision/acceptance steps).  We then extended it by adding auto discovery of the openid url.  Here&amp;rsquo;s a somewhat up to date diagram that shows off how things work.  You&amp;rsquo;ll notice that the user-agent(browser) never specifies its identity url, it&amp;rsquo;s automatically provided from the SSO server.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20090305-be6wwmbc4gfsi9euy3w7np31mm.jpg" alt="hancock sso handshake" height="500px" width="475px" /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m pleased to announce a new piece of software that might interest you if you need a single sign on solution for your projects.  It&amp;rsquo;s called &lt;a href="http://github.com/atmos/hancock"&gt;hancock&lt;/a&gt; and it&amp;rsquo;s available(like all good things) on &lt;a href="http://github.com"&gt;github&lt;/a&gt;.  Here&amp;rsquo;s a quick run down of what it offers you:&lt;/p&gt;

&lt;ul&gt;    &lt;li&gt;a rubygem that provides all the functionality you need for an sso server&lt;/li&gt;
    &lt;li&gt;an sso server as an extendable sinatra app, aka rack middleware&lt;/li&gt;
    &lt;li&gt;a required whitelist for consumer application access&lt;/li&gt;
    &lt;li&gt;configurable sreg response parameters to customize what information is exposed to clients&lt;/li&gt;
    &lt;li&gt;can hook into anything that &lt;a href="http://datamapper.org"&gt;datamapper&lt;/a&gt; supports as a user/consumer store.&lt;/li&gt;
    &lt;li&gt;trivial deployment as a rack application under passenger&lt;/li&gt;
    &lt;li&gt;simple user signup with email verification&lt;/li&gt;
        &lt;li&gt;application sessions don't overlap by using .domain.com style cookies&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This is all implemented in about 400 lines of ruby code using the &lt;a href="http://sinatrarb.com"&gt;sinatra&lt;/a&gt; framework.  With the release of Sinatra 0.9.1.1 programmers can write sinatra applications in a more modular fashion.  The killer feature is that these modular applications are actually &lt;a href="http://github.com/chneukirchen/rack/tree/master"&gt;rack&lt;/a&gt; applications.  This allows for services to be written in sinatra that can be deployed as either a standalone rack application or used as middleware in frameworks like merb or rails.  Hancock is an example standalone rack application.  I&amp;rsquo;ll be blogging about sinatra as middleware in the days to come.&lt;/p&gt;

&lt;p&gt;Hancock requires that you provide atleast three things to get it going.  This is normally provided in your rackup file.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;database connection info, specifically the &lt;a href="http://datamapper.org/doku.php?id=getting_started_with_datamapper#specify_your_database_connection"&gt;datamapper connect string&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;mailer info&lt;/li&gt;
    &lt;li&gt;a custom layout file&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Hancock assumes that you&amp;rsquo;re going to provide the layout that gives your site its customized look and feel.  The hancock gem itself provides all of the forms for authentication.  If you&amp;rsquo;re going to be serving static assets like images, stylesheets, or javascript files you&amp;rsquo;ll also need to set the public attribute.  Here&amp;rsquo;s what my rackup file looks like on my server.&lt;/p&gt;

&lt;script src="http://gist.github.com/82625.js"&gt;&lt;/script&gt;


&lt;p&gt;That&amp;rsquo;s your whole app.&lt;/p&gt;

&lt;p&gt;The Hancock gem provides a sinatra application as a class named &lt;strong&gt;Hancock::App&lt;/strong&gt;.  You should inherit from this class and implement a landing page at &amp;ldquo;&lt;strong&gt;/&lt;/strong&gt;&amp;rdquo;.  The mailer configuration functions a lot like the merb-mailer gem, if you&amp;rsquo;re having issues google around for merb-mailer help.&lt;/p&gt;

&lt;p&gt;The Hancock gem also provides a class named &lt;strong&gt;Hancock::Consumer&lt;/strong&gt; that represents a consumer application that is to be accepted by your hancock application.  The &lt;strong&gt;:url&lt;/strong&gt; attribute MUST match up to the return_to parameter in the openid negotiation.  If you&amp;rsquo;re using the &lt;a href="http://github.com/atmos/hancock-client"&gt;hancock-client&lt;/a&gt; gem then it should take care of this for you.  The main thing to remember about this class is that if you ever receive the &lt;strong&gt;Forbidden&lt;/strong&gt; message on your SSO provider you should double check that the host is allowed to access the provider.&lt;/p&gt;

&lt;p&gt;Your user model is exposed as &lt;strong&gt;Hancock::User&lt;/strong&gt;.  Right now there is simple sign up through web forms.  If you want to test the provider without setting up the full email configuration then you should run your application in development mode.  When run under development mode the registration url that would normally be sent via email is embedded as a comment.  I found that it made it really easy to test.&lt;/p&gt;

&lt;p&gt;The Hancock gem doesn&amp;rsquo;t have perfect tests, but I&amp;rsquo;ll be damned if we aren&amp;rsquo;t shooting for it.  You&amp;rsquo;ll find both unit and acceptance tests done in &lt;a href="http://rspec.info"&gt;rspec&lt;/a&gt;, &lt;a href="http://github.com/brynary/rack-test"&gt;rack-test&lt;/a&gt;, &lt;a href="http://github.com/brynary/webrat"&gt;webrat&lt;/a&gt;, and &lt;a href="http://github.com/aslakhellesoy/cucumber"&gt;cucumber&lt;/a&gt;.  Even if you&amp;rsquo;re not interested in an SSO server the tests might help clarify a few things if you&amp;rsquo;re a testing junkie.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, the killer feature of sinatra 0.9.1.1 is that sinatra apps are modular rack applications.  While hancock is a pretty cool example of the power and simplicity of sinatra; its use as middleware in other frameworks is where I expect to see sinatra shine for the foreseeable future.  Even if you&amp;rsquo;re stuck on a never ending rails project with no chance of innovation in sight, go learn about rack.  I think you&amp;rsquo;ll be surprised where you can start leveraging it.  Besides, writing sinatra is &lt;strong&gt;fun&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So what good is a simple SSO server if you don&amp;rsquo;t have a super simple client library?  I bet if we did it as a &lt;a href="http://github.com/atmos/hancock-client"&gt;simple sinatra app&lt;/a&gt; then we could turn it into middleware.  Then we could hook our &lt;a href="http://github.com/atmos/hancock-client-rails"&gt;rails&lt;/a&gt; and &lt;a href="http://github.com/atmos/hancock-client-merb"&gt;merb&lt;/a&gt; apps up.  Yeah, that&amp;rsquo;d be sweet.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m gonna follow this up in the next few days with something covering the &lt;a href="http://github.com/atmos/hancock-client"&gt;hancock-client&lt;/a&gt; gem.  This gem provides a sinatra application that can be run standalone or as middleware in other apps.  I&amp;rsquo;ll prolly follow that up with two short articles on &amp;ldquo;how you get your middleware running in (rails|merb).&amp;rdquo;&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/03/20/hancock-a-single-sign-on-server-in-sinatra.html</feedburner:origLink></entry>
 
 <entry>
   <title>Considerations for Creating a Test Driven Ruby Project</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/D5JwzZRRQoE/considerations-for-creating-a-test-driven-ruby-project.html" />
   <updated>2009-02-01T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2009/02/01/considerations-for-creating-a-test-driven-ruby-project</id>
   <content type="html">&lt;h1&gt;Creating a TDD Ruby Project&lt;/h1&gt;

&lt;h2&gt;Where this comes from&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;d originally wanted to do something like &amp;ldquo;how our group at &lt;a
href="http://engineyard.com"&gt;EY&lt;/a&gt; specs things&amp;rdquo; but I feel like a lot of
these ideas extend beyond the merb/rspec/datamapper bubble we currently develop
in. When I went through the &lt;a href="http://integrityapp.com/"&gt;Integrity&lt;/a&gt;
source code a couple weeks ago I realized they were doing the same things, but
with &lt;a href="http://sinatra.github.com/"&gt;sinatra&lt;/a&gt;, &lt;a
href="http://github.com/jeremymcanally/context/tree/master"&gt;context&lt;/a&gt;, and &lt;a
href="http://github.com/jeremymcanally/matchy/tree/master"&gt;matchy&lt;/a&gt;.  I found
it really easy to understand the integrity test suite because it was setup in a
wonderfully sane manner.  I figured I&amp;rsquo;d share a few thoughts on it since I&amp;rsquo;d
like to see more projects testing things like this.  There&amp;rsquo;s nothing earth
shattering here,   In reality though, few projects I come across embrace
developers to collaborate and enhance.  If you &lt;strong&gt;consider&lt;/strong&gt; these
things while creating your project, I promise, you&amp;rsquo;ll be in a much better state
to collaborate.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a few things that stick out in my mind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="#readme"&gt;You should have a README that tells another developer how to get up and running&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#testing"&gt;You should really be testing, even if it's after the fact&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#naming_tests"&gt;Name Your Tests/Specs after what it does&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#mocks"&gt;Be able to toggle mocks and integration tests easily&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#github"&gt;Use GitHub&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#ci"&gt;How will this commit affect Continuous Integration?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;You should have a README that tells another developer how to get up and running&lt;/h2&gt;

&lt;p&gt;If some random person needs to add a feature or fix a bug in your software,
they&amp;rsquo;re prolly going to have to do some setup. Maintain this README. The
easier it is to get a system bootstrapped to start developing and enhancing the
software the better.  The old timers can send you a patch via email, the new
schoolers send you &lt;a href="http://github.com/guides/pull-requests"&gt;pull
requests&lt;/a&gt;.  Let other people do some of the work for you. Even &lt;a
href="http://twitter.com/drnic/statuses/952116463"&gt;Dr Nic&lt;/a&gt; thinks it&amp;rsquo;s a
good idea!&lt;/p&gt;

&lt;h2&gt;You should really be testing, even if it&amp;rsquo;s after the fact&lt;/h2&gt;

&lt;p&gt;I don&amp;rsquo;t care how fucking smart you are, software maintenance isn&amp;rsquo;t easy.  I&amp;rsquo;ve
seen folks argue that &lt;a
href="http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html"&gt;unit
testing is fail&lt;/a&gt;, I&amp;rsquo;m starting to agree when it comes to the web.  I&amp;rsquo;m
finding that if you&amp;rsquo;re actually writing tests as you&amp;rsquo;re completing user stories
you naturally exercise your models.  With a code coverage tool like &lt;a
href="http://eigenclass.org/hiki.rb?rcov"&gt;rcov&lt;/a&gt; you can really tell which
portions of your models are being exercised fully.  If you know your stuff then
you know that rcov coverage doesn&amp;rsquo;t really mean &lt;strong&gt;ALL&lt;/strong&gt; that much,
but it helps.  You can then use a mutator like &lt;a
href="https://github.com/ryansobol/heckle/tree/master"&gt;heckle&lt;/a&gt; or &lt;a
href="https://github.com/halorgium/boo_hiss/tree/master"&gt;boo hiss&lt;/a&gt; to cover
your ass for the rest of your cases.  We normally employ the mutators after
we&amp;rsquo;re happy with the state of the software, it helps us prepare for handling
weird errors in a more graceful manor.  You don&amp;rsquo;t have to go so far as to
running mutators on your code, but you should &lt;strong&gt;really really&lt;/strong&gt; be
testing.  If you don&amp;rsquo;t have time to test code, perhaps it&amp;rsquo;s time for you to
&lt;strong&gt;TAKE THE TIME&lt;/strong&gt; to learn how to do it.  Your co-workers and
friends will thank you for it, I promise.  Even if you develop software by
changing code and refreshing your browser or running your script over and over,
you owe it to your collaborators to let them know what portions of the code are
important and what will cause major breakage if it changes.  By not testing
you&amp;rsquo;re saying &amp;ldquo;I really don&amp;rsquo;t care whether or not this project lives a long,
happy life.&amp;rdquo;&lt;/p&gt;

&lt;h2&gt;Name Your Tests/Specs after what it does&lt;/h2&gt;

&lt;p&gt;At the first &lt;a href="http://railsconf.org"&gt;railsconf&lt;/a&gt; I remember &lt;a
href="http://twitter.com/srbaker"&gt;srbaker&lt;/a&gt; talking about rspec and how much
he hated the way rails generators generated test files.  He told me something
along the lines of &amp;ldquo;when I need to create a new spec I make it based on what
it&amp;rsquo;s for.&amp;rdquo;  I didn&amp;rsquo;t really understand him at the time, I was still learning
how to test via the rails framework.&lt;/p&gt;

&lt;p&gt;&lt;img title="Checkout the names" src="http://img.skitch.com/20090130-e75wm4neriiunbcc9k18dqk2n.jpg" alt="Integrity and Braintree TR Slice" width="554" height="503" /&gt;&lt;/p&gt;

&lt;p&gt;In the images above you can easily identify what functionality has tests.  It
annoys me to death when I open up spec/controllers/ and find specs named after
classes.  They might be empty or they might be a giant file testing all of the
functionality of the class in isolation, both cases suck.  I&amp;rsquo;m becoming more
and more fond of just creating a spec file for a user story as I implement it.
In the web space I think you should investigate &lt;a
href="http://github.com/brynary/webrat/tree/master"&gt;webrat&lt;/a&gt;, you can use it
with merb, sinatra, or rails.  You&amp;rsquo;re basically writing acceptance tests that&amp;rsquo;s
like a fake browser request with persistent sessions.  Name your acceptance
tests according to what they validate and you&amp;rsquo;ll be in business.&lt;/p&gt;

&lt;h2&gt;Be able to toggle mocks and integration tests easily&lt;/h2&gt;

&lt;p&gt;We recently did a bunch of stuff with &lt;a
href="http://dev.braintreepaymentsolutions.com/"&gt;braintree&lt;/a&gt; for some payment
processing.  They provide a pretty awesome &lt;strong&gt;&lt;a
href="http://dev.braintreepaymentsolutions.com/test-transaction/"&gt;test
environment&lt;/a&gt;&lt;/strong&gt; for you to test against.  I wrote a whole bunch of
specs that faked browser requests to the API server and I found their docs to
be incorrect.  Their examples worked but once I got down to requiring CVVs and
address verification, the response hashes came back inconsistently.  By really
testing the requests/responses  I was able to dm this &lt;a
href="http://twitter.com/ch0wda"&gt;really awesome ruby developer on twitter&lt;/a&gt;
and resolve the issue in a day or two, long before we ever went live.  If we&amp;rsquo;d
generated mocks based on the documentation alone we would&amp;rsquo;ve gone live with a
broken system.  You could argue that it&amp;rsquo;s braintree&amp;rsquo;s fault and they should
have correct documentation, but I&amp;rsquo;m not a big fan of finger pointing. Finger
pointing doesn&amp;rsquo;t accomplish a damn thing when you just launched a site and it&amp;rsquo;s
not completely functional.  We&amp;rsquo;ve started shooting for something along the
lines of &amp;ldquo;only mock things out if we can toggle a real integration test.&amp;rdquo;  Some
of our apps could really use some mocking help, but the speed hit isn&amp;rsquo;t really
that big of a deal when you know it&amp;rsquo;s really running against the remote
service.  Of course my friend Tim has some ideas about &lt;a
href="http://github.com/halorgium/mockz0r/tree/master"&gt;mocks&lt;/a&gt; too.&lt;/p&gt;

&lt;h2&gt;Use GitHub&lt;/h2&gt;

&lt;p&gt;I use &lt;a href="http://whygitisbetterthanx.com/"&gt;git&lt;/a&gt;, my homies at &lt;a
href="http://github.com"&gt;GitHub&lt;/a&gt; get it.  It&amp;rsquo;s all I&amp;rsquo;ve been using since
February of 2008.  I really can&amp;rsquo;t say enough good things about github, it
really simplifies things when collaborating on software.&lt;/p&gt;

&lt;h2&gt;How will this commit affect Continuous Integration?&lt;/h2&gt;

&lt;p&gt;You do use continuous integration, right?  Continuous Integration is just a
remote machine that runs your test suite every time someone pushes code.  I use
&lt;a href="http://integrityapp.com/"&gt;Integrity&lt;/a&gt;, some of my friends use &lt;a
href="http://cruisecontrolrb.thoughtworks.com/"&gt;cc.rb&lt;/a&gt;.  Integrity works
&lt;strong&gt;really frackin' well&lt;/strong&gt; with &lt;a
href="http://github.com/guides/post-receive-hooks"&gt;github&lt;/a&gt;, all of my code
lives there so it makes it that much more attractive.  If I push some code, how
will my CI task handle installing any new dependencies I introduced?  Will my
co-workers want to punch me in the face because half of their day was wasted
tracking down some shit I committed?  How well do these changes work outside of
my machine?  This is stuff that you really want to consider when you
collaborate.&lt;/p&gt;

&lt;h2&gt;Collaboration is King&lt;/h2&gt;

&lt;p&gt;Collaboration keeps bubbling to the surface here.  Perhaps I should change the
title.  These suggestions have little merit if you&amp;rsquo;re not interested in
collaborating on software.  If you&amp;rsquo;re not interested in collaborating on
software though, you&amp;rsquo;re going the way of the dodo.  Think of all the awesome
techniques you picked up from working with other people.  Think of all the
projects you tried to use or hack on but couldn&amp;rsquo;t because you couldn&amp;rsquo;t get it
working.  It&amp;rsquo;s up to you to make your projects easy to collaborate on.&lt;/p&gt;

&lt;p&gt;So, what&amp;rsquo;d I forget to mention?&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2009/02/01/considerations-for-creating-a-test-driven-ruby-project.html</feedburner:origLink></entry>
 
 <entry>
   <title>Merb and Rails Sitting in a Tree</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/i4JVSSjkUGM/merb-and-rails-sitting-in-a-tree.html" />
   <updated>2008-12-23T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2008/12/23/merb-and-rails-sitting-in-a-tree</id>
   <content type="html">&lt;h1&gt;Rails and Merb Merge&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://rubyonrails.org/merb"&gt;Ruby on Rails: Merb&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/"&gt;Rails and Merb Merge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Who&amp;rsquo;d have thought?  In case you didn&amp;rsquo;t know the two powerhouses in Ruby Frameworks are going to start working together to make the world a better place.  This brings up a lot of emotions for me and gives me hope for the community.&lt;/p&gt;

&lt;p&gt;4 years ago I spent my christmas holidays rewriting my php based weblog in rails, this new and crazy framework where you wrote less and did more.  At the time I was a Solaris administrator in Georgia and the programming job landscape was primarily Java, C#, and PHP.  I didn&amp;rsquo;t really want to write in those languages so I stuck to something I did enjoy, UNIX.  Over that holiday season though, I really fell for the Ruby language.  Not just the language but the community that surrounded rails at this time was nothing short of magical.  This was my first introduction to entrepreneurs in the web space and it seemed like every new person I met in this community was just awesome at life(and hacking).&lt;/p&gt;

&lt;p&gt;So rails took off and a lot of us got busy.  A lot of us wrote software that never saw the light of day, others wrote stuff that made the world take rails seriously.  I was lucky enough to be the first technical hire at &lt;a href="http://engineyard.com"&gt;Engine Yard&lt;/a&gt; and the growth that we&amp;rsquo;ve seen is inspirational.  Not only did we target the &amp;ldquo;premium rails hosting&amp;rdquo; market and excel at meeting and exceeding our customer&amp;rsquo;s expectations but we made it clear that we love the Ruby community.  We hired &lt;a href="http://blog.fallingsnow.net/"&gt;Evan Phoenix&lt;/a&gt; and &lt;a href="http://yehudakatz.com/"&gt;Yehuda Katz&lt;/a&gt; to push the ruby interpreter and the merb framework respectively despite the fact that there was no immediate financial benefit.&lt;/p&gt;

&lt;p&gt;So I&amp;rsquo;m sitting here avoiding work by writing this blog post, but I&amp;rsquo;m just so freaking excited by this merge.  I&amp;rsquo;m delighted to know that our community can still surprise me, that folks can work together, and the future of ruby in the websphere is looking good.&lt;/p&gt;

&lt;p&gt;Much respect to the merb and rails teams for making this happen.  Thanks, a lot.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/12/23/merb-and-rails-sitting-in-a-tree.html</feedburner:origLink></entry>
 
 <entry>
   <title>Merb 1.0 Controller Testing</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/uaZXLEdAJl0/merb-10-controller-testing.html" />
   <updated>2008-11-29T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2008/11/29/merb-10-controller-testing</id>
   <content type="html">&lt;h1&gt;Merb Request Testing Evolved&lt;/h1&gt;

&lt;p&gt;This was originally going to be part of &amp;ldquo;testing flatirons&amp;rdquo; but it got kinda
long and I felt it&amp;rsquo;d be most useful to community if I made it a standalone
article.  I&amp;rsquo;ve had the pleasure of experimenting with everything I cover in
this write-up, and the state of merb&amp;rsquo;s testing environment is getting better.
Since merb is at 1.0 these days this rundown should be valid for at least a few
more months.  I&amp;rsquo;m gonna run through what I know about how you test in merb, and
in the next few days I&amp;rsquo;ll dissect &lt;a href="http://github.com/atmos/flatirons"&gt;flatirons&lt;/a&gt;.
Here&amp;rsquo;s what I&amp;rsquo;ll be covering in this write up:&lt;/p&gt;

&lt;h3&gt;Request&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;dispatch_to&lt;/li&gt;
&lt;li&gt;get/post/put/delete&lt;/li&gt;
&lt;li&gt;request&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Requests with Authentication&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;dispatch_to / http verb tests&lt;/li&gt;
&lt;li&gt;requests w/ given blocks&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;RSpec Matchers FTW&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;have_selector&lt;/li&gt;
&lt;li&gt;have_xpath&lt;/li&gt;
&lt;li&gt;Roll Your Own&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;1.1 dispatch_to&lt;/h3&gt;

&lt;p&gt;This method allows you to unit test controllers.  It also makes your co-workers
cry, swear to kill you, and rewrite your code.&lt;/p&gt;

&lt;script src="http://gist.github.com/30271.js"&gt;
&lt;/script&gt;


&lt;p&gt;It seems harmless enough.  &lt;strong&gt;dispatch_to&lt;/strong&gt; takes 4 parameters and an optional
block.  The 3rd parameter is the actual params hash that the action will see.
The 4th is your http environment and how you modify things like HTTP_ACCEPT to
change content type.  When you call this method it instantiates the Class and
calls the Action with your http params, you bypass routing and have the option
to stub/mock to your heart&amp;rsquo;s content.  The response from &lt;strong&gt;dispatch_to&lt;/strong&gt;
returns an instance of the class, in this case it&amp;rsquo;s the Sessions controller.
The response also has a few instance methods that might be useful to check in
your testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;#status&lt;/strong&gt; &amp;ndash; the http response code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;#body&lt;/strong&gt; &amp;ndash; the document returned from the action&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;#headers&lt;/strong&gt; &amp;ndash; the http headers returned&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;#session&lt;/strong&gt;&amp;ndash; the session for the request&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In my experience &lt;strong&gt;dispatch_to&lt;/strong&gt; leads to really brittle tests when things
start to get a little more complex.  While I&amp;rsquo;m a &lt;strong&gt;HUGE&lt;/strong&gt; fan of
&lt;a href="http://github.com/btakita/rr"&gt;rr&lt;/a&gt;, I&amp;rsquo;m finding that mocks are mostly
complicating my day to day work. I wanna see my code work from beginning
to end, even if it means my test suite takes a little longer.  The merb-core
team advises against using &lt;strong&gt;dispatch_to&lt;/strong&gt;.  If you&amp;rsquo;re going to be using merb
for the foreseeable future, do not get in the habit of using this.  Seriously.&lt;/p&gt;

&lt;h3&gt;1.2 get/post/put/delete&lt;/h3&gt;

&lt;p&gt;The standard HTTP verbs are available as request helpers in your test
environment too.  It&amp;rsquo;s kinda like &lt;strong&gt;dispatch_to&lt;/strong&gt; but it actually goes through
the router.  Insted of giving a Class and an Action to call, you give the same
path you would request in a browser.  The optional 2nd and 3rd parameters to
this function are the request parameters and http environment respectively.
This also has a block syntax that you&amp;rsquo;ll see later in this tutorial.  Here&amp;rsquo;s
what the above request looks like using the HTTP verb helpers.&lt;/p&gt;

&lt;script src="http://gist.github.com/30274.js"&gt;
&lt;/script&gt;


&lt;p&gt;The response from &lt;strong&gt;get&lt;/strong&gt; / &lt;strong&gt;post&lt;/strong&gt; / &lt;strong&gt;put&lt;/strong&gt; / &lt;strong&gt;delete&lt;/strong&gt; has the same
instance methods available that &lt;strong&gt;dispatch_to&lt;/strong&gt; has since they both return the
actual controller that was executed.&lt;/p&gt;

&lt;p&gt;This is cooler than &lt;strong&gt;dispatch_to&lt;/strong&gt; because it goes through the router and we
can make sure that our pretty &amp;ldquo;/login&amp;rdquo; url is properly configured in the
router.&lt;/p&gt;

&lt;h3&gt;1.3 request&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;request&lt;/strong&gt; is short and sweet.  It&amp;rsquo;s a programmatic browser experience of
sorts.  At first glance it doesn&amp;rsquo;t seem much better than &lt;strong&gt;get&lt;/strong&gt;
but it actually preserves states between a series of requests.  We&amp;rsquo;ll see why
this kicks ass later in the tutorial.  Here&amp;rsquo;s how you display the login form
with the request helper.&lt;/p&gt;

&lt;script src="http://gist.github.com/30275.js"&gt;
&lt;/script&gt;


&lt;p&gt;The response from &lt;strong&gt;request&lt;/strong&gt; is a struct that provides the following instance
methods.  In general I try not to call these instance methods, it tends to be
more clean when you write &lt;strong&gt;matchers&lt;/strong&gt; against the response object itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;h1&gt;status &amp;ndash; the http response code&lt;/h1&gt;&lt;/li&gt;
&lt;li&gt;&lt;h1&gt;body &amp;ndash; the document returned from the action&lt;/h1&gt;&lt;/li&gt;
&lt;li&gt;&lt;h1&gt;headers &amp;ndash; the http headers returned&lt;/h1&gt;&lt;/li&gt;
&lt;li&gt;&lt;h1&gt;url &amp;ndash; the url that was requested&lt;/h1&gt;&lt;/li&gt;
&lt;li&gt;&lt;h1&gt;original_env &amp;ndash; i think this is how stuff persists between requests.  I&amp;rsquo;ve never actually called this for anything.&lt;/h1&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;2.0 Testing with Authentication&lt;/h2&gt;

&lt;h3&gt;2.1 merb-auth and all that jazz&lt;/h3&gt;

&lt;p&gt;So you&amp;rsquo;re supposed to be using merb-auth if you need authentication in your app.  So how do you test it?&lt;/p&gt;

&lt;h3&gt;2.2 dispatch_to and HTTP verbs with Authentication&lt;/h3&gt;

&lt;p&gt;Both &lt;strong&gt;dispatch_to&lt;/strong&gt; and &lt;strong&gt;get&lt;/strong&gt; can take an optional block that allows you to spec and mock things on the controller. If you need to
stub out authentication both helpers are easily spec&amp;rsquo;d like this.&lt;/p&gt;

&lt;script src="http://gist.github.com/30278.js"&gt;
&lt;/script&gt;


&lt;p&gt;While adding the mocks and stubs might yield some immediate results, it tends
to be a maintenance nightmare.  You either end up with a bunch of duplicated
stuff in each spec or you end up wrapping these methods with things like
employee_get/employee_put etc.&lt;/p&gt;

&lt;script src="http://gist.github.com/30280.js"&gt;
&lt;/script&gt;


&lt;p&gt;Even with this bit of abstraction it becomes a royal PITA to test real use
cases.  Since each spec tests the controller action in isolation you open
yourself up to the possibility of having bugs in your tests that are directly
related to keeping your mocks/specs synced up with your real code.  &amp;ldquo;Does the
signup process really work from start to finish?&amp;rdquo; &amp;ldquo;I don&amp;rsquo;t really know what
that chunk of code does, but I know it returns true or false.&amp;rdquo;  It becomes very
easy to bypass chunks of code in certain situations without really
understanding how things integrate.  The request helper shines bright in this
situation.&lt;/p&gt;

&lt;h3&gt;2.3 requests with given blocks&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;request&lt;/strong&gt; helper allows you to preserve the normal browser
experience by making successive calls to &lt;strong&gt;request&lt;/strong&gt; and
preserving the user session.  So here&amp;rsquo;s how you authenticate against merb-auth:&lt;/p&gt;

&lt;script src="http://gist.github.com/30281.js"&gt;
&lt;/script&gt;


&lt;p&gt;It sucks that you had to explicitly call that request to &amp;ldquo;/login&amp;rdquo; but it&amp;rsquo;s
kinda nice to be able to comprehend the user experience that led up to the
point where the code in question was tested.  Someone logged in and then they
could view their account settings.&lt;/p&gt;

&lt;p&gt;Either Merb or RSpec provide you with this &lt;strong&gt;given&lt;/strong&gt; block to
setup pre conditions that the spec relies on.  They&amp;rsquo;re kinda like
shared_examples but if you&amp;rsquo;re using &lt;strong&gt;request&lt;/strong&gt; you can build
entire use cases up and attach them to describe blocks.  Your session persists
between requests, instant WIN!  I added this to the bottom of my
&lt;strong&gt;spec/spec_helper.rb&lt;/strong&gt; to allow for authenticated requests.&lt;/p&gt;

&lt;script src="http://gist.github.com/30282.js"&gt;
&lt;/script&gt;


&lt;p&gt;After that your test code starts to look like this&lt;/p&gt;

&lt;script src="http://gist.github.com/30364.js"&gt;
&lt;/script&gt;


&lt;p&gt;If you&amp;rsquo;re super awesome you can pass &amp;ldquo;cookie jars&amp;rdquo; along with your requests to
restore certain states.  I think they&amp;rsquo;ll be really useful in situations where
specs start taking forever because of the amount of setup required to get to a
certain state.  Thus far our specs aren&amp;rsquo;t taking a long time so I guess I&amp;rsquo;ll
cross this bridge when our spec suite starts taking forever.&lt;/p&gt;

&lt;p&gt;One other thing to keep in mind is that your HTTP_HOST environmental variable
is http://example.org.  So don&amp;rsquo;t be surprised if you see this popping up in
your tests.&lt;/p&gt;

&lt;h2&gt;3. RSpec Matchers&lt;/h2&gt;

&lt;p&gt;Remember how both the &lt;strong&gt;dispatch_to&lt;/strong&gt; and &lt;strong&gt;request&lt;/strong&gt;
responses have a few instance methods that are useful in testing?  Notice that
we didn&amp;rsquo;t explicitly call them in any of the spec examples above?  It&amp;rsquo;s because
we&amp;rsquo;re using the rspec matchers that merb provides.  Not only should you be
using the ones that merb provides, you should be writing custom ones for your
app.  Here&amp;rsquo;s the matchers that I use from merb on a daily basis.&lt;/p&gt;

&lt;h3&gt;3.1 HTTP Response Checks&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;be_successful&lt;/strong&gt; This basically checks that response.status was 200.  It was a successful request. :D&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;redirect&lt;/strong&gt; This checks that response.status was 302.  It&amp;rsquo;s your normal HTTP redirect code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;redirect_to&lt;/strong&gt; This not only checks that response.status was 302 but it takes a string for the &lt;strong&gt;path&lt;/strong&gt; portion of the redirection.  If you need to check query parameters you&amp;rsquo;re going to have to write your own matcher.  We have one in one of our apps now, &lt;strong&gt;redirect_to_with_params&lt;/strong&gt; that does exactly this, we&amp;rsquo;re hoping to give it back to the merb community shortly.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Markup Validation&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;have_selector&lt;/strong&gt; is what you should be using to validate HTML markup.  It
allows you to specify &lt;a href="http://www.w3.org/TR/css3-selectors"&gt;CSS 3 Selectors&lt;/a&gt;
to identify the presence of certain markup.  If you&amp;rsquo;re into that
&lt;a href="http://jquery.com"&gt;jquery&lt;/a&gt; thing, it&amp;rsquo;s great practice for selectors
in js too.  Let&amp;rsquo;s say we want to check for the presence of the &amp;lsquo;Hello World&amp;rsquo;
string in the following example.&lt;/p&gt;

&lt;script src="http://gist.github.com/30365.js"&gt;
&lt;/script&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In your spec you&amp;rsquo;d have something like the following:&lt;/p&gt;

&lt;script src="http://gist.github.com/30366.js"&gt;
&lt;/script&gt;


&lt;p&gt;It&amp;rsquo;s pretty straightforward, find the div with an h2 that has the dom id of
&amp;lsquo;hello&amp;rsquo; and contains the string &amp;lsquo;Hello World&amp;rsquo;.  Now is a good time to review
the example specs above, hopefully you can visualize the markup that those
specs require now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;have_xpath&lt;/strong&gt; is the slightly older cousin of have_selector.  Instead of CSS 3
Selectors you specify an &lt;a href="http://www.w3.org/TR/xpath"&gt;xpath&lt;/a&gt; that should be
present in the response document.  I&amp;rsquo;ve gotten in the habit of only using this
for XML documents.  Let&amp;rsquo;s see the Hello World example done with xpath.&lt;/p&gt;

&lt;script src="http://gist.github.com/30367.js"&gt;
&lt;/script&gt;


&lt;h3&gt;3.3 Roll Your Own&lt;/h3&gt;

&lt;p&gt;Rolling your own RSpec matchers is the super pimp stuff.  You can cut down on
duplication in your tests by coming up with an expressive name for certain
situations, their responses, and the markup that&amp;rsquo;s returned. Here&amp;rsquo;s a little
matcher we wrote in flatirons that handles unauthenticated requests returned by
merb-auth.&lt;/p&gt;

&lt;script src="http://gist.github.com/30368.js"&gt;
&lt;/script&gt;


&lt;p&gt;We put this matcher into our spec/spec_helper.rb file and included it into our
rspec environment with the following code.&lt;/p&gt;

&lt;script src="http://gist.github.com/30369.js"&gt;
&lt;/script&gt;


&lt;p&gt;So that&amp;rsquo;s about it for the merb controller testing intro.  Now that we&amp;rsquo;ve
discussed the basics of testing we can get back into
&lt;a href="http://github.com/atmos/flatirons"&gt;flatirons&lt;/a&gt; and talk about how things are
tested in that app.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m sure I made some errors in here, please offer up corrections in the
comments and I&amp;rsquo;ll try to work the fixes into the article soonish.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/11/29/merb-10-controller-testing.html</feedburner:origLink></entry>
 
 <entry>
   <title>Flatirons : A Merb OpenID Provider Part 1</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/UXl8e-QC0X8/flatirons-a-merb-openid-provider-part-1.html" />
   <updated>2008-11-24T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2008/11/24/flatirons-a-merb-openid-provider-part-1</id>
   <content type="html">&lt;h1&gt;Flatirons OpenID Server&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://www.powerset.com/explore/semhtml/Flatirons?query=what+are+the+flatirons"&gt;What are the flatirons&lt;/a&gt;
you say?  They&amp;rsquo;re a rock formation near my house in Colorado, they look like
this in the winter.&lt;/p&gt;

&lt;p&gt;&lt;a class="tt-flickr tt-flickr-Medium"
href="http://flickr.com/photos/molas/62517813"&gt;&lt;img class="alignnone"
src="http://farm1.static.flickr.com/31/62517813_0d49863e68.jpg" alt=""
width="465" height="167" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also the name of the open source merb 1.0 based OpenID &lt;strong&gt;Provider&lt;/strong&gt; that&amp;rsquo;s
&lt;a href="http://github.com/atmos/flatirons/tree/master"&gt;available on github&lt;/a&gt;.
We recently started rolling out a customized OpenID &lt;strong&gt;Provider&lt;/strong&gt; for all of our
internal apps.  Flatirons was how I familiarized myself with the
OpenID &lt;a href="http://openid.net/specs/openid-authentication-2_0.html"&gt;spec&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;The Low Down&lt;/h1&gt;

&lt;p&gt;I&amp;rsquo;m going to break this into two parts, one on the OpenID &lt;strong&gt;Provider&lt;/strong&gt; and one
on the way we&amp;rsquo;re testing in merb 1.0.  There appears to be a lack of examples
on writing specs in the merb 1.0 world and I assure you it rocks way more than
it used to.  This part will give you a brief overview of what&amp;rsquo;s really involved
in the OpenID protocol.  Part 2 will cover testing the spec that&amp;rsquo;s described
here.&lt;/p&gt;

&lt;h1&gt;Paint a Perfect Picture&lt;/h1&gt;

&lt;p&gt;It&amp;rsquo;s not perfect, but it should give you an idea about the request/response
life cycle for an OpenID Authentication.  Keep in mind that &lt;strong&gt;User-Agent&lt;/strong&gt; in
these diagrams is normally a User&amp;rsquo;s browser.  A &lt;strong&gt;Consumer&lt;/strong&gt; is your new
micro-app that doesn&amp;rsquo;t even have a concept of user passwords.  The &lt;strong&gt;Provider&lt;/strong&gt;
is where flatirons comes into play, it&amp;rsquo;s the OpenID to Merb layer that allows
you to take advantage of merb-auth&amp;rsquo;s strategies.  The &lt;strong&gt;Auth Backend&lt;/strong&gt; is
trivial to customize, consult the &lt;a href="http://github.com/wycats/merb/tree/master/merb-auth"&gt;merb-auth&lt;/a&gt;
docs for more info.  Check it:&lt;/p&gt;

&lt;p&gt;&lt;a class="tt-flickr tt-flickr-Original"
href="http://www.flickr.com/photos/atmos/3054931483/"&gt;&lt;img
class="aligncenter"
src="http://farm4.static.flickr.com/3036/3054931483_b2d220624a.jpg"
alt="flatirons" width="465" height="500" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Identity Discovery&lt;/h1&gt;

&lt;p&gt;Identity Discovery is the first part of the &lt;strong&gt;User-Agent&lt;/strong&gt; authentication.
The &lt;strong&gt;Consumer&lt;/strong&gt; can request one of three options(&lt;a
href="http://openid.net/specs/openid-authentication-2_0.html#discovery"&gt;the
spec&lt;/a&gt;) but normally the &lt;strong&gt;Provider&lt;/strong&gt; sends back a Yadis document that lets
the &lt;strong&gt;Consumer&lt;/strong&gt; know where to go to start talking that crypto shit with the
&lt;strong&gt;Provider&lt;/strong&gt;.  This is normally in the form of an xrds+xml response.&lt;/p&gt;

&lt;h1&gt;Associate&lt;/h1&gt;

&lt;p&gt;This is where the magic starts.  &amp;ldquo;An association between the Relying Party
and the OpenID Provider establishes a shared secret between them, this is used
to verify subsequent protocol messages and reduce round trips.&amp;rdquo;(&lt;a
href="http://openid.net/specs/openid-authentication-2_0.html#associations"&gt;the
spec&lt;/a&gt;)  The &lt;strong&gt;Consumer&lt;/strong&gt; and the &lt;strong&gt;Provider&lt;/strong&gt; negotiate some Diffie-Hellman
keys and use these for communicating for the rest of the auth life-cycle.&lt;/p&gt;

&lt;h1&gt;Check ID Setup&lt;/h1&gt;

&lt;p&gt;Check ID Setup covers a few things, there&amp;rsquo;s a few modes that you should really
investigate in the &lt;a
href="http://openid.net/specs/openid-authentication-2_0.html#requesting_authentication"&gt;documentation&lt;/a&gt;
if you&amp;rsquo;re curious.  Suffice it to say there&amp;rsquo;s two interesting modes that are a
part of the id setup, &lt;strong&gt;checkid_setup&lt;/strong&gt; and &lt;strong&gt;immediate&lt;/strong&gt;.  &lt;strong&gt;Immediate&lt;/strong&gt; is
used less frequently and it&amp;rsquo;s designed for authenticating in a manner that
isn&amp;rsquo;t interactive(think ajax logins).  The &lt;strong&gt;checkid_setup&lt;/strong&gt; mode is way more
common, it involves normal http requests, redirects, and pages where you enter
your username and password.&lt;/p&gt;

&lt;h1&gt;Acceptance &amp;ndash; &amp;ldquo;Do you trust me?&amp;rdquo;&lt;/h1&gt;

&lt;p&gt;Acceptance is a form on the &lt;strong&gt;Provider&lt;/strong&gt; displaying the specific information
it&amp;rsquo;s going to send to the &lt;strong&gt;Consumer&lt;/strong&gt;.  The &lt;strong&gt;User-Agent&lt;/strong&gt; specifies whether
or not this information is OK to send to the &lt;strong&gt;Consumer&lt;/strong&gt;.  Normally users just
click OK here but this is where a full fledged &lt;strong&gt;Provider&lt;/strong&gt; allows you to pick
one of many identities you have stored there.&lt;/p&gt;

&lt;h1&gt;Identity Result&lt;/h1&gt;

&lt;p&gt;Once the &lt;strong&gt;User-Agent&lt;/strong&gt; accepts the &lt;strong&gt;Provider&lt;/strong&gt; as a trusted source, an
identity result is sent back to the &lt;strong&gt;Consumer&lt;/strong&gt; from the &lt;strong&gt;Provider&lt;/strong&gt;.  The
&lt;strong&gt;Consumer&lt;/strong&gt; can then take this response and do whatever local bootstrapping
they need to for the user.  OpenID can send back more than just the identity
URL, but flatirons doesn&amp;rsquo;t take advantage of these spec extensions yet.&lt;/p&gt;

&lt;h1&gt;WTF, Why do I even care?&lt;/h1&gt;

&lt;p&gt;Since this is based on &lt;strong&gt;merb-auth&lt;/strong&gt;, you have all of the strategies it
provides at your disposal.  Flatirons defaults to the salted password setup,
but you could easily hook this into whatever authentication backend that you
need.  If you&amp;rsquo;re considering Ruby applications and need single sign on then
this is a good starting point regardless of your user store.  In a trusted
environment you can make this even more simple, whitelisting can simplify the
request/response life-cycle by removing the &lt;strong&gt;Acceptance&lt;/strong&gt; step.  Depending on
your user store you can mask the interaction with the actual identity URL.
We&amp;rsquo;re able to mask the concept of the identity url a &lt;strong&gt;User-Agent&lt;/strong&gt; uses and we
just ask them for their email address.  Ours users don&amp;rsquo;t even know what OpenID
is, it rocks.&lt;/p&gt;

&lt;h1&gt;Where&amp;rsquo;s the Code&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://github.com/atmos/flatirons"&gt;It&amp;rsquo;s on github of course&lt;/a&gt;.  In the next
couple of days I&amp;rsquo;ll dissect the specs that validate the expectations defined
above.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/11/24/flatirons-a-merb-openid-provider-part-1.html</feedburner:origLink></entry>
 
 <entry>
   <title>Merb OpenID Consumer Application based on Merb-Auth</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/vzIfhWpwhF0/merb-openid-consumer-application-based-on-merb-auth.html" />
   <updated>2008-10-30T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2008/10/30/merb-openid-consumer-application-based-on-merb-auth</id>
   <content type="html">&lt;h1&gt;Merb OpenID Consumer&lt;/h1&gt;

&lt;p&gt;We&amp;rsquo;ve been playing around with &lt;a href="http://openid.net/"&gt;openid&lt;/a&gt; this week so I figured it was worth spending some time to test
&lt;a href="http://merbist.com/2008/10/29/yet-another-rc-release-merb-10-rc3/"&gt;the latest merb 1.0 rc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Say hello to the &lt;a href="http://github.com/atmos/merb-openid-example/tree/master"&gt;merb-openid-example&lt;/a&gt;
app.  It is a simple openid consumer application based on &lt;a href="http://github.com/wycats/merb/tree/master/merb-auth"&gt;merb-auth&lt;/a&gt;.  One
of merb-auth&amp;rsquo;s &lt;a href="http://github.com/wycats/merb/tree/master/merb-auth/merb-auth-more/lib/merb-auth-more/strategies/basic/openid.rb#L10"&gt;built in strategies is openid&lt;/a&gt;
, getting things going is simply a matter of enabling the appropriate
authentication strategies.&lt;/p&gt;

&lt;p&gt;This application is intended to run against merb 0.9.12(1.0rc4).  Here&amp;rsquo;s a
quick checklist of what was involved in getting merb-auth working with the
openid strategy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sudo gem install merb&lt;/li&gt;
&lt;li&gt;setup the merb-auth strategy&lt;/li&gt;
&lt;li&gt;add the &lt;strong&gt;openid&lt;/strong&gt; and &lt;strong&gt;signup&lt;/strong&gt; named routes&lt;/li&gt;
&lt;li&gt;modify the user model to handle openid attributes&lt;/li&gt;
&lt;li&gt;add the &lt;strong&gt;ensure_authenticated&lt;/strong&gt; filter&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;To setup merb I normally uninstall every trace of merb that&amp;rsquo;s on my system.
The 0.9.x branches tend to conflict if you have multiple merb versions
installed.  I tend to do the following(note it uninstalls ALL merb gems):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gem list merb | awk '/merb/ {print $1}' | xargs sudo gem uninstall -aI&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then I just install the merb meta package&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo gem install merb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Setting up the merb-auth strategy requires you to familiarize yourself with the
merb/merb-auth/strategies.rb file.  In a newly generated merb application this
file should setup a salted password base authentication scheme, we want to
change it so it looks like the following:&lt;/p&gt;

&lt;script src="http://gist.github.com/21213.js"&gt;
&lt;/script&gt;


&lt;p&gt;Next we need to setup two named routes that the openid auth strategy will use
in order to make the openid authentication happen.  I created a separate
controller(&lt;a href="http://github.com/atmos/merb-openid-example/tree/master/app/controllers/authentication.rb"&gt;authentication.rb&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;to handle these requirements.  All you really need to know about the two named
routes, &lt;strong&gt;openid&lt;/strong&gt; and &lt;strong&gt;signup&lt;/strong&gt;, is that &lt;strong&gt;signup&lt;/strong&gt; should not require
authentication and the &lt;strong&gt;openid&lt;/strong&gt; route should.&lt;/p&gt;

&lt;p&gt;The default user.rb that you get from merb-gen will need a few minor
adjustments to work with openid.  First you&amp;rsquo;ll have to add a few attributes if
you intend to cache them locally, and after that you&amp;rsquo;ll need to disable the
password validations that are automatically enabled by the salted password
strategy(even if you disabled it).  My user.rb looks like this.&lt;/p&gt;

&lt;script src="http://gist.github.com/21218.js"&gt;
&lt;/script&gt;


&lt;p&gt;Once all that&amp;rsquo;s done you should be able to just throw the before filter into
your &lt;a href="http://github.com/atmos/merb-openid-example/tree/master/app/controllers/application.rb"&gt;application.rb&lt;/a&gt;
and you&amp;rsquo;ll be ready to start using merb-auth with the openid strategy.&lt;/p&gt;

&lt;p&gt;The example application works outta the box, just run the merb command.  It
also has specs which show off a bug that still exists in rc4 where controllers
are &lt;strong&gt;not&lt;/strong&gt; honoring :only/:exclude parameters that are passed to
before filters.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d like for this to remain a simple app that we can keep as a community
example.  If this gets outta date please fork it and send me a pull request on
github.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/10/30/merb-openid-consumer-application-based-on-merb-auth.html</feedburner:origLink></entry>
 
 <entry>
   <title>Adding God to /etc/inittab on a Linux box</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/19ZbVkX8Imc/adding-god-to-etcinittab-on-a-linux-box.html" />
   <updated>2008-10-19T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2008/10/19/adding-god-to-etcinittab-on-a-linux-box</id>
   <content type="html">&lt;h1&gt;God is watching&lt;/h1&gt;

&lt;p&gt;We&amp;rsquo;ve been using monit at &lt;a href="http://www.engineyard.com"&gt;Engine Yard&lt;/a&gt;
on thousands of machines with a great deal of success.  Sometimes it can get
itself into a weird situation where it lets you down, but by far it does its
job exceptionally.  When I was setting up process monitoring for a merb app of
my own; the logging capabilities of monit really let me down. �I had weird
stuff happening because the environment was being cleared and I couldn&amp;rsquo;t track
down exactly WHY my merbs kept aborting.  So I gave�&lt;a
href="http://god.rubyforge.org"&gt;God&lt;/a&gt; a try and I really like it.  I run god
under init and here&amp;rsquo;s the basics for setting it up on an EY slice or any Linux
box for that matter.&lt;/p&gt;

&lt;h2&gt;Setting Things Up&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ensure that you&amp;rsquo;re on rubygems 1.3.0, older versions would load WAY too many things and it behaves like rubbish on most EY slices&lt;/li&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% gem install god&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% mkdir /etc/god&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% echo "God.load \"/etc/god/*.god\"" &amp;gt; /etc/god/god.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add the following two lines to /etc/inittab:
  god:345:respawn:/usr/bin/god -c /etc/god/god.config &amp;mdash;log-level error -D
  god0:06:wait:/usr/bin/god quit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% telinit q&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now all you have to do is drop god configs in /etc/god and you&amp;rsquo;re good to go.  You should be able to see some meaningful log output in /var/log/syslog.&lt;/p&gt;

&lt;h2&gt;But it leaks memory!?!&lt;/h2&gt;

&lt;p&gt;Some of my coworkers are still hesitant about it because of the memory
consumption and leaks they&amp;rsquo;ve seen.  I kill god once a day with a cron job. :)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0 0 * * * /usr/bin/killall -9 god&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;Comments&lt;/h2&gt;

&lt;p&gt;p.s. Anyone have a better god config for merb processes? Here&amp;rsquo;s &lt;a href="http://gist.github.com/17980"&gt;mine&lt;/a&gt;&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/10/19/adding-god-to-etcinittab-on-a-linux-box.html</feedburner:origLink></entry>
 
 <entry>
   <title>Merb Exception Notification with HopToad</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/EfV4y0UjW54/merb-exception-notification-with-hoptoad.html" />
   <updated>2008-10-09T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2008/10/09/merb-exception-notification-with-hoptoad</id>
   <content type="html">&lt;h1&gt;Exceptions&lt;/h1&gt;

&lt;p&gt;One of my frustrations over the past few months has been the lack of a quality exception notifier plugin for &lt;a href="http://merbivore.com"&gt;merb&lt;/a&gt;. The &lt;a href="http://github.com/newbamboo/merb_exceptions/tree/master"&gt;New Bamboo Merb Exceptions&lt;/a&gt; gem has been around for a while now, but it has been consistently broken or tailored to versions of merb that I&amp;rsquo;m not currently running.  So for the last few months we used a hacked version of new bamboo&amp;rsquo;s merb_exceptions in production, and it worked pretty well until the exception refactoring that went down in merb landed in mid-august. There&amp;rsquo;s a slightly more recent post on the &lt;a href="http://merbist.com/2008/10/01/exception-handling-in-merb/"&gt;Merbist&lt;/a&gt; about the merb_exceptions plugin being consumed into the official merb plugins repo, this is quite cool. :)&lt;/p&gt;

&lt;h2&gt;Call to Arms&lt;/h2&gt;

&lt;p&gt;Last night I saw a &lt;a href="http://twitter.com/benburkert/statuses/952186855"&gt;tweet&lt;/a&gt; by &lt;a href="http://benburkert.com/"&gt;benburkert&lt;/a&gt; about hoptoad.  I know Ben from the Merb/DM community and figured he had to be using hoptoad with merb.  &lt;a href="http://www.hoptoadapp.com/welcome"&gt;Hoptoad&lt;/a&gt; is an exception notifier/logger service provided by the good folks at &lt;a href="http://www.thoughtbot.com/"&gt;ThoughBot&lt;/a&gt;.  It&amp;rsquo;s kind of like a nice combination of the classic rails &lt;a href="http://svn.rubyonrails.org/rails/plugins/exception_notification/README"&gt;Exception Notifier&lt;/a&gt; and technoweenie/dreamer3&amp;rsquo;s &lt;a href="http://github.com/defunkt/exception_logger/tree/master"&gt;exception_logger&lt;/a&gt; plugin.  A quick search on &lt;a href="http://github.com"&gt;github&lt;/a&gt; revealed an existing &lt;a href="http://github.com/joakimk/hoptoad_notifier_merb/tree/master"&gt;merb plugin for hoptoad&lt;/a&gt;.  SCORE.&lt;/p&gt;

&lt;h2&gt;Problems&lt;/h2&gt;

&lt;p&gt;The downside was that this was written right when hoptoad was released, and the way that the Exceptions controller behaves changed(for the better) shortly after the initial plugin was released.  So I forked the repo and it took about 30 minutes to update the code to work with the version of merb we&amp;rsquo;re running(0.9.7).  I&amp;rsquo;ve sent a pull request to the author and I&amp;rsquo;m hoping he&amp;rsquo;ll consume my changes, but in the meantime you can grab it from &lt;a href="http://github.com/atmos/hoptoad_notifier_merb/tree/master"&gt;my public fork of the plugin&lt;/a&gt;.  I also updated the README to be a little more informative on how to get things going.
&lt;strong&gt;UPDATE&lt;/strong&gt;:
I went ahead and made the code a proper merb plugin w/ specs and such, it&amp;rsquo;s available &lt;a href="http://github.com/atmos/merb_hoptoad_notifier/tree/master"&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/10/09/merb-exception-notification-with-hoptoad.html</feedburner:origLink></entry>
 
 <entry>
   <title>Link to Unimplemented</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/zcr8TNWBaAE/link-to-unimplemented.html" />
   <updated>2008-09-30T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2008/09/30/link-to-unimplemented</id>
   <content type="html">&lt;h1&gt;link_to_unimplemented&lt;/h1&gt;

&lt;p&gt;I ran across &lt;a href="http://www.robbyonrails.com/articles/2008/03/27/tip-link-to-unimplemented"&gt;this post&lt;/a&gt;
&lt;a href="http://www.robbyonrails.com"&gt;Robby Russell&lt;/a&gt; a while back and really liked the
idea.  It reminded me a little bit of an older post by
&lt;a href="http://entp.com"&gt;Courtenay&lt;/a&gt; where he came up with the
&lt;a href="http://blog.caboo.se/articles/2007/3/29/tongue-in-cheek-icon-set"&gt;Tongue in Cheek Icon Set&lt;/a&gt;
The general idea is that you&amp;rsquo;re not done with the application, there&amp;rsquo;s
non-functional pieces of the UI that are at least partially exposed, and you
need to make sure the client knows that these things aren&amp;rsquo;t complete.&lt;/p&gt;

&lt;p&gt;In Robby&amp;rsquo;s post he implemented a simple javascript function that could be
called via a custom link helper.Nice and simple. Here&amp;rsquo;s the js:&lt;/p&gt;

&lt;script src="http://gist.github.com/13902.js"&gt;
&lt;/script&gt;


&lt;p&gt;And here&amp;rsquo;s the ruby to invoke it:&lt;/p&gt;

&lt;script src="http://gist.github.com/13903.js"&gt;
&lt;/script&gt;


&lt;p&gt;I&amp;rsquo;ve grown pretty fond of &lt;a href="http://jquery.com/"&gt;jquery&lt;/a&gt; since I spent
the better part of the year working with &lt;a href="http://yehudakatz.com"&gt;yehuda&lt;/a&gt; on a
merb app.  When I&amp;rsquo;d whip up some js in the style above he&amp;rsquo;d sit down with me
and show me how wrong I was.  So when I needed to actually use something like
&amp;lsquo;link to unimplemented&amp;rsquo; in my app last night I went about it in a slightly
different way.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s actually really simple.  You just attach an &amp;lsquo;unimplemented&amp;rsquo; class to any
anchor that you don&amp;rsquo;t want folks to follow.  It&amp;rsquo;s cool because you can attach
the real URL to the anchor and when the time comes to use it you simply remove
the class.  Here&amp;rsquo;s the js.&lt;/p&gt;

&lt;script src="http://gist.github.com/13907.js"&gt;
&lt;/script&gt;


&lt;p&gt;Here&amp;rsquo;s some haml taking advantage of it.&lt;/p&gt;

&lt;div class="thumbnail"&gt;
  &lt;a href="http://skitch.com/atmos/amw8/untitled.haml"&gt;
    &lt;img src="http://img.skitch.com/20080930-jmequreem78w49djyrj56w733.preview.jpg" alt="untitled.haml" /&gt;
  &lt;/a&gt;
  &lt;br /&gt;
&lt;/div&gt;


&lt;p&gt;So there it is.  A simple and effective way to keep clients from wandering to
the parts of your site that you really don&amp;rsquo;t want them visiting yet.&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2008/09/30/link-to-unimplemented.html</feedburner:origLink></entry>
 
 <entry>
   <title>Integrity : Continuous Integration</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/HBwIBcWfJOA/integrity-continuous-integration.html" />
   <updated>2008-09-26T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2008/09/26/integrity-continuous-integration</id>
   <content type="html">&lt;h1&gt;What's it all about?&lt;/h1&gt;




&lt;p&gt;
  I'm a big fan of &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt; Continuous Integration&lt;/a&gt; when writing software. However I've always found myself disappointed by the CI solutions that are floating around, namely &lt;a href="http://cruisecontrolrb.thoughtworks.com/"&gt;Cruisecontrolrb&lt;/a&gt;. Managing the processes can become a nightmare once you have a few projects running under it. At work I was recently tasked with revamping our on-again/off-again cruisecontrol setup and I thought to myself "there has got to be something better." It turns out there is, it's called &lt;a href="http://github.com/foca/integrity/tree/master"&gt;Integrity&lt;/a&gt;. Here's why I love this little piece of software.
&lt;/p&gt;


&lt;ul&gt;
  &lt;li&gt;works fine with github repos, public and private&lt;/li&gt;
  &lt;li&gt;emails me reliably so I don't have to check a web ui to know what's up&lt;/li&gt;
  &lt;li&gt;automatically works with the Post-Receive hooks github offers, including branch support&lt;/li&gt;
  &lt;li&gt;excellent test coverage, it's was at 100% last time I hacked on it&lt;/li&gt;
  &lt;li&gt;works off an sqlite3 database&lt;/li&gt;
  &lt;li&gt;keeps history of test runs&lt;/li&gt;
  &lt;li&gt;written in datamapper and sinatra&lt;/li&gt;
  &lt;li&gt;they've got lighthouse setup ( &lt;a href="http://integrity.lighthouseapp.com/projects/14308-integrity/overview"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Random Tidbits&lt;/h1&gt;


&lt;p&gt;The README on the integrity site is a great start, but here's a few extra things that we're using that you might be interested in.&lt;/p&gt;


&lt;h2&gt;Process Management&lt;/h2&gt;


&lt;p&gt;We're just running bin/integrity like the README says under &lt;a href="http://www.gnu.org/software/screen/"&gt;GNU Screen&lt;/a&gt;.  It hasn't crashed and doesn't seem to be leaking.&lt;/p&gt;


&lt;h2&gt;Private Repo Access&lt;/h2&gt;


&lt;p&gt;We're using &lt;a href="http://www.gentoo.org/proj/en/keychain/"&gt;keychain&lt;/a&gt; and github deploy keys to access our source code from crons and the ci process.&lt;/p&gt;


&lt;h2&gt;The Github Hooks are AWESOME&lt;/h2&gt;


&lt;p&gt;A lot of the time a simple CI setup will just 'svn up' or 'git pull' and run the latest version that it pulls down.  The github hooks actually send SHA1 hashes for each commit that a person makes.  If one of your co-workers bundles half a dozen commits and he broke the build in the middle, you'll be able to identify which commit caused the problem instead of reviewing each commit and possibly running them all yourself. �It's this easy:&lt;/p&gt;


&lt;ul&gt;
  &lt;li&gt;Click Edit on your github project(&lt;a href="http://atmos.org/photos/photo/2890620312/click-edit.html"&gt;example&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Enter your Post-Receive url(&lt;a href="http://atmos.org/photos/photo/2889784601/integrity-post-receive-setup.html"&gt;example&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Can it get any better?&lt;/h1&gt;


&lt;p&gt;I'd really like to see some async build process for Integrity, or perhaps some &lt;a href="http://devver.net/"&gt;devver&lt;/a&gt; integration.  It's a pretty solid product and it keeps improving.&lt;/p&gt;

</content>
 <feedburner:origLink>http://www.atmos.org/2008/09/26/integrity-continuous-integration.html</feedburner:origLink></entry>
 
 <entry>
   <title>iPhone pwns</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/cZYCLLD8DQs/iphone-pwns.html" />
   <updated>2007-07-03T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2007/07/03/iphone-pwns</id>
   <content type="html">&lt;h1&gt;iPhone pwns&lt;/h1&gt;
&lt;p&gt;So I contained myself all day on friday and didn&amp;#8217;t wait in line for an &lt;a href="http://www.apple.com/iphone/"&gt;iphone&lt;/a&gt;.  At about 6:45 I decided that I&amp;#8217;d go check out the closest AT&amp;amp;T store to see if I could get one.  I walked in and out in about 10 minutes with a 4GB model for the sane? price of 500$ US.  I went home, activated the thing, waited, waited and waited some more.  After about 2 hours I called support, &amp;#8220;i can has iphone?&amp;#8221; and they replied &amp;#8220;you can has iphone in 6 hours!&amp;#8221;  So I waited 6 hours, only able to slide the little touchscreen over to pretend like I really needed to make that emergency call.  After the 6 hours past I thought &amp;#8220;fuck this&amp;#8221; and went to sleep.  Needless to say I refreshed my email entirely too often for a while and my iphone(which was purchased on a friday) didn&amp;#8217;t work until Sunday morning.  Two days without a phone is kinda creepy in this day and age, especially when it has all sorts of nice features you wanna fuck with. :)&lt;/p&gt;
&lt;p&gt;All that other bullshit aside, it&amp;#8217;s &lt;strong&gt;fabulous&lt;/strong&gt;.  Everyone who takes my phone from me can figure it out.  I&amp;#8217;m delighted by the intuitive UI and the integration with my mac.  The keyboard took me a little bit of getting used to(I came from a blackberry), but that&amp;#8217;s the only thing I&amp;#8217;ve remotely struggled with.  Well done apple!  I don&amp;#8217;t feel like it was a waste of money, I&amp;#8217;m delighted with my purchase but I only wish it would&amp;#8217;ve started working sooner.&lt;/p&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2007/07/03/iphone-pwns.html</feedburner:origLink></entry>
 
 <entry>
   <title>I can has ... wolf dog?</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/ARMrvXFp0HY/i-can-has-wolf-dog.html" />
   <updated>2007-06-27T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2007/06/27/i-can-has-wolf-dog</id>
   <content type="html">&lt;p&gt;After getting &lt;a href="http://flickr.com/photos/atmos/sets/72157594425531384)"&gt;denali&lt;/a&gt;
around Christmas time last year, I really hadn&amp;rsquo;t planned on getting another dog
for a while.  Then I came back to Memphis and met a friend&amp;rsquo;s
&lt;a href="http://en.wikipedia.org/wiki/Wolf_hybrid"&gt;wolf hybrid&lt;/a&gt;.  He was a big beautiful four
year old dog and I found myself really wanting one.  I&amp;rsquo;m terribly impulsive
when it comes to things like this.  If I &lt;em&gt;really&lt;/em&gt; &lt;em&gt;really&lt;/em&gt; want something, I
usually figure out how to get it.  So I scoured the local papers and found a
breeder with 7 week old pups, one of which was a beautiful blue eyed little
girl cub.  This was a few days before &lt;a href="http://railsconf.org"&gt;Railsconf&lt;/a&gt; so I
figured I&amp;rsquo;d read up on them some more and make my final decision when I
returned.  At railsconf I ended up talking a handful of people&amp;rsquo;s ears off about
how beautiful and wonderful these wolf dogs were.  I think everyone thought I
was a little crazy when I&amp;rsquo;d describe my desire to have a wolf.  I even had an
&lt;a href="http://engineyard.com"&gt;Engine Yard&lt;/a&gt; client tell me &amp;ldquo;You look like the kinda
person who would own a wolf.&amp;rdquo;  I don&amp;rsquo;t really know if that&amp;rsquo;s a complement or
what&amp;hellip;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://flickr.com/photos/atmos/sets/72157600253032345/"&gt;&lt;img src="http://farm2.static.flickr.com/1019/561202741_7c39ea0ff4.jpg" alt="Cinderella" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is my new wolf dog .  She&amp;rsquo;s 7/8ths Arctic and Timber wolf and 1/8th
Husky, so she&amp;rsquo;s technically a &amp;lsquo;high content&amp;rsquo; wolf dog.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EVERYONE&lt;/em&gt; seems to have an opinion on this.  If only I had a dollar for every
genius who told me &amp;ldquo;you just gotta be the alpha&amp;hellip;&amp;rdquo;  Animal behavior,
especially psuedo-wild animals, is actually a hell of a lot more complicated
than just being &amp;lsquo;the alpha.&amp;rsquo;  So I&amp;rsquo;ve been reading a bunch to expose myself to
possible warning signs of behavioral problems and hopefully make the years to
come really easy for our pack. :)&lt;/p&gt;

&lt;p&gt;The silly thing is that I really didn&amp;rsquo;t find the resources that were most
informative until after I&amp;rsquo;d had Cindy for a week or two.  If you or anyone you
know is ever considering getting a wolf hybrid check out Nicole Wilde&amp;rsquo;s
&lt;a href="(http://www.amazon.com/gp/product/0966772644/ref=pd_cp_b_0/104-6472283-7606303?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=center-41&amp;amp;pf_rd_r=16DQ9XZ6RXHT9R99TZT8&amp;amp;pf_rd_t=201&amp;amp;pf_rd_p=252362401&amp;amp;pf_rd_i=0966772601"&gt;Living with Wolfdogs&lt;/a&gt;, it&amp;rsquo;s extremely informative.  If I&amp;rsquo;d read
that book before I got Cindy, I might not have gotten such a high content wolf
dog.  I am a little weary of what she&amp;rsquo;ll be like from about 10 months to 2
years, a lot of the &amp;lsquo;wolfy&amp;rsquo; behavior seems to come out  when they hit sexual
maturity.  Specifically I&amp;rsquo;m scared about a Cindy/Denali alpha bitch clash at
some point, I really should have gotten a male.  I also pretty much committed
myself to living in houses with 6 foot tall fences for the next 10-15 years,
apartments just won&amp;rsquo;t cut it.  There are just all of these little things you
have to keep an eye out for because, well, they&amp;rsquo;re not dogs. :(&lt;/p&gt;

&lt;p&gt;Anyway, she&amp;rsquo;s a simply wonderful little pup.  I&amp;rsquo;m doing daily &lt;a href="http://en.wikipedia.org/wiki/Clicker_training"&gt;clicker
training&lt;/a&gt; with her and
Denali(separately of course).  She&amp;rsquo;s got three labs to play with and a big back
yard.  She also gets to play with Hubble and Kioko practically every day.  I
really doubt socialization will be an issue with her.  Her flickr set will grow
in time, but probably not as quickly as she&amp;rsquo;s growing.  She&amp;rsquo;s 13 weeks now, and
I give her another 6-8 weeks before she&amp;rsquo;s bigger than Denali.  I&amp;rsquo;m definitely
have a shitload of fun with the dogs right now. :)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://flickr.com/photos/atmos/638761597/"&gt;&lt;img src="http://farm2.static.flickr.com/1405/638761597_e67970a4b9.jpg" alt="Sofa King" /&gt;&lt;/a&gt;&lt;/p&gt;
</content>
 <feedburner:origLink>http://www.atmos.org/2007/06/27/i-can-has-wolf-dog.html</feedburner:origLink></entry>
 
 <entry>
   <title>Moving at the Speed of Life</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/LSeAAkydDWY/moving-at-the-speed-of-life.html" />
   <updated>2007-05-03T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2007/05/03/moving-at-the-speed-of-life</id>
   <content type="html">&lt;p&gt;The last few weeks at &lt;a href="http://engineyard.com"&gt;Engine Yard&lt;/a&gt; have been fucking insane, seriously.  I can&amp;#8217;t remember the last time I was this stressed and tired regularly.  Come to think of it, the last time I was this tired and stressed was the last time I was a systems admin.  I&amp;#8217;m learning a bunch of new things, I&amp;#8217;m holding lots of developers hands while they get their apps out to the world, and I&amp;#8217;m constantly amazed by my coworkers knowledge.  I miss hacking terribly right now.  When I do finally pull myself away from work, I&amp;#8217;m usually trying to get as far away from the computer as possible.  Despite the stress, exhaustion, and lack of programming time, life is beautiful right now.  I&amp;#8217;m extremely happy with my life right now, that&amp;#8217;s not something I could say a year or two ago. :D&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve finally gotten out of Nashville for a considerably less wonderful city, Memphis.  I&amp;#8217;m going to miss so many things in that city, but getting out of the southeast is now a priority for me.  I&amp;#8217;m crashing with family(who fucking rock btw) for the next couple of months until I get everything settled for a move out west.  I&amp;#8217;m looking at Portland, the Engine Yard folks want me to look at San Francisco or Sacramento.  I&amp;#8217;m not sure where I&amp;#8217;ll end up but I&amp;#8217;ve got a month or two to figure it out.  I&amp;#8217;m really looking forward to &lt;a href="http://railsconf.org"&gt;Railsconf&lt;/a&gt; now, it&amp;#8217;ll give me a peek at Portland and it&amp;#8217;ll give me the opportunity to talk with some of my favorite hackers.&lt;/p&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2007/05/03/moving-at-the-speed-of-life.html</feedburner:origLink></entry>
 
 <entry>
   <title>Logrotate and Mongrel</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/YeCULVNJZ0Q/logrotate-and-mongrel.html" />
   <updated>2007-03-22T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2007/03/22/logrotate-and-mongrel</id>
   <content type="html">&lt;p&gt;If you&amp;#8217;ve been around webservers for a number of years you&amp;#8217;ve inevitably run into &lt;a href="http://www.linuxcommand.org/man_pages/logrotate8.html"&gt;logrotate&lt;/a&gt; at some point.  You set a tiny config file up and daily, weekly or monthly your logs get rotated out, compressed and optionally moved elsewhere for archiving.  It&amp;#8217;s pretty cool when your logs get chomped out into easily identifiable chunks.   You can think &amp;#8220;I need the logs from 2 days ago&amp;#8221; and you won&amp;#8217;t have to go sifting through &lt;strong&gt;all&lt;/strong&gt; of last week&amp;#8217;s logs in order to get to them.  Mongrel really isn&amp;#8217;t any different than any other webserver most people have dealt with, but logrotate and mongrel seems to be lacking proper documentation around the web.&lt;/p&gt;
&lt;p&gt;Everywhere I looked online I found stuff like &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/218107"&gt;this&lt;/a&gt; explaining how when more than one process are sharing logs files, ruby&amp;#8217;s built in log rotation falls flat on its face.  The answer to correct log rotation kept coming back to &amp;#8220;use logrotate&amp;#8221; but I couldn&amp;#8217;t find an example config to save my life.  So I mucked around with it for a bit.  The straightforward approach, moving the log outta the way and compressing it with logrotate, doesn&amp;#8217;t quite work because once the log file is moved out of the way the mongrels can&amp;#8217;t write to the new empty one.  This is easily solved with a postrotate task and a SIGUSR2 signal sent to mongrel.  So here it is, in all its glory, a logrotate task that you can prolly copy right over to your system and not waste time scouring the web for something that&amp;#8217;s really freakin simple.  It compresses files once a day, moves them to a subdirectory of the log dir called &amp;#8216;old&amp;#8217; and it keeps 28 days of back logs.&lt;/p&gt;
&lt;pre&gt;
/home/atmos/Sites/atmos.org/shared/log/*.log {
  daily
  missingok
  compress
  sharedscripts
  olddir old
  rotate 28
  postrotate
    for i in `ls /var/atmos.org/shared/log/*.pid`; do
      kill -USR2 `cat $i`
    done
  endscript
}
&lt;/pre&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2007/03/22/logrotate-and-mongrel.html</feedburner:origLink></entry>
 
 <entry>
   <title>Moving on ... to Engine Yard</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/tVEndckrNOw/moving-on-to-engine-yard.html" />
   <updated>2007-03-02T00:00:00-08:00</updated>
   <id>http://www.atmos.org/2007/03/02/moving-on-to-engine-yard</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m happy to report that I&amp;#8217;m going to start working with the good folks at &lt;a href="http://engineyard.com/"&gt;Engine Yard&lt;/a&gt; in 2 weeks.  I&amp;#8217;ll basically be trying to lighten the load that &lt;a href="http://brainspl.at"&gt;Ezra&lt;/a&gt; has been bearing by himself and learning all about how they&amp;#8217;re doing things over there.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m sad to report that I&amp;#8217;ll be leaving Centerstone in two weeks.  I started there just over a year ago and my life has changed so much in the last 12 months.  &lt;em&gt;Sooo Much&lt;/em&gt;.  I have a lot of respect for everyone on my team at Centerstone for various reasons, and I&amp;#8217;ll really miss all of them.  I&amp;#8217;m also giving notice 3 days before we go into user acceptance testing.  I know this is really going to hurt my team, but this was far too good of an opportunity to pass up.  I had a large leadership role there and am responsible for a lot of the good(and most of the bad) things in the system.  I got to help train and convert a Java shop to Rails and I got to grow immensely as a developer.&lt;/p&gt;
&lt;p&gt;Mixed feelings aside, I have a grin from ear to ear.&lt;/p&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2007/03/02/moving-on-to-engine-yard.html</feedburner:origLink></entry>
 
 <entry>
   <title>Phone Upgrade</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/Oph9sBoBu5k/phone-upgrade.html" />
   <updated>2006-09-08T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2006/09/08/phone-upgrade</id>
   <content type="html">&lt;p&gt;About a month ago my Blackberry 7290 quit getting reliable reception.  I&amp;#8217;d &lt;strong&gt;never&lt;/strong&gt; had any problems with the phone up until then and even when I was visiting Atlanta it wouldn&amp;#8217;t let me talk more than 45 seconds or so without dropping calls.  I took it into Cingular and they tried to get me to renew my service and get a more modern blackberry.  While the phone made a lot of sense while I was at GE, I really didn&amp;#8217;t need a wallet phone anymore.  So I went looking on ebay&amp;#8230;&lt;/p&gt;
&lt;p&gt;There were only two requirements, one of which I could deal without if I found the right phone.  Mainly I wanted something that worked well with my mac via bluetooth, and the other was a keyboard for text messaging(yes the blackberry spoiled me).  Most of my friends with Motorol Razrs hate them, and the other &amp;#8216;popular&amp;#8217; phones were either more than I wanted to spend or pushing features I didn&amp;#8217;t foresee myself using very often.  I remembered &lt;a href="http://redx.be"&gt;my friend Roy&lt;/a&gt; hyping up &lt;a href="http://www.reelintelligence.com/BluePhoneElite/"&gt;bluephoneelite&lt;/a&gt; a while back, so I looked at what phones would work well with it.  One of their well supported phones looked really dope, a &lt;a href="http://www.motorola.com/motoinfo/product/details.jsp?globalObjectId=66"&gt;Motorola A630&lt;/a&gt;.  I found one on ebay, brand new, for a little more than 100$.  Wow oh wow, I&amp;#8217;m absolutely hooked on bluephoneelite.  It&amp;#8217;s so dope when I get a phone call, the caller id is displayed on-screen, and my itunes pauses when I answer it.  It&amp;#8217;ll put my machine into screensaver mode and shuts off itunes when I walk out of range.  Equally cool is when it starts it back up when I walk back in range. :)  They&amp;#8217;re really really simple interactions with my computer that are just convenient.  I love it.&lt;/p&gt;
&lt;p&gt;Syncing my contacts from my Blackberry wasn&amp;#8217;t as straight forward as I thought it&amp;#8217;d be.  Unfortunately the A630 doesn&amp;#8217;t work with isync by default.  &lt;a href="http://www.pocketmac.net/"&gt;PocketMac&lt;/a&gt; did a decent job of putting all of my blackberry contacts into my mac address book, isync just refused to connect to my a630.  I found a great &lt;a href="http://www.macosxhints.com/article.php?story=2005071122352210"&gt;write-up on syncing the a630 with isync&lt;/a&gt; on &lt;a href="http://www.macosxhints.com/"&gt;macosxhints&lt;/a&gt; and now all is well.&lt;/p&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2006/09/08/phone-upgrade.html</feedburner:origLink></entry>
 
 <entry>
   <title>nginx proxying down to your mongrels</title>
   <link href="http://feedproxy.google.com/~r/atmosdotorg/~3/igBga1Rnz44/nginx-proxying-down-to-your-mongrels.html" />
   <updated>2006-08-23T00:00:00-07:00</updated>
   <id>http://www.atmos.org/2006/08/23/nginx-proxying-down-to-your-mongrels</id>
   <content type="html">&lt;p&gt;&lt;a href="http://brainspl.at"&gt;Ezra&lt;/a&gt; was going on and on about this &lt;a href="http://sysoev.ru/en/"&gt;nginx&lt;/a&gt; things on &lt;span class="caps"&gt;IRC&lt;/span&gt; today.  Saying how it was &amp;#8220;super light and fast webserver with really good(better than pound) proxy module.&amp;#8221;  I had an app I wanted to setup a &lt;a href="http://mongrel.rubyforge.org/docs/mongrel_cluster.html"&gt;mongrel_cluster&lt;/a&gt; for at work, and when he gave a &lt;a href="http://pastie.caboo.se/9734"&gt;pastie like this&lt;/a&gt; I figured I&amp;#8217;d give it a try.  It took all of 5 minutes to be up and running.  It &lt;strong&gt;seems&lt;/strong&gt; fine for the time being, I&amp;#8217;ll find out tomorrow when more users start hitting it.  One thing that was weird was I couldn&amp;#8217;t start it on a high port as an unprivileged user.  You &lt;span class="caps"&gt;CAN&lt;/span&gt; however start it with sudo, set the user in your config file, and it seems to setuid properly.  Thanks Ezra!&lt;/p&gt;
&lt;p&gt;My friend Kevin at work shared &lt;a href="http://blog.kovyrin.net/2006/04/04/nginx-small-powerful-web-server/"&gt;this link&lt;/a&gt; this morning, which covers a few of the cool features it offers.&lt;/p&gt;</content>
 <feedburner:origLink>http://www.atmos.org/2006/08/23/nginx-proxying-down-to-your-mongrels.html</feedburner:origLink></entry>
 

</feed>

