<?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>stephencelis</title>
  
  <link href="http://stephencelis.com" />
  <updated>2011-03-04T18:30:11-05:00</updated>
  <id>http://stephencelis.com</id>
  <author>
    <name>Stephen Celis</name>
    <email>stephen@stephencelis.com</email>
  </author>
  
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/stephencelis" /><feedburner:info uri="stephencelis" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>Miniskirt: factory_girl, relaxed</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/b7tq9njfMdc/miniskirt.html" />
    <updated>2010-01-11T00:00:00-05:00</updated>
    <id>http://stephencelis.com/2010/01/11/miniskirt</id>
    <content type="html">&lt;p&gt;
  &lt;a href="http://github.com/rails/rails"&gt;Living on the edge&lt;/a&gt; isn’t easy.
  You continuously risk that everything you rely on stops working.
&lt;/p&gt;
&lt;aside&gt;
&lt;pre&gt;&lt;samp&gt;NoMethodError: undefined method `configuration' for #&amp;lt;Rails::Application&gt;
  from rails/railties/lib/rails.rb:53:in `configuration'
  from factory_girl-1.2.3/lib/factory_girl.rb:25:in `&amp;lt;top (required)&gt;'
  from rails/activesupport/lib/active_support/dependencies.rb:167:in `require'
  from rails/activesupport/lib/active_support/dependencies.rb:167:in `block in require'
  from rails/activesupport/lib/active_support/dependencies.rb:537:in `new_constants_in'
  from rails/activesupport/lib/active_support/dependencies.rb:167:in `require'
  from test/test_helper.rb:16&lt;/samp&gt;&lt;/pre&gt;
&lt;/aside&gt;
&lt;p&gt;
  &lt;i&gt;Et tu&lt;/i&gt;,
  &lt;a href="http://github.com/thoughtbot/factory_girl"&gt;&lt;code&gt;factory_girl&lt;/code&gt;&lt;/a&gt;?
&lt;/p&gt;
&lt;p&gt;
  The fix was easy enough&lt;sup id="mark_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;, but
  I started realized that I only really used a small fraction of what was
  under the hood. I took a page out of
  &lt;a href="http://blog.zenspider.com"&gt;Ryan Davis&lt;/a&gt;’
  &lt;a href="http://rubyconf2007.confreaks.com/d1t2p3_hurting_code.html"&gt;book&lt;/a&gt;,
  reordered the words, and wrote
  &lt;a href="http://gist.github.com/273579"&gt;Miniskirt&lt;/a&gt; to complement
  &lt;a href="http://blog.zenspider.com/minitest"&gt;minitest&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Miniskirt is &lt;code&gt;factory_girl&lt;/code&gt;, relaxed. It’s the essential, with
  some flare:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;mark&gt;Blocks are avoidable&lt;/mark&gt; with Ruby 1.9 string interpolation.
    Avoid blocks if you can. Your models should handle their own logic.
    &lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;%{first_name}.%{last_name}@example.com&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# ...not...&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@example.com&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
  &lt;li&gt;&lt;mark&gt;Sequences are simpler&lt;/mark&gt; (why bother with blocks?):
    &lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;person%d@example.com&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# ...instead of...&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;person&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@example.com&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/ul&gt;
&lt;p&gt;
  What’s missing?
&lt;/p&gt;
&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;Factory.attributes_for :model&lt;/code&gt;.
  &lt;dd&gt;Call &lt;code&gt;Factory.build(:model).attributes&lt;/code&gt;, instead.
  &lt;dt&gt;&lt;code&gt;Factory.stub&lt;/code&gt;.
  &lt;dd&gt;Stub your models like you stub everything else.
  &lt;dt&gt;&lt;code&gt;Factory#association&lt;/code&gt;.
  &lt;dd&gt;Almost as short, and explicit: &lt;code&gt;f.user { Factory :user }&lt;/code&gt;.
  &lt;dt&gt;&lt;code&gt;Factory#callback&lt;/code&gt;.
  &lt;dd&gt;I can’t think of a callback that should be on a factory but not the
    model.
&lt;/dl&gt;
&lt;p&gt;
  Here she is. All of her.
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-273579"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# Factory girl, relaxed.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   Factory.define :user do |f|&lt;/span&gt;
&lt;span class="c1"&gt;#     f.login &amp;#39;johndoe%d&amp;#39;                          # Sequence.&lt;/span&gt;
&lt;span class="c1"&gt;#     f.email &amp;#39;%{login}@example.com&amp;#39;               # Interpolate.&lt;/span&gt;
&lt;span class="c1"&gt;#     f.password f.password_confirmation(&amp;#39;foobar&amp;#39;) # Chain.&lt;/span&gt;
&lt;span class="c1"&gt;#   end&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   Factory.define :post do |f|&lt;/span&gt;
&lt;span class="c1"&gt;#     f.user { Factory :user }                     # Blocks, if you must.&lt;/span&gt;
&lt;span class="c1"&gt;#   end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Miniskirt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:__klass__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;undef_method&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nb"&gt;instance_methods&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^(?!__|object_id)/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# BlankerSlate.&lt;/span&gt;
  &lt;span class="vc"&gt;@@factories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;private_class_method&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vc"&gt;@@factories&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="kp"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;classify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constantize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stringify_keys!&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vc"&gt;@@factories&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="c1"&gt;# Sequence and interpolate.&lt;/span&gt;
            &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/%\d*d/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
          &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Proc&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
      &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vc"&gt;@@factories&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;__klass__&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Miniskirt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="no"&gt;Miniskirt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Miniskirt&lt;/span&gt;
&lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Factory&lt;/span&gt; &lt;span class="no"&gt;Miniskirt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Not bad for under 30 &lt;abbr class="acronym" title="lines of code"&gt;LOC&lt;/abbr&gt;.
&lt;/p&gt;
&lt;p&gt;
  Miniskirt isn't for everyone. The slightly more conservative, more
  backwards-compatible &lt;a href="http://gist.github.com/273587"&gt;Minidress&lt;/a&gt;
  may suit you better. Or maybe &lt;code&gt;factory_girl&lt;/code&gt;, with all her bells
  and whistles, fits you just
  fine.&lt;sup id="mark_2"&gt;&lt;a href="#foot_2"&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;
  Whatever you choose, though, remember: &lt;strong&gt;write less&lt;/strong&gt;, and
  &lt;strong&gt;write better&lt;/strong&gt;.
&lt;/p&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;sup id="#foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
    &lt;small&gt;Up and running:&lt;/small&gt;
  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# test/test_helper.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_eval&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;factory_girl&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# Now she loads just fine...&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;factories&amp;quot;&lt;/span&gt;    &lt;span class="c1"&gt;# ...and the rest needs to load explicitly.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;
    &lt;sup id="#foot_2"&gt;&lt;a href="#mark_2"&gt;2&lt;/a&gt;&lt;/sup&gt;
    &lt;small&gt;I &lt;em&gt;like&lt;/em&gt; &lt;code&gt;factory_girl&lt;/code&gt;, and may find myself
    returning to her when my platform is a bit more stable, especially if she
    picks up some of these interpolative tricks.&lt;/small&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/b7tq9njfMdc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2010/01/11/miniskirt.html</feedburner:origLink></entry>
  
  <entry>
    <title>YAAC—yes, yet another…</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/empG2fKgFx0/yaac-yes-yet-another.html" />
    <updated>2009-04-18T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2009/04/18/yaac-yes-yet-another</id>
    <content type="html">&lt;p&gt;
  I’ve been rolling my own app configs for awhile now. It’s been just another
  step in the &lt;kbd&gt;rails newapp&lt;/kbd&gt; ritual. A chore, really.
  &lt;a href="http://weblog.rubyonrails.org/2009/3/16/rails-2-3-templates-engines-rack-metal-much-more"&gt;Rails templates&lt;/a&gt;
  make things a bit easier, but the logic shouldn’t untidy my &lt;samp&gt;lib&lt;/samp&gt;
  and &lt;samp&gt;initializers&lt;/samp&gt;, should it?
&lt;/p&gt;
&lt;p&gt;
  I know
  &lt;a href="http://github.com/cjbottaro/app_config"&gt;it’s been done before&lt;/a&gt;,
  and others will do it again, but I just had to &lt;kbd&gt;TODO&lt;/kbd&gt; its release
  when, last month, I heard Jacques Crocker &lt;strong&gt;blithely gloat&lt;/strong&gt;
  that
  &lt;a href="http://github.com/merbjedi/app_config"&gt;his take on AppConfig&lt;/a&gt;
  is
  &lt;q&gt;&lt;a href="http://mwrc2009.confreaks.com/13-mar-2009-19-12-appconfig-jacques-crocker.html"&gt;better than everyone else’s&lt;/a&gt;&lt;/q&gt;.
&lt;/p&gt;
&lt;p&gt;
  &lt;i&gt;Au contraire, mon amie!&lt;/i&gt; Let me introduce &lt;em&gt;my&lt;/em&gt; way: the way I
  rather like it.
&lt;/p&gt;
&lt;h3&gt;Hello, App&lt;/h3&gt;
&lt;p&gt;
  &lt;a href="http://github.com/stephencelis/app"&gt;App&lt;/a&gt; is &lt;em&gt;yet another&lt;/em&gt;
  &lt;abbr title="Yet Another Markup Language" class="acronym"&gt;YAML&lt;/abbr&gt;-based,
  app config for Rails. App should look familiar enough. It looks for and
  loads from &lt;samp&gt;config/app.yml&lt;/samp&gt;, and provides namespaced access:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; {&amp;quot;apis&amp;quot;=&amp;gt;{&amp;quot;flickr&amp;quot;=&amp;gt;{ ... }}&lt;/span&gt;

&lt;span class="c1"&gt;# Sugar is always sweeter:&lt;/span&gt;
&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;apis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;flickr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; App.config[&amp;quot;apis&amp;quot;][&amp;quot;flickr&amp;quot;]&lt;/span&gt;

&lt;span class="c1"&gt;# Who doesn&amp;#39;t like sugar?&lt;/span&gt;
&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;apis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;flickr&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Sugar, sugar, sugar!&lt;/span&gt;
&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;flickr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Namespace again, if necessary, e.g., with &amp;quot;config/app/apis.yml&amp;quot;:&lt;/span&gt;
&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Apis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flickr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  So, how does App stand up against the self-proclaimed champ? Well, it’s
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;mark&gt;⅓ the size of &lt;kbd&gt;AppConfig&lt;/kbd&gt;&lt;/mark&gt;, so save yourself those
    last six keystrokes. It also starts you out with just one file:
    &lt;samp&gt;app.yml&lt;/samp&gt; (no environmental waste!). (The code base? Yes, it’s
    slimmer, too.)
  &lt;li&gt;&lt;mark&gt;Less magical [&lt;i&gt;pej.&lt;/i&gt;]&lt;/mark&gt; on the surface. Method
    chaining should really only go so far, so we prefer
    &lt;code&gt;App.apis("twitter")&lt;/code&gt; to the &lt;code&gt;OpenStruct&lt;/code&gt; choo-choo
    that is &lt;code&gt;AppConfig.apis.twitter&lt;/code&gt;.
  &lt;li&gt;&lt;mark&gt;More modular&lt;/mark&gt; (when we want it to be). If your configuration
    starts to outgrow itself, branch it out.
&lt;/ul&gt;
&lt;p&gt;
  So what’s the easiest way to get started? Using this template:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-97629"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# App (http://github.com/stephencelis/app), for Rails:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# In existing projects:&lt;/span&gt;
&lt;span class="c1"&gt;#   % rake rails:template LOCATION=http://gist.github.com/97629.txt&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# For new projects:&lt;/span&gt;
&lt;span class="c1"&gt;#   % rails newapp -m http://gist.github.com/97629.txt&lt;/span&gt;

&lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;config/environment.rb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include?&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;stephencelis-app&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;stephencelis-app&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:lib&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;app&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="ss"&gt;:source&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://gems.github.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="ss"&gt;:version&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;gt;= 0.2.2&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exist?&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;config/app.yml&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;app_config&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;stephencelis-app&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LoadError&lt;/span&gt;
  &lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;gems:install&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sudo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vendor/gems/stephencelis-app*&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;any?&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vendor/gems&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;yes?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Unpack gem?&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;gems:unpack&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sudo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  You can also install App as a plugin, or maintain its gem installation
  yourself: just take a look at the
  &lt;a href="http://github.com/stephencelis/app/tree/master#readme"&gt;&lt;samp&gt;README&lt;/samp&gt; on GitHub&lt;/a&gt;.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/empG2fKgFx0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2009/04/18/yaac-yes-yet-another.html</feedburner:origLink></entry>
  
  <entry>
    <title>What’s the password…haddock?</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/7ZbIV_5FRC8/whats-the-password-haddock.html" />
    <updated>2009-03-29T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2009/03/29/whats-the-password-haddock</id>
    <content type="html">&lt;div class="flow"&gt;
  &lt;figure class="video"&gt;
    &lt;a href="http://www.youtube.com/watch?v=IOxpPJYUTDM"&gt;
      &lt;img src="http://img.skitch.com/20090328-jyht7ue6ti99mk675m1rwjppxn.png" alt="Have you seen Horse Feathers?" title="Have you seen Horse Feathers?"&gt;
    &lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a href="http://www.youtube.com/watch?v=IOxpPJYUTDM"&gt;Haddock worked for Groucho&lt;/a&gt;, and it can work for you. It’s not the password, but it can help
  get you there.
&lt;/p&gt;
&lt;p&gt;
  What’s haddock?
  &lt;a href="http://github.com/stephencelis/haddock"&gt;Haddock&lt;/a&gt; is a
  &lt;a href="http://rubygems.org"&gt;gem&lt;/a&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;% &lt;/samp&gt;&lt;kbd&gt;sudo gem install haddock
&lt;/kbd&gt;&lt;samp&gt;Password:&lt;/samp&gt;&lt;kbd&gt;
&lt;/kbd&gt;&lt;samp&gt;Successfully installed haddock-0.2.0
1 gem installed
Installing ri documentation for haddock-0.2.0...
Installing RDoc documentation for haddock-0.2.0...&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Haddock is based on one of Apple’s own hidden gems:
  &lt;a href="http://docs.info.apple.com/article.html?path=Mac/10.5/en/8162.html#taskbox"&gt;Password Assistant&lt;/a&gt;’s memorable password generator. It uses something most
  password generators don’t use:
&lt;/p&gt;
&lt;div class="flow"&gt;
  &lt;figure&gt;
    &lt;a href="http://docs.info.apple.com/article.html?path=Mac/10.5/en/8162.html#taskbox"&gt;
      &lt;img src="http://img.skitch.com/20090328-rtec87prfqkyiyc7716ufjby3r.png" alt="Words."&gt;
    &lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;
  Actual words. And so does haddock.
&lt;/p&gt;
&lt;p&gt;
  So now that you have a &lt;span title="Headache?" class="hint"&gt;haddock&lt;/span&gt;,
  &lt;span title="Take an aspirin or a calomel." class="hint"&gt;what are you going
  to do?&lt;/span&gt; Let’s make some passwords with
  &lt;kbd&gt;ha-gen&lt;/kbd&gt;.&lt;sup id="mark_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;% &lt;/samp&gt;&lt;kbd&gt;ha-gen
&lt;/kbd&gt;&lt;samp&gt;habit57/love
% &lt;/samp&gt;&lt;kbd&gt;ha-gen
&lt;/kbd&gt;&lt;samp&gt;hawk47{uncle
% &lt;/samp&gt;&lt;kbd&gt;ha-gen
&lt;/kbd&gt;&lt;samp&gt;Bim52`bummer&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Ripe for mnemonic stories, every one of them! And &lt;strong&gt;secure!&lt;/strong&gt;
  But we can be even &lt;em&gt;more&lt;/em&gt; secure:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;% &lt;/samp&gt;&lt;kbd&gt;ha-gen --length=16
&lt;/kbd&gt;&lt;samp&gt;knab7[bitterhead
% &lt;/samp&gt;&lt;kbd&gt;ha-gen -l 24
&lt;/kbd&gt;&lt;samp&gt;picklelike63%captainship
% &lt;/samp&gt;&lt;kbd&gt;ha-gen -l30
&lt;/kbd&gt;&lt;samp&gt;craniology3430{incompetentness&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;strong&gt;Beautiful!&lt;/strong&gt; Work on your diction as you go!
  Security &lt;em&gt;and&lt;/em&gt; self-improvement! I’m not sure about you, but I could
  make these all day long. &lt;strong&gt;Be warned&lt;/strong&gt;, though. When you use
  haddock a lot,
  &lt;a href="http://en.wikipedia.org/wiki/Captain_Haddock"&gt;another Haddock may come to mind&lt;/a&gt;:
&lt;/p&gt;
&lt;div class="flow"&gt;
  &lt;figure&gt;
    &lt;a href="http://en.wikipedia.org/wiki/Captain_Haddock"&gt;
      &lt;img src="http://img.skitch.com/20090329-eby5k3dpdb988egktrdpe57x3w.png" alt="Captain Haddock!" title="Captain Haddock!"&gt;
    &lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;
  This utility has an even more colorful vocabulary than
  &lt;a href="http://tintinologist.org/guides/lists/curses.html"&gt;the Captain’s&lt;/a&gt;.
  It uses your
  &lt;a href="http://en.wikipedia.org/wiki/Words_(Unix)"&gt;UNIX word list&lt;/a&gt; (at
  &lt;samp&gt;/usr/share/dict/words&lt;/samp&gt; or &lt;samp&gt;/usr/share/words&lt;/samp&gt;), so
  anything therein is fair game. The occasional anatomical term may put off
  sensitive users, but you can always make haddock eat your own words, easily
  enough:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;% &lt;/samp&gt;&lt;kbd&gt;ha-gen -f ~/Documents/awesome_words.txt
&lt;/kbd&gt;&lt;samp&gt;gnarly8;cool&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  In fact, if you’re on Windows, you’ll have to. But don’t worry,
  &lt;a href="http://wordlist.sourceforge.net"&gt;Kevin has you covered&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  In the end, though, haddock is a library for your Ruby applications. Want to
  add some flair to your web app’s password reset codes? This will probably
  look familiar enough:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-87453"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;haddock&amp;quot;&lt;/span&gt;

&lt;span class="no"&gt;Haddock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; &amp;quot;bowl9&amp;amp;bracky&amp;quot;&lt;/span&gt;

&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Haddock&lt;/span&gt;            &lt;span class="c1"&gt;# (Make things easier on our fingers...)&lt;/span&gt;

&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# =&amp;gt; &amp;quot;Phlebotomus2473?nonconditioned&amp;quot;&lt;/span&gt;
&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# =&amp;gt; &amp;quot;amy7@rax&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# To use a custom (newline-delimited) word list:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   Password.diction = &amp;quot;/path/to/words&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  That’s all it takes to get up and running. Your users will appreciate the
  friendlier alternative to a cryptographic digest. I don’t care
  &lt;a href="http://coderrr.wordpress.com/2008/10/28/ruby-golf-generating-random-strings"&gt;how cool your code golf is&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  All right, all right, I care. That stuff is just &lt;em&gt;too&lt;/em&gt; cool.
&lt;/p&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;sup id="foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
    &lt;small&gt;
      I know, I know:
      &lt;kbd&gt;&lt;a href="http://www.hagen.com/usa/aquatic/index.html"&gt;ha-gen&lt;/a&gt;&lt;/kbd&gt;?
      You see, &lt;a href="http://haskell.org/haddock"&gt;Haskell already has a &lt;kbd&gt;haddock&lt;/kbd&gt;&lt;/a&gt;, and let’s not step on any toes. You can always
      &lt;code&gt;alias haddock=ha-gen&lt;/code&gt;, though. Much better!
    &lt;/small&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/7ZbIV_5FRC8" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2009/03/29/whats-the-password-haddock.html</feedburner:origLink></entry>
  
  <entry>
    <title>Yahoo! for the future</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/EEnIzvsQAKE/yahoo-for-the-future.html" />
    <updated>2009-03-09T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2009/03/09/yahoo-for-the-future</id>
    <content type="html">&lt;style type="text/css" media="screen" scoped&gt;
  /* General */

  div#springboard {
    background: #000;
    border: 3px solid #000;
    height: 444px;
    margin: 0 auto;
    width: 312px;
    overflow: hidden;

    -webkit-border-radius: 4px;
    -webkit-transition-duration: 0.25s;
    -webkit-transition-property: background;
    -webkit-transition-timing-function: ease-in-out;
  }
    div#springboard:hover {
      background: #6e6e6e;
    }
    div#springboard &gt; ul {
      background: #000;
      height: 348px;
      margin: 0;
      overflow: hidden;
      padding: 2px;
      width: 308px;
    }
    div#springboard ul li {
      background:
        -webkit-gradient(radial, 29 -37, 57, 29 -37, 67,
          from(rgba(255, 255, 255, 0.5)), to(rgba(255, 255, 255, 0)),
          color-stop(90%, rgba(255, 255, 255, 0.25))),
        url(/images/yahoo-apple-touch-icon.png);
      cursor: pointer;
      display: inline-block;
      height: 57px;
      margin: 10px 10px 16px;
      padding: 0;
      position: relative;
      width: 57px;
      z-index: 0;

      -webkit-border-radius: 10px;
      -webkit-box-shadow: #000 0 2px 2px;
      -webkit-transition-duration: 0.25s;
      -webkit-transition-property: left, opacity, top, -webkit-transform;
      -webkit-transition-timing-function: ease-in-out;
    }
    div#springboard div#favorites {
      background: -webkit-gradient(linear, left top, left bottom,
        from(#494949),
        to(#bfbfbf));
      padding: 2px;
      width: 308px;
      height: 74px;
      margin: 0;
      opacity: 0;

      -webkit-transition-duration: 0.25s;
      -webkit-transition-property: opacity;
      -webkit-transition-timing-function: ease-in-out;
    }
      div#springboard:hover div#favorites {
        opacity: 1;

        -webkit-transition-duration: 0.25s;
        -webkit-transition-property: opacity;
        -webkit-transition-timing-function: ease-in-out;
      }
      div#springboard div#favorites ul {
        background: url(/images/dimple.png);
        margin: 0;
        padding: 0;
        width: 308px;
        height: 74px;
      }
        div#favorites ul li {
          margin-top: 8px;
        }
        div#springboard ul li p {
          color: #777;
          font: 11px "Lucida Grande";
          margin: 0;
          position: relative;
          text-align: center;
          text-shadow: none;
          top: 57px;
        }
          div#springboard div#favorites ul li p {
            color: #fff;
            text-shadow:  #111 0 -1px 1px;
            top: 68px;
          }

  /* Offscreen */

  div#springboard img {
    position: absolute;
    
    -webkit-transition-property: opacity, -webkit-transform;
    -webkit-transition-duration: 0.25s;
    -webkit-transform: scale(1);
  }
  div#springboard:hover img {
    opacity: 0;
    
    -webkit-transform: scale(0);
    -webkit-transition-duration: 0.25s;
  }
  div#springboard:not(:hover) &gt; ul li:nth-child(4n+1) { left: -400px; }
  div#springboard:not(:hover) &gt; ul li:nth-child(4n+2) { left: -250px; }
  div#springboard:not(:hover) &gt; ul li:nth-child(4n+3) { left: 250px; }
  div#springboard:not(:hover) &gt; ul li:nth-child(4n+4) { left: 400px; }
  div#springboard:not(:hover) &gt; ul li:nth-child(-n+4),
    div#springboard:not(:hover) &gt; ul li:nth-child(5),
    div#springboard:not(:hover) &gt; ul li:nth-child(6),
    div#springboard:not(:hover) &gt; ul li:nth-child(7),
    div#springboard:not(:hover) &gt; ul li:nth-child(8) { top: -400px; }
  div#springboard:not(:hover) &gt; ul li:nth-child(9),
    div#springboard:not(:hover) &gt; ul li:nth-child(10),
    div#springboard:not(:hover) &gt; ul li:nth-child(11),
    div#springboard:not(:hover) &gt; ul li:nth-child(12),
    div#springboard:not(:hover) &gt; ul li:nth-child(13),
    div#springboard:not(:hover) &gt; ul li:nth-child(14),
    div#springboard:not(:hover) &gt; ul li:nth-child(15),
    div#springboard:not(:hover) &gt; ul li:nth-child(16) { top: 400px; }

  /* Pagination */

  div#springboard:hover &gt; ul:after {
    color: #ddd;
    content: "•";
    display: block;
    text-align: center;
  }
  div#springboard:active &gt; ul:after {
    -webkit-mask-image: -webkit-gradient(linear, left top, right top,
      color-stop(0.49, rgba(255,255,255,1)),
      color-stop(0.51, rgba(255,255,255,0.2)));
    content: "•  •";
  }

  /* Wiggling */

  div#springboard:active ul li:active {
    opacity: 0.5;
    -webkit-transform: scale(1.375);
    -webkit-transition-duration: 0.25s;
    z-index: 1;
  }
  div#springboard:active ul li:not(:active) {
    -webkit-animation-duration: 0.25s;
    -webkit-animation-iteration-count: infinite;
  }
  div#springboard:active ul li:not(:active):nth-child(5n+1) {
    -webkit-animation-name: "wiggle1";
  }
  div#springboard:active ul li:not(:active):nth-child(5n+2) {
    -webkit-animation-name: "wiggle2";
  }
  div#springboard:active ul li:not(:active):nth-child(5n+3) {
    -webkit-animation-name: "wiggle3";
  }
  div#springboard:active ul li:not(:active):nth-child(5n+4) {
    -webkit-animation-name: "wiggle4";
  }
  div#springboard:active ul li:not(:active):nth-child(5n+5) {
    -webkit-animation-name: "wiggle5";
  }

  @-webkit-keyframes "wiggle1" {
    0%, 100% { left: 2px; top: 2px; -webkit-transform: rotate(3deg); }
    50% { left: -1px; top: -1px; -webkit-transform: rotate(-2deg); }
  }
  @-webkit-keyframes "wiggle2" {
    0%, 100% { left: -1px; top: -1px; -webkit-transform: rotate(2deg); }
    50% { left: 2px; top: 2px; -webkit-transform: rotate(-3deg); }
  }
  @-webkit-keyframes "wiggle3" {
    0%, 100% { left: -1px; top: 2px; -webkit-transform: rotate(-3deg); }
    50% { left: -1px; top: 1px; -webkit-transform: rotate(2deg); }
  }
  @-webkit-keyframes "wiggle4" {
    0%, 100% { left: 2px; top: -2px; -webkit-transform: rotate(4deg); }
    50% { left: 2px; top: 2px; -webkit-transform: rotate(0deg); }
  }
  @-webkit-keyframes "wiggle5" {
    0%, 100% { left: -1px; top: -1px; -webkit-transform: rotate(-2deg); }
    50% { left: 2px; top: 2px; -webkit-transform: rotate(1deg); }
  }
&lt;/style&gt;
&lt;p&gt;
  &lt;a href="http://crockford.com"&gt;Doug Crockford&lt;/a&gt; has it out for me! Less
  than a week after I submit to our friend &lt;abbr&gt;HTML5&lt;/abbr&gt;,
  &lt;a href="http://blog.360.yahoo.com/blog-TBPekxc1dLNy5DOloPfzVvFIVOWMB0li?p=978"&gt;he
  declares war&lt;/a&gt;! &lt;i&gt;Off with its &lt;code&gt;&amp;lt;HEAD&amp;gt;&lt;/code&gt;&lt;/i&gt;, says he:
&lt;/p&gt;
&lt;blockquote&gt;
  …the HTML5 project is misguided… It is trying to do too much without a clear
  mission that defines the problems it is solving. I think the project needs a
  reset.
&lt;/blockquote&gt;
&lt;p&gt;
  Oh, say it isn’t so, Doug! This is the guy that named
  &lt;abbr title="JavaScript Objectionable Notation"&gt;JSON&lt;/abbr&gt; and gave him
  &lt;a href="http://json.org"&gt;a home&lt;/a&gt;; the guy that
  &lt;a href="http://www.crockford.com/javascript/jsmin.html"&gt;prescribed&lt;/a&gt; us
  &lt;a href="http://developer.yahoo.com/yui/compressor"&gt;minification&lt;/a&gt;. This
  guy figured out
  &lt;a href="http://www.youtube.com/watch?v=hQVTIJBZook"&gt;which parts of
  JavaScript are &lt;em&gt;good&lt;/em&gt;&lt;/a&gt;. He risked his life for us and lived to
  tell the tale
  (&lt;a href="https://www.amazon.com/dp/0596517742?tag=stepceli-20&amp;amp;camp=0&amp;amp;creative=0&amp;amp;linkCode=as4&amp;amp;creativeASIN=0596517742&amp;amp;adid=11AR1HJY9Y1PDQZVBW5R&amp;amp;"&gt;$29.99 list&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;
  Then again, Old Doug also wrote &lt;a href="http://jslint.com"&gt;JSLint&lt;/a&gt;,
  and let’s not even get into that one. Let’s move on. That’s what he’d want
  us to do.
&lt;/p&gt;
&lt;p&gt;
  No need to be bitter. Douglas only wants the best for us. Really. It’s just
  tough love from a stolid, fatherly figure with salt ’n’ pepper whiskers and
  a gentle grin.
&lt;/p&gt;
&lt;p&gt;
  &lt;i&gt;But we already have
  &lt;abbr title="Extensible HyperText Markup Language"&gt;XHTML&lt;/abbr&gt;&lt;/i&gt;, you may
  be quick to say. &lt;i&gt;Where &lt;dfn&gt;strict&lt;/dfn&gt; is cool! So what’s the
  deal with 4.2? More of the same?&lt;/i&gt;
  &lt;a href="http://crockford.com/html"&gt;This document&lt;/a&gt; offers some clues.
&lt;/p&gt;
&lt;p&gt;
  Where’s the glitz, though? The dazzle? What can an artist do without a
  &lt;code&gt;canvas&lt;/code&gt;? We could have &lt;code&gt;audio&lt;/code&gt; and
  &lt;code&gt;video&lt;/code&gt;, and no plugin! You won’t miss my congratulatory
  advertisement &lt;em&gt;this&lt;/em&gt; time. You &lt;em&gt;deserve&lt;/em&gt; to know. And to know
  the joy of &lt;abbr title="Structured Query Language"&gt;SQL&lt;/abbr&gt;, finally, in
  the browser. Forms with placeholders and validations built-in! Vectors!
  &lt;code&gt;details&lt;/code&gt;! And the semantics, oh the semantics! What’s a poor old
  Google to do, parsing through &lt;code&gt;div&lt;/code&gt;s and &lt;code&gt;span&lt;/code&gt;s when
  it could have &lt;code&gt;nav&lt;/code&gt;, &lt;code&gt;article&lt;/code&gt;, and
  &lt;code&gt;aside&lt;/code&gt;? Won’t somebody please think of the robots?
&lt;/p&gt;
&lt;p&gt;
  But let’s leave the &lt;abbr&gt;HTML&lt;/abbr&gt; argument be, for now. We can at least
  agree that &lt;abbr title="Cascading Style Sheets"&gt;CSS&lt;/abbr&gt; is in a wonderful
  place. JSON’s little half nephew is doing all right.
&lt;/p&gt;
&lt;p&gt;
  This next one’s for you,
  Crock.&lt;sup id="mark_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
  &lt;small&gt;(&lt;a href="http://apple.com/safari"&gt;Safari 4&lt;/a&gt; or equivalent
  required; just hover over the image.)&lt;/small&gt;
&lt;/p&gt;
&lt;figure&gt;
  &lt;div id="springboard"&gt;
    &lt;img src="/images/crock.jpg"&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
    &lt;/ul&gt;
    &lt;div id="favorites"&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
        &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
        &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
        &lt;li&gt;&lt;p&gt;Yahoo!&lt;/p&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/figure&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;sup id="foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
    &lt;small&gt;
      Sorry, Doug. No JavaScript here. But
      &lt;a href="http://stephencelis.com/images/crock.jpg"&gt;only&lt;/a&gt;
      &lt;a href="http://stephencelis.com/images/yahoo-apple-touch-icon.png"&gt;three&lt;/a&gt;
      &lt;a href="http://stephencelis.com/images/dimple.png"&gt;images&lt;/a&gt;, all
      quite dolled up on the fly. Not too
      &lt;a href="http://developer.yahoo.com/yslow"&gt;YSlow&lt;/a&gt;! And apologies,
      it’s not pixel perfect. I leave that exercise to the reader.
      &lt;a href="http://skitch.com/stephencelis/b8c1x/springing"&gt;Some&lt;/a&gt;
      &lt;a href="http://skitch.com/stephencelis/b8c1w/sprung"&gt;static&lt;/a&gt;
      &lt;a href="http://skitch.com/stephencelis/b8c12/sprang"&gt;demonstrations&lt;/a&gt;
      for the lazy.
      &lt;a href="http://www.flickr.com/photos/charliebrewer/2897862701/"&gt;Crock-shot
      by Charlie Brewer&lt;/a&gt;.
    &lt;/small&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;ins title="2009-03-10"&gt;
      &lt;small&gt;Lazy update: &lt;a href="http://almaer.com"&gt;Dion Almaer&lt;/a&gt; has
      kindly provided
      &lt;a href="http://www.vimeo.com/3558882"&gt;video of the action&lt;/a&gt;.&lt;/small&gt;
    &lt;/ins&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/EEnIzvsQAKE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2009/03/09/yahoo-for-the-future.html</feedburner:origLink></entry>
  
  <entry>
    <title>Now I just need an audience</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/SBmVs7La3dA/now-i-just-need-an-audience.html" />
    <updated>2009-03-02T00:00:00-05:00</updated>
    <id>http://stephencelis.com/2009/03/02/now-i-just-need-an-audience</id>
    <content type="html">&lt;section class="ins"&gt;
  &lt;h3&gt;Warning! This Library Is Deprecated!&lt;/h3&gt;
  &lt;p&gt;
    Please Please don't use this library anymore. It was a good run, though. We
    had some laughs and it was easy for the iPhone to hear them.
  &lt;/p&gt;
  &lt;p&gt;
    This code has been deprecated in favor of Apple's built-in solution,
    available since iOS 3.0:
    &lt;a href="http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioRecorder_ClassReference/Reference/Reference.html"&gt;&lt;code&gt;AVAudioRecorder&lt;/code&gt;&lt;/a&gt;.
  &lt;/p&gt;
  &lt;p&gt;
    Mobile Orchard published
    &lt;a href="http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/"&gt;a nice tutorial&lt;/a&gt;.
  &lt;/p&gt;
&lt;/section&gt;
&lt;p&gt;
  &lt;strong&gt;Voice activation&lt;/strong&gt;. Sounds cool, doesn’t it? And all the
  cool people are using it! Nintendo was on to something with their DS and
  its microphone:
  &lt;a href="http://en.wikipedia.org/wiki/Wario_Ware_Touched!"&gt;Wario's little games&lt;/a&gt;
  were no match for a little heavy breathing. With the iPhone,
  &lt;a href="http://www.smule.com"&gt;Smule&lt;/a&gt; is
  using it up a storm! And &lt;a href="http://isteam.co.uk"&gt;iSteam&lt;/a&gt;? Yes!
  These guys &lt;em&gt;get&lt;/em&gt; it: people &lt;em&gt;love&lt;/em&gt; doing stuff with their
  mouths! If there’s some kind of reward involved, well then, &lt;em&gt;now&lt;/em&gt;
  you’re talking. Blowing out candles, kissing, outright yelling up a
  scene—these are the things of life, right?
&lt;/p&gt;
&lt;p&gt;
  Apple’s been a pretty good parent: keeping the sandbox clean, inviting
  us to use the cam’, the accelerwhometer, the
  &lt;abbr title="Google Probably Sees-you"&gt;GPS&lt;/abbr&gt;, all without making us
  do too many chores. C’mon, Apple, what do you have for the mic’? We
  wanna be cool kids!
&lt;/p&gt;
&lt;p&gt;
  What’s this?
  &lt;a href="http://developer.apple.com/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/index.html"&gt;Audio Queue Services&lt;/a&gt;?
  Looks heavy. Lots in here. We just want to make a birthday cake app’
  with a birthday cake and a bunch of trick candles. Maybe a library buddy
  that shushes you if you’re disrespectful around the ardent readers. Or a
  game with a &lt;strong&gt;swarm of bees&lt;/strong&gt; and you get to puff smoke at
  them! &lt;strong&gt;Oh!&lt;/strong&gt; And maybe something with our friend Phillip and
  you get to finally put him in his place. Take that, Phillip!
&lt;/p&gt;
&lt;p&gt;
  …So, in a line or two of code I can figure out where in the universe my
  iPhone is and make sure I’m not holding it upside-down again, but I
  can’t figure out how loud I’m talking? Well, the pleasantly-prefixed
  &lt;code title="The SC stands for Smule-cool."&gt;SCListener&lt;/code&gt; may be
  able to help.
&lt;/p&gt;
&lt;p&gt;
  &lt;code&gt;SCListener&lt;/code&gt; is a simple little singleton with the bare bones
  of iPhone microphone impedimenta. Getting the levels is a mere matter of
  asking. Here’s a quick tour to get you started:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72914"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objectivec"&gt;&lt;span class="cp"&gt;#import &amp;quot;SCListener.h&amp;quot; &lt;/span&gt;&lt;span class="c1"&gt;// Remember to link to AudioToolbox.framework.&lt;/span&gt;

&lt;span class="c1"&gt;// Start listening.&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;SCListener&lt;/span&gt; &lt;span class="n"&gt;sharedListener&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve the average power.&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;SCListener&lt;/span&gt; &lt;span class="n"&gt;sharedListener&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;averagePower&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve the peak power.&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;SCListener&lt;/span&gt; &lt;span class="n"&gt;sharedListener&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;peakPower&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Hmm...we&amp;#39;re using this guy a lot...&lt;/span&gt;
&lt;span class="n"&gt;SCListener&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SCListener&lt;/span&gt; &lt;span class="n"&gt;sharedListener&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// We can temporarily stop returning levels&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Quick.&lt;/span&gt;

&lt;span class="c1"&gt;// Or free up resources when we&amp;#39;re not listening for awhile.&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Slower.&lt;/span&gt;

&lt;span class="c1"&gt;// Advanced!:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// If you&amp;#39;re using the average and the peak, fetch both at once.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;isListening&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// If listener has paused or stopped...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// ...bail.&lt;/span&gt;

&lt;span class="n"&gt;AudioQueueLevelMeterState&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;levels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;Float32&lt;/span&gt; &lt;span class="n"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;mPeakPower&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Float32&lt;/span&gt; &lt;span class="n"&gt;average&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;mAveragePower&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  &lt;code&gt;SCListener&lt;/code&gt; is
  &lt;a href="http://github.com/stephencelis/sc_listener"&gt;available on GitHub&lt;/a&gt;:
  &lt;a href="http://github.com/stephencelis/sc_listener/zipball/master"&gt;&lt;img src="http://stephencelis.com/images/download-trans.png" class="download" alt="Download"&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Now run along and throw your microphoney app’ into the ring. I’m just
  wrapping up a voice-activated flashlight, myself.
&lt;/p&gt;
&lt;p&gt;
  What? The flashlight vogue is over? &lt;em&gt;Please&lt;/em&gt;. No one should ever get
  tired of flashlights.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/SBmVs7La3dA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2009/03/02/now-i-just-need-an-audience.html</feedburner:origLink></entry>
  
  <entry>
    <title>Capistrano Growl notifications</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/HnzoSDS-08U/capistrano-growl-notifications.html" />
    <updated>2008-11-06T00:00:00-05:00</updated>
    <id>http://stephencelis.com/2008/11/06/capistrano-growl-notifications</id>
    <content type="html">&lt;p&gt;
  It’s very easy to lose track of your deployment. A &lt;kbd&gt;cap deploy&lt;/kbd&gt; and
  we’re on to other things. Time passes, our deploy failed, and we’ve
  forgotten all about it! Time to address that.
&lt;/p&gt;
&lt;h3&gt;Global &lt;kbd&gt;cap&lt;/kbd&gt; configuration&lt;/h3&gt;
&lt;p&gt;
  &lt;a href="http://rake.rubyforge.org"&gt;Rake&lt;/a&gt; has
  &lt;a href="http://github.com/postmodern/sake/tree/master"&gt;Sake&lt;/a&gt; and
  &lt;samp&gt;~/.rake/*.rake&lt;/samp&gt;files; Capistrano has &lt;samp&gt;~/.caprc&lt;/samp&gt;.
  C’mon, cap’n’, let’s get modular!
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72794"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# ~/.caprc&lt;/span&gt;
&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;HOME&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.recipes/*.rb&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  From now on, when we save a Ruby script into our &lt;samp&gt;~/.recipes/&lt;/samp&gt;
  directory, its tasks will be available to Capistrano wherever &lt;kbd&gt;cap&lt;/kbd&gt;
  is invoked.
&lt;/p&gt;
&lt;h3&gt;Growling&lt;/h3&gt;
&lt;p&gt;
  For Growl to play nicely with Ruby, we’ll need Leopard’s standard Ruby
  installation or
  &lt;a href="/2008/11/05/the-definitive-leopard-ruby-build"&gt;equivalent&lt;/a&gt;—with
  &lt;a href="http://rubyforge.org/frs/?group_id=126"&gt;RubyGems&lt;/a&gt;,
  &lt;a href="http://rubycocoa.sourceforge.net/HomePage"&gt;RubyCocoa&lt;/a&gt;: the
  works.
&lt;/p&gt;
&lt;p&gt;
  Wait…some of you don’t have Growl? Well
  &lt;a href="http://growl.info"&gt;get it&lt;/a&gt;; install it; love it. If you’re just
  downloading it now, be sure to install
  &lt;a href="http://growl.info/documentation/growlnotify.php"&gt;&lt;kbd&gt;growlnotify&lt;/kbd&gt;&lt;/a&gt;
  alongside it.
&lt;/p&gt;
&lt;p&gt;
  An alternative to &lt;kbd&gt;growlnotify&lt;/kbd&gt; is
  &lt;a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow"&gt;Meow&lt;/a&gt;,
  a delightful little gem. It makes growling with Ruby quite effortless:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo gem install meow
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  All that’s left is our little &lt;samp&gt;Capfile&lt;/samp&gt;:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72796"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# ~/.recipes/growl.rb&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;defined?&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:growl&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:notify&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;growl_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GROWL_MESSAGE&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;wants your attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:alert&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;growl_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GROWL_MESSAGE&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;needs your attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;deploy&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GROWL_MESSAGE&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;deployed &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;growl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rollback&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GROWL_MESSAGE&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rolled back &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;growl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;growl_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;meow&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OSX&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NSWorkspace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharedWorkspace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iconForFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`which cap`&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="no"&gt;Meow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cap&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Capistrano&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:priority&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:icon&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt;
  &lt;span class="sb"&gt;`growlnotify -ncap -p&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; -m &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; Capistrano`&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Next time your deploy wraps up, you’ll know about it.
&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt="A growl will modally show up." src="http://img.skitch.com/20090302-ntyk6cykjht9a7wbf8s1s7p12a.png"&gt;
&lt;/figure&gt;
&lt;p&gt;
  Oh, and if it doesn’t go over so well, you’ll know about it.
&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt="A growl will alert you." src="http://img.skitch.com/20090302-m94q6r6mjbpr4ski1yq4f67y3.png"&gt;
&lt;/figure&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/HnzoSDS-08U" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/11/06/capistrano-growl-notifications.html</feedburner:origLink></entry>
  
  <entry>
    <title>The definitive Leopard Ruby build</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/PRe3MY3fruY/the-definitive-leopard-ruby-build.html" />
    <updated>2008-11-05T00:00:00-05:00</updated>
    <id>http://stephencelis.com/2008/11/05/the-definitive-leopard-ruby-build</id>
    <content type="html">&lt;aside&gt;
  &lt;p&gt;
    &lt;ins&gt;
      (Updated &lt;time datetime="2009-04-19"&gt;19 Apr 2009&lt;/time&gt; for Ruby 1.8.7
      p160.&lt;sup id="mark_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;)
    &lt;/ins&gt;
  &lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;
  &lt;a href="http://hivelogic.com"&gt;Dan Benjamin&lt;/a&gt; has provided comprehensive
  compilation instructions to the Mac community for awhile now, but
  &lt;a href="http://hivelogic.com/articles/2008/02/ruby-rails-leopard"&gt;the latest one&lt;/a&gt;
  just doesn’t quite do it. If we want a build that’s as solid as Leopard’s
  built-in Ruby, we need to patch it for
  &lt;a href="http://rubycocoa.sourceforge.net"&gt;RubyCocoa&lt;/a&gt;:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72789"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;curl -O http://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p160.tar.gz
tar xzf ruby-1.8.7-p160.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;ruby-1.8.7-p160
curl http://gist.github.com/98109.txt | patch -p0
./configure --enable-shared --enable-pthread --enable-install-doc &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-D_XOPEN_SOURCE&lt;span class="o"&gt;=&lt;/span&gt;1
make
sudo make install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  You should be good to go.
&lt;/p&gt;
&lt;h3&gt;If things hiccup on Readline…&lt;/h3&gt;
&lt;p&gt;
  …you’ll need
  &lt;a href="http://tiswww.case.edu/php/chet/readline/rltop.html"&gt;Readline&lt;/a&gt;
  in your local path. To install it:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72790"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;curl -O ftp://ftp.cwru.edu/pub/bash/readline-5.2.tar.gz
tar xzf readline-5.2.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;readline-5.2
./configure &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo make install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Change the Ruby configuration line appropriately:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72792"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;./configure --enable-shared --enable-pthread --enable-install-doc &lt;span class="se"&gt;\&lt;/span&gt;
            --with-readline-dir&lt;span class="o"&gt;=&lt;/span&gt;/usr/local &lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-D_XOPEN_SOURCE&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;h3&gt;&lt;ins title="2009-04-19"&gt;Finally, RubyCocoa&lt;/ins&gt;&lt;/h3&gt;
&lt;p&gt;
  To get RubyCocoa up and running again, just check out the source, and
  install:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-98114"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;svn co http://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/trunk/src
&lt;span class="nb"&gt;cd &lt;/span&gt;src
ruby install.rb config --build-universal&lt;span class="o"&gt;=&lt;/span&gt;no
ruby install.rb setup
sudo ruby install.rb install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  And finally, make sure it all worked:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;% &lt;/samp&gt;&lt;kbd&gt;irb
&lt;/kbd&gt;&lt;samp&gt;&gt;&gt; &lt;/samp&gt;&lt;kbd&gt;require "rubycocoa"
&lt;/kbd&gt;&lt;samp&gt;=&gt; true&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;strong&gt;Phew!&lt;/strong&gt; We can use
  &lt;a href="http://zenspider.com/ZSS/Products/ZenTest"&gt;autotest&lt;/a&gt; with
  &lt;a href="http://growl.info"&gt;Growl&lt;/a&gt; again!
&lt;/p&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;ins title="2009-04-19"&gt;
      &lt;sup id="foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
      &lt;small&gt;
        If you’re looking for the old instructions,
        &lt;a href="http://gist.github.com/72789/4c46611d1083e8343f5eaada97fe84b3ffaa830a"&gt;they still exist as a gist revision&lt;/a&gt;.
      &lt;/small&gt;
    &lt;/ins&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/PRe3MY3fruY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/11/05/the-definitive-leopard-ruby-build.html</feedburner:origLink></entry>
  
  <entry>
    <title>ez does it, gemdoc</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/7eDStRq8wW4/ez-does-it-gemdoc.html" />
    <updated>2008-10-24T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/10/24/ez-does-it-gemdoc</id>
    <content type="html">&lt;p&gt;
  Let’s get back to basics. Let’s finally give
  &lt;a href="http://grml.org/zsh/zsh-lovers.html"&gt;Zsh&lt;/a&gt; and
  &lt;a href="http://code.google.com/p/macvim"&gt;Vim&lt;/a&gt; a royal go (we’ll try
  Emacs next week).
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;/samp&gt;&lt;kbd&gt;chsh -s /bin/zsh
&lt;/kbd&gt;&lt;samp&gt;Changing shell for stephen.
% &lt;/samp&gt;&lt;kbd&gt;alias mate=mvim&lt;/kbd&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;kbd&gt;ez&lt;/kbd&gt;&lt;/h3&gt;
&lt;p&gt;
  The shell is a place where configuration may go over convention.
  Ryan Bates
  &lt;a href="http://github.com/ryanb/dotfiles/tree/master/zsh"&gt;organizes things nicely&lt;/a&gt;,
  so we can fork from there, then customize. Our first addition: an important
  alias that will make our editing easier. Enter
  &lt;abbr title="Edit z"&gt;E.Z.&lt;/abbr&gt;:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72787"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.zsh/aliases&lt;/span&gt;

&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;ez&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;mvim -f ~/.zshrc +1 \&amp;quot;+set syntax=sh\&amp;quot; \&amp;quot;+Sex ~/.zsh\&amp;quot; \&lt;/span&gt;
&lt;span class="s2"&gt;          &amp;amp;&amp;amp; echo Sourcing... \&lt;/span&gt;
&lt;span class="s2"&gt;          &amp;amp;&amp;amp; source ~/.zshrc&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  This will give us a split editor, the top level browsing
  &lt;samp&gt;~/.zsh/&lt;/samp&gt;, the lower level editing &lt;samp&gt;~/.zshrc&lt;/samp&gt;; upon
  closing the files, it’ll source them back in.
&lt;/p&gt;
&lt;h3&gt;&lt;kbd&gt;gemdoc&lt;/kbd&gt;&lt;/h3&gt;
&lt;p&gt;
  We may miss our
  &lt;a href="/2008/06/12/bashfully-yours-gem-shortcuts.html"&gt;&lt;abbr class="acronym" title="Bourne Again SHell"&gt;BASH&lt;/abbr&gt; &lt;kbd&gt;gemdoc&lt;/kbd&gt;&lt;/a&gt;,
  but now we can rethink things:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72788"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.zsh/config&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;gem env gemdir&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="c"&gt;# we should cache this call&lt;/span&gt;

&lt;span class="c"&gt;# ~/.zsh/functions/gemdoc&lt;/span&gt;
open &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GEMPATH&lt;/span&gt;/doc/&lt;span class="nv"&gt;$1&lt;/span&gt;*&lt;span class="o"&gt;(&lt;/span&gt;om&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;/rdoc/index.html

&lt;span class="c"&gt;# ~/.zsh/functions/_gemdoc&lt;/span&gt;
&lt;span class="c"&gt;#compdef gemdoc&lt;/span&gt;
_files -W &lt;span class="nv"&gt;$GEMPATH&lt;/span&gt;/doc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Ah, we can even be a bit cleaner with that fancy glob.
&lt;/p&gt;
&lt;p&gt;
  For more on my setup, see my
  &lt;a href="http://github.com/stephencelis/dotfiles"&gt;dotfiles&lt;/a&gt;.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/7eDStRq8wW4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/10/24/ez-does-it-gemdoc.html</feedburner:origLink></entry>
  
  <entry>
    <title>Rails controllers, views &amp; variables</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/Y3JrmVkrT6A/rails-controllers-views-and-variables.html" />
    <updated>2008-09-06T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/09/06/rails-controllers-views-and-variables</id>
    <content type="html">&lt;p&gt;
  In object-oriented programming, an object uses instance variables to store
  private information. If you want to access an object’s instance variables,
  those variables should only be accessible through instance methods. At
  least, this is the expectation.
&lt;/p&gt;
&lt;p&gt;
  So when one dives into Rails, they may find it quite confusing when an
  instance variable set in a controller is also available in the view.
  Convenient, sure…but it somehow doesn’t feel true to Ruby. The controller
  and view are different objects with their own scopes, right?
&lt;/p&gt;
&lt;p&gt;
  How hard is it to be a purist? How can we tell Action Controller to be a
  little more discreet?
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# config/initializers/less_gossip.rb&lt;/span&gt;

&lt;span class="c1"&gt;# Stop sharing so much!&lt;/span&gt;
&lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_instance_variables_to_assigns&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Stop caring so much!&lt;/span&gt;
&lt;span class="no"&gt;ActionView&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assign_variables_from_controller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Now the controller has some privacy. Rails won’t force it to tell all its
  secrets to the view. The controller still needs to do its job, though, which
  likely involves retrieving data and serving it to the view. So how to we
  mediate the flow of information without instance variables? The same way
  Ruby usually does: attribute readers.
&lt;/p&gt;
&lt;p&gt;
  Let’s say we have a
  &lt;abbr class="acronym" title="Create, read, update and delete"&gt;CRUD&lt;/abbr&gt;
  controller for articles. &lt;code&gt;ArticlesController#index&lt;/code&gt; would
  normally assign &lt;code&gt;@articles&lt;/code&gt;, so let’s define a reader method,
  &lt;code&gt;articles&lt;/code&gt;, instead.
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# app/controllers/articles_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;articles&lt;/span&gt;
  &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Now we can call articles throughout the controller, and it will return what
  &lt;code&gt;@articles&lt;/code&gt; previously would have. Rails is pretty good about
  caching database queries, but that doesn’t mean we shouldn’t memoize as a
  best practice for optimization:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;articles&lt;/span&gt;
  &lt;span class="vi"&gt;@articles&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Ah, instance variables used as they were meant to be used.
&lt;/p&gt;
&lt;p&gt;
  So what about &lt;code&gt;@article&lt;/code&gt;? Doesn’t its value change depending on
  the action being called? We just have to be a little smarter. Several lines
  of &lt;code&gt;@article&amp;nbsp;=&amp;nbsp;Article.find(params[:id])&lt;/code&gt; wasn’t very
  &lt;abbr class="acronym" title="Don't repeat yourself"&gt;DRY&lt;/abbr&gt;, anyhow.
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
  &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:article&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  There we go. We’re accessing variables through getters! When we’re in the
  view, we only need to call those methods on the controller, which is
  available through &lt;code&gt;ActionView::Base#controller&lt;/code&gt;. Here’s an
  example:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="erb"&gt;&lt;span class="cp"&gt;&amp;lt;%#&lt;/span&gt;&lt;span class="c"&gt; app/views/articles/index.html.erb&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  What? That’s pretty ugly? And what about the controller public instance
  methods? They should refer to actions?
&lt;/p&gt;
&lt;p&gt;
  I guess we can’t completely ignore Rails’ conventions. We’ll have to make
  those getters private. But how, now, can we deliver these methods to the
  view? Luckily, Rails makes this easy with helpers:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# app/controllers/articles_controller.rb&lt;/span&gt;
&lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Now it looks nicer in the view, if a bit plainer than the &lt;code&gt;@&lt;/code&gt;
  decorations we’re all used to:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="erb"&gt;&lt;span class="cp"&gt;&amp;lt;%#&lt;/span&gt;&lt;span class="c"&gt; app/views/articles/index.html.erb&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  There are, actually, a few benefits to all this maneuvering (beyond clarity
  for the classically-trained Rubyist):
&lt;/p&gt;
&lt;dl&gt;
  &lt;dt&gt;Maintainability
  &lt;dd&gt;Any before filter you used, in the past, to set instance variables, is
    now irrelevant. You no longer have to worry about scoping it with
    &lt;code&gt;:only&lt;/code&gt; or &lt;code&gt;:except&lt;/code&gt;, or updating it when you add,
    remove, or rename actions.
  &lt;dt&gt;Cacheability
  &lt;dd&gt;These methods will only run when they’re first called during a request.
    If they only appear in the view, and the view is cached, you won’t hit the
    database.&lt;ins&gt;&lt;sup id="mark_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/ins&gt;
&lt;/dl&gt;
&lt;p&gt;
  Here’s our completed code:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72785"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

  &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;

  &lt;span class="c1"&gt;# render index, show, new, edit&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save!&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;articles_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_attributes!&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:article&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;articles_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;articles_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;articles&lt;/span&gt;
    &lt;span class="vi"&gt;@articles&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:article&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;ins title="2008-09-09"&gt;
      &lt;sup id="foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
      &lt;small&gt;
        Mike Burrows points out that if
        &lt;code&gt;ActiveRecord::RecordNotFound&lt;/code&gt; is raised in the template,
        you are given a 500 error in production.
        &lt;code&gt;ActionController::Rescue&lt;/code&gt; normally handles the 404s, while
        Action View wraps exceptions in its own &lt;code&gt;TemplateError&lt;/code&gt;
        (always 500), so—coupling aside—we just have to make the view more
        aware.
      &lt;/small&gt;
    &lt;/ins&gt;
  &lt;/p&gt;
  &lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="c1"&gt;# config/initializers/less_gossip.rb&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActionView&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Template&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;local_assigns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;local_assigns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt; &lt;span class="c1"&gt;# Ah. Here we are.&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;TemplateError&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub_template_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;TemplateError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/Y3JrmVkrT6A" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/09/06/rails-controllers-views-and-variables.html</feedburner:origLink></entry>
  
  <entry>
    <title>Bashfully yours, Migrations w/o Migraines</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/YS5v_IakZvw/bashfully-yours-migrations-without-migraines.html" />
    <updated>2008-08-07T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/08/07/bashfully-yours-migrations-without-migraines</id>
    <content type="html">&lt;p&gt;
  Let’s face it. The migration timestamps, nice for teams and conflicts, are a
  bit painful otherwise. You create a migration and want to open it quickly,
  but the tab-completion is awkward. Too many numbers (shared by too many
  files) gum up the whole process.
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;/samp&gt;&lt;kbd&gt;script/generate migration add_comments_count_to_blog_entry comments_count:integer
&lt;/kbd&gt;&lt;samp&gt;    create  db/migrate
    create  db/migrate/20080807210534_add_comments_count_to_blog_entry.rb
$ &lt;/samp&gt;&lt;kbd&gt;mate db&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;/&lt;/samp&gt;&lt;kbd&gt;m&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;igrate/&lt;/samp&gt;&lt;kbd&gt;2&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;0080&lt;/samp&gt;&lt;kbd&gt;&lt;kbd&gt;→&lt;/kbd&gt;&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
20080[...]
[...]
--More--
$ mate db/migrate/20080&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  And that’s just the beginning. Copypasta? Sure…but do I really have to take
  my fingers from the keyboard?
&lt;/p&gt;
&lt;p&gt;
  How about a better way, with &lt;samp&gt;~/.bash_profile&lt;/samp&gt;:
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72783"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.bash_profile&lt;/span&gt;

sg&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;migration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;script/generate &lt;span class="nv"&gt;$@&lt;/span&gt; | awk &lt;span class="s1"&gt;&amp;#39; /db\/migrate\//{print $NF}&amp;#39;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$migration&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="nv"&gt;$EDITOR&lt;/span&gt; &lt;span class="nv"&gt;$migration&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rake db:migrate; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;sgmo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sg model $@&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;sgmi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sg migration $@&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Let’s try it out.
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bash_profile
sgmi add_comments_count_to_blog_entry comments_count:integer
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure&gt;
  &lt;img alt="TextMate opens." src="http://img.skitch.com/20090302-grysuf555t37378ai894bekdpr.png"&gt;
&lt;/figure&gt;
&lt;p&gt;
  A quick edit, save, close, and…
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;(in ~/Code/blog/trunk)
== 20080807210534 AddCommentsCountToBlogEntry: migrating ======================
-- add_column(:blog_entries, :comments_count, :integer, {:default=&gt;0})
   -&gt; 0.0360s
== 20080807210534 AddCommentsCountToBlogEntry: migrated (0.0360s) =============&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Beautiful. Migration editing without migraines.
&lt;/p&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;ins title="2008-09-24"&gt;
      &lt;small&gt;
        Zubin Henner emailed me to let me know the script didn't work with the
        &lt;kbd&gt;-g&lt;/kbd&gt; or &lt;kbd&gt;-c&lt;/kbd&gt; flags. I've added a space to the
        beginning of the regular expression above to make sure the script only
        matches path output that &lt;em&gt;begins&lt;/em&gt; with &lt;samp&gt;db/&lt;/samp&gt;.
      &lt;/small&gt;
    &lt;/ins&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/YS5v_IakZvw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/08/07/bashfully-yours-migrations-without-migraines.html</feedburner:origLink></entry>
  
  <entry>
    <title>Bashfully yours, Gem Shortcuts</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/qqGR7yOoz6w/bashfully-yours-gem-shortcuts.html" />
    <updated>2008-06-12T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/06/12/bashfully-yours-gem-shortcuts</id>
    <content type="html">&lt;p&gt;
  To gain quick &lt;abbr class="acronym" title="Bourne Again SHell"&gt;BASH&lt;/abbr&gt;
  access to your RDocs, add these lines to your &lt;samp&gt;~/.bash_profile&lt;/samp&gt;
  (or &lt;span class="~/.bashrc, ~/.profile, whichever"&gt;equivalent&lt;/span&gt;):&lt;ins&gt;&lt;sup id="note_1"&gt;&lt;a href="#foot_1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/ins&gt;
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72782"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.bash_profile&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;gem env gemdir&lt;span class="sb"&gt;`&lt;/span&gt;

gemdoc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="nv"&gt;$GEMDIR&lt;/span&gt;/doc/&lt;span class="nv"&gt;$1&lt;/span&gt;*/rdoc/index.html&lt;span class="o"&gt;)&lt;/span&gt;
  open &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;gems&lt;/span&gt;&lt;span class="p"&gt;[@]: -1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;complete&lt;/span&gt; -W &lt;span class="s1"&gt;&amp;#39;$(`which ls` $GEMDIR/doc)&amp;#39;&lt;/span&gt; gemdoc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;
  Let’s try it out…
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bash_profile
gemdoc hpricot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure&gt;
  &lt;legend&gt;Yummy Hpricot docs, instantly.&lt;/legend&gt;
  &lt;img alt="" src="http://img.skitch.com/20090302-c4m97h8j29se2ujentfhndbeus.png"&gt;
&lt;/figure&gt;
&lt;p&gt;
  It will open the latest version, but you can specify, and tab completion
  simplifies the task:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;/samp&gt;&lt;kbd&gt;gemdoc P&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;arseTree-2.&lt;/samp&gt;&lt;kbd&gt;&lt;kbd&gt;→&lt;/kbd&gt;&lt;kbd&gt;→&lt;/kbd&gt;&lt;/kbd&gt;&lt;samp&gt;
ParseTree-2.1.1/  ParseTree-2.2.0/
$ gemdoc ParseTree-2.&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Great. All bases covered. Modify slightly if you want to open gems in your
  favorite editor. Replace &lt;kbd&gt;open&lt;/kbd&gt; with your favorite website-opening
  command if you’re not on OS X.
&lt;/p&gt;
&lt;p&gt;
  (A hat tip to &lt;a href="http://mislav.caboo.se"&gt;Mislav&lt;/a&gt; for the dotfile
  inspiration.)
&lt;/p&gt;
&lt;footer&gt;
  &lt;hr&gt;
  &lt;p&gt;
    &lt;ins title="2008-10-24"&gt;
      &lt;sup id="foot_1"&gt;&lt;a href="#mark_1"&gt;1&lt;/a&gt;&lt;/sup&gt;
      &lt;small&gt;
        I'm spending a lot more time with &lt;dfn&gt;the Z shell&lt;/dfn&gt; lately. For
        the curious,
        &lt;a href="/2008/10/24/ez-does-it-gemdoc.html"&gt;here’s a &lt;abbr&gt;zsh&lt;/abbr&gt;-based &lt;kbd&gt;gemdoc&lt;/kbd&gt;&lt;/a&gt;.
      &lt;/small&gt;
    &lt;/ins&gt;
  &lt;/p&gt;
&lt;/footer&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/qqGR7yOoz6w" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/06/12/bashfully-yours-gem-shortcuts.html</feedburner:origLink></entry>
  
  <entry>
    <title>Introducing Timeframe</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/s_yp_XB6NSQ/introducing-timeframe.html" />
    <updated>2008-04-21T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/04/21/introducing-timeframe</id>
    <content type="html">&lt;p&gt;
  &lt;a href="http://github.com/stephencelis/timeframe"&gt;Welcome to GitHub&lt;/a&gt;,
  little one. May you grow into something big and strong.
&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="http://stephencelis.github.com/timeframe/"&gt;&lt;img alt="" src="http://img.skitch.com/20090302-f827k68ujp7j1qk168bmmc1nsi.png"&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://stephencelis.github.com/timeframe/"&gt;More information and demo&lt;/a&gt;.
  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/MIT_License"&gt;MIT License&lt;/a&gt;, so
    do what you will.
  &lt;li&gt;I’m just sick of multiple date pickers on the same page.
&lt;/ul&gt;
&lt;p&gt;
  Download:
  &lt;a href="http://github.com/stephencelis/timeframe/zipball/master"&gt;&lt;img src="http://stephencelis.com/images/download-trans.png" class="download" alt="Download"&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/s_yp_XB6NSQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/04/21/introducing-timeframe.html</feedburner:origLink></entry>
  
  <entry>
    <title>Time-sensitive asset serving</title>
    <link href="http://feedproxy.google.com/~r/stephencelis/~3/LG3L6vd_HSw/time-sensitive-asset-serving.html" />
    <updated>2008-04-12T00:00:00-04:00</updated>
    <id>http://stephencelis.com/2008/04/12/time-sensitive-asset-serving</id>
    <content type="html">&lt;p&gt;
  I had a &lt;kbd&gt;cron&lt;/kbd&gt; job regularly sending new files to an asset host
  via &lt;kbd&gt;rsync&lt;/kbd&gt;. It reduced the load on the application server, but how
  could I ensure that new files were served properly before the asset server
  synchronized? Simply.
&lt;/p&gt;
&lt;aside class="gisted" id="gisted-72775"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# config/environments/production.rb&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asset_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;assets.example.com&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;[/&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="vg"&gt;$/&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;img src="http://feeds.feedburner.com/~r/stephencelis/~4/LG3L6vd_HSw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://stephencelis.com/2008/04/12/time-sensitive-asset-serving.html</feedburner:origLink></entry>
  
</feed>
