<?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">

  <title>Mike Mayo</title>
  
  <link href="http://mikemayo.org/" />
  <updated>2012-12-21T12:03:12-06:00</updated>
  <id>http://mikemayo.org/</id>
  <author>
    <name>Jeff Mike Mayo</name>
  </author>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/mikemayo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="mikemayo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title type="html">Deploying Jekyll sites to Heroku with Rack-Jekyll</title>
    <link href="http://mikemayo.org/2012/deploying-jekyll-sites-to-heroku-with-rack-jekyll" />
    <id>http://mikemayo.org/2012/deploying-jekyll-sites-to-heroku-with-rack-jekyll</id>
    <updated>2012-02-08T00:00:00-06:00</updated>
    <content type="html">
      &lt;p class="note"&gt;Note: Check out my &lt;a href="http://dev.twinenginelabs.com/2012/How-to-make-a-blog-post-with-Jekyll/"&gt;article on the Twin Engine Labs engineering blog&lt;/a&gt; for some Jekyll highlights and a mini-guide on creating your first blog post.&lt;/p&gt;
&lt;p&gt;This will just a quick guide to show how to get your Jekyll site going on &lt;a href="http://heroku.com"&gt;Heroku&lt;/a&gt;.  I&amp;#8217;m going to be working off the assumption that you&amp;#8217;ve already got a Heroku account setup, so I won&amp;#8217;t be going through any of that here.&lt;/p&gt;
&lt;p&gt;First you need to install &lt;a href="http://gembundler.com"&gt;Bundler&lt;/a&gt; and add a Gemfile to your project if you don&amp;#8217;t already have one. The gem we need is called &lt;a href="https://github.com/adaoraul/rack-jekyll"&gt;Rack-Jekyll&lt;/a&gt;.  It basically just provides a little Rack middleware to serve your statically-generated site to Heroku&amp;#8217;s thins.  Unfortunately the latest version in Rubygems depends on some very old versions of gems so you&amp;#8217;ll need to install from git.&lt;/p&gt;
&lt;p&gt;Add the following line to your Gemfile:&lt;/p&gt;
&lt;div class="longer"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rack-jekyll&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:git&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://github.com/adaoraul/rack-jekyll.git&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:require&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rack/jekyll&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Next create a file named &lt;code&gt;config.ru&lt;/code&gt; in your project, if it doesn&amp;#8217;t already exist, add the following to it:&lt;/p&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="s1"&gt;&amp;#39;bundler&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;Bundler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:production&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Jekyll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The guide on GitHub is different than the above advice, but I kept getting errors when it tried to require &amp;#8216;rack/jekyll&amp;#8217; until I modified my &lt;code&gt;config.ru&lt;/code&gt; to look like this.&lt;/p&gt;
&lt;p&gt;Now you should be clear to deploy to Heroku as usual (&lt;code&gt;git push heroku master&lt;/code&gt;).&lt;/p&gt;
&lt;h4&gt;An interesting sidenote&lt;/h4&gt;
&lt;p&gt;Up until recently I was deploying my site with rack-jekyll version 0.3.5 (current version in RubyGems is 0.3.7). For a long time I was experiencing an issue where any images I uploaded (after switching to this deploy method) had the bottom 10% or so cut off when served from Heroku. At first it was just a single image and I thought it just a fluke (and I hadn&amp;#8217;t written a new blog post in a long time), so I didn&amp;#8217;t mess with it. But then with my latest blog post I ran into the same issue again.&lt;/p&gt;
&lt;p&gt;I finally contacted Heroku support, and after a bit of back-and-forth they determined that Rack-Jekyll was responding with an incorrect &lt;code&gt;Content-Length&lt;/code&gt; header. I tried upgrading to 0.3.7 immediately, but the RubyGems version called a whole new slew of headaches, so I gave up and dug into the code. Turned out that the old version was reading in the file, turning the body into a string, calling &lt;code&gt;.length&lt;/code&gt; off that string, and passing that as the content length. This is the incorrect way to handle this, and there are a couple of better ways to do it.  Since we&amp;#8217;re reading the file in anyways, an easy way is just to use &lt;code&gt;file.size&lt;/code&gt;.  Another option, if you&amp;#8217;re using a string, is to call &lt;code&gt;"string".bytesize&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Anyways, I eventually discovered that the version of Rack-Jekyll on GitHub had been updated to current versions of the important gems, and already had the fix in place, so I just switched over to using that instead.&lt;/p&gt;
&lt;p&gt;Cool story bro.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">How I learned to stop worrying and love REST</title>
    <link href="http://mikemayo.org/2012/how-i-learned-to-stop-worrying-and-love-rest" />
    <id>http://mikemayo.org/2012/how-i-learned-to-stop-worrying-and-love-rest</id>
    <updated>2012-02-04T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;&lt;img src="/images/rest_strangelove.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Buzzwords can be a funny thing. I&amp;#8217;ve been writing (what I thought were) &amp;#8216;RESTful&amp;#8217; web apps and APIs for five years now, and it wasn&amp;#8217;t until a couple of weeks ago that I really began to understand what that meant. I&amp;#8217;d like to share my &amp;#8216;&lt;span class="caps"&gt;AHA&lt;/span&gt;&amp;#8217; moment, and give a concrete example of why following the &lt;a href="http://en.wikipedia.org/wiki/Representational_state_transfer"&gt;&lt;span class="caps"&gt;REST&lt;/span&gt;&lt;/a&gt; style correctly can save you headaches in the long run.&lt;/p&gt;
&lt;div id="tldr"&gt;
&lt;p&gt;&lt;em&gt;TL;DR: A RESTful &lt;span class="caps"&gt;API&lt;/span&gt; should provide hypertext links to drive traversal through itself, instead of forcing the client to craft their own URIs.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Many have complained about the font on my site, but I personally like it. If you&amp;#8217;re having trouble with it though, just click &lt;a href="javascript:void(0)" id="font-changer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;A little backstory&lt;/h3&gt;
&lt;p&gt;At &lt;a href="http://www.twinenginelabs.com"&gt;Twin Engine Labs&lt;/a&gt;, we develop iOS apps that are generally backed by Rails &lt;span class="caps"&gt;REST&lt;/span&gt; APIs. We&amp;#8217;ve been doing this for a little over a year now, and are constantly refining our process. A few weeks ago I built my first iOS app (which got approved this week) as well as the &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; backend for it. I take a lot of pride in my code, and I have to say I was quite pleased with how everything turned out. The project felt clean, things were refactored as I felt they needed to be, and nothing was overly complex or ugly.  However, at the end of the project lifecycle, I started looking to increase performance by adding basic Rails caching where it was appropriate, and things took an unhappy turn.&lt;/p&gt;
&lt;p&gt;At this point, the iOS app was complete and had been submitted to the app store. If you&amp;#8217;ve ever gone through this process, you know the delays can be&amp;#8230;annoying, and resubmitting is essentially out of the question if you have a deadline to worry about. None of this should have been a problem, since the &lt;span class="caps"&gt;API&lt;/span&gt; was frozen and I was just making internal performance changes, but then I started looking at caching one of the main actions of the application.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s a fairly simple index action that returns a list of &lt;span class="caps"&gt;JSON&lt;/span&gt; objects, but the rub comes in that it&amp;#8217;s paginated. This action is consumed by a TableView that has infinite scrolling on it, so we only load 25 at a time to make things snappier on the iPhone. We handle all of our pagination using the wonderful &lt;a href="https://github.com/mislav/will_paginate"&gt;will_paginate&lt;/a&gt; gem, where page information is passed as query params like: &lt;code&gt;www.myapi.com/index_action?page=1&amp;amp;per_page=25&lt;/code&gt;. Unfortunately default Rails page caching doesn&amp;#8217;t store query params, so you&amp;#8217;ll always cache the first page a user hits. The &lt;a href="http://guides.rubyonrails.org/caching_with_rails.html#page-caching"&gt;suggested means of dealing with this&lt;/a&gt; is to, instead of using query params, pass your pagination params through the &lt;span class="caps"&gt;URI&lt;/span&gt;, transforming the above example to this: &lt;code&gt;www.myapi.com/index_action/page/1/per_page/25&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This would be trivial to implement on the Rails side, but since my iOS application was crafting these paginated URIs it would mean a change to the iOS code and a resubmission to the app store.  The action was fast enough that I moved caching it to a lower priority, but it ate at me that I hadn&amp;#8217;t known about the pitfall earlier.&lt;/p&gt;
&lt;h3&gt;The &lt;span class="caps"&gt;AHA&lt;/span&gt; moment&lt;/h3&gt;
&lt;p&gt;It wasn&amp;#8217;t until several weeks later that I came upon the perfect solution to my problem&amp;#8230;at least it would have been had I used it from the beginning as I should have.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve got about a 30 minute bike commute every morning, and I find the best use of that time is to listen to tech podcasts. More specifically I&amp;#8217;ve been listening to the &lt;a href="http://www.rubyrogues.com"&gt;Ruby Rogues&lt;/a&gt; podcast for the past few weeks; catching up on the backlog as well as keeping up with the latest episodes as they come out. Recently I listened to the &lt;a href="http://rubyrogues.com/rest-done-right-with-steve-klabnik/"&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; Done Right&lt;/a&gt; episode where they had Steve Klabnik on as a guest panelist. If you follow Steve on &lt;a href="https://twitter.com/#!/steveklabnik"&gt;twitter&lt;/a&gt; or read his &lt;a href="http://blog.steveklabnik.com/"&gt;blog&lt;/a&gt;, you&amp;#8217;ll know he&amp;#8217;s a big proponent of &lt;span class="caps"&gt;REST&lt;/span&gt; and does a lot to educate developers on its proper usage.&lt;/p&gt;
&lt;p&gt;In that podcast they mentioned that one of the core points of &lt;span class="caps"&gt;REST&lt;/span&gt; is that the resources should provide the means to traverse the &lt;span class="caps"&gt;API&lt;/span&gt;. Think of it like links on a webpage; we don&amp;#8217;t expect the user to know our &lt;span class="caps"&gt;URL&lt;/span&gt; format and manually type it in when they want to view the next link. Instead we provide them hyperlinks so they can easily traverse our sites. A &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; should function the same way; when you provide someone a list of &lt;span class="caps"&gt;JSON&lt;/span&gt; objects, you should also provide the &lt;span class="caps"&gt;URI&lt;/span&gt; to access each of those objects, or, in the case of my pagination example, the &lt;span class="caps"&gt;URI&lt;/span&gt; to retrieve the next page of results. To quote Roy Fielding:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; should be entered with no prior knowledge beyond the initial &lt;span class="caps"&gt;URI&lt;/span&gt; (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the &lt;span class="caps"&gt;API&lt;/span&gt;). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. &lt;sup&gt;&lt;a href="#footnote1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Steve Klabnik also talks about this very issue in his wonderful article titled &lt;a href="http://timelessrepo.com/haters-gonna-hateoas"&gt;Haters gonna &lt;span class="caps"&gt;HATEOAS&lt;/span&gt;&lt;/a&gt;.  (&lt;span class="caps"&gt;HATEOAS&lt;/span&gt; stands for &amp;#8216;Hypertext As The Engine Of Application State&amp;#8217; and refers to using hypertext to direct an &lt;span class="caps"&gt;API&lt;/span&gt; consumer through the application).  You should definitely read his article to get a great explanation of how it should work and how/why most people aren&amp;#8217;t currently doing it.&lt;/p&gt;
&lt;p&gt;So while listening to this podcast, somewhere on the bike path between the office and home, it hit me: Instead of crafting the paginated &lt;span class="caps"&gt;URI&lt;/span&gt; in my iOS client, I should have been crafting that &lt;span class="caps"&gt;URI&lt;/span&gt; on the Rails side and sending it through along with my list of &lt;span class="caps"&gt;JSON&lt;/span&gt; objects. I&amp;#8217;d actually dealt with this exact format on the iOS side when I was consuming the Facebook search &lt;span class="caps"&gt;API&lt;/span&gt;. Here is an example of how the Facebook Graph &lt;span class="caps"&gt;API&lt;/span&gt; handles pagination:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#http://graph.facebook.com/search?type=Page&amp;amp;q=dcuocentral&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;data&amp;quot;&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="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;DCUO Central&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Website&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;141968085865824&amp;quot;&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="s2"&gt;&amp;quot;paging&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;next&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://graph.facebook.com/search?type=Page&amp;amp;q=dcuocentral&amp;amp;limit=25&amp;amp;offset=25&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All you have to do is pluck the &lt;code&gt;paging&lt;/code&gt; key out of the &lt;span class="caps"&gt;JSON&lt;/span&gt; and hit that &lt;span class="caps"&gt;URI&lt;/span&gt; for your next page (though they annoyingly provide that &lt;span class="caps"&gt;URI&lt;/span&gt; even if there are no more records to be returned).&lt;/p&gt;
&lt;p&gt;By following the &lt;span class="caps"&gt;REST&lt;/span&gt; style, I would have saved myself either &lt;em&gt;A)&lt;/em&gt; having to alter my iOS code and resubmit to the store, or &lt;em&gt;B)&lt;/em&gt; time spent researching alternate caching methods and implementing them in Rails. As it stands, my partially-RESTful &lt;span class="caps"&gt;API&lt;/span&gt; is going to cost me (and possibly the client) more time before we can call the project finished.&lt;/p&gt;
&lt;p&gt;All of that said, I think that Rails does an amazing job of making it easy to implement &lt;span class="caps"&gt;REST&lt;/span&gt;. I&amp;#8217;ve been doing a large part of it without even really understanding it. I&amp;#8217;m not sure how well it works when you want to go all the way, but that&amp;#8217;s something I intend to explore as I learn more about &lt;span class="caps"&gt;REST&lt;/span&gt; and build APIs in the months to come. I&amp;#8217;m also eagerly awaiting Steve Klabnik&amp;#8217;s book &lt;a href="http://getsomere.st/"&gt;Get Some Rest&lt;/a&gt;, which looks to be a great resource on developing RESTful applications in Rails as well as explaining the details of &lt;span class="caps"&gt;REST&lt;/span&gt; in a more approachable way.&lt;/p&gt;
&lt;div id="post_footer"&gt;
&lt;h4&gt;Footnotes&lt;/h4&gt;
&lt;ol&gt;
	&lt;li id="footnote1"&gt;&lt;a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven"&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; APIs must be hypertext-driven&lt;/a&gt;, Roy Fielding&lt;br /&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">Rendering a collection of partials with layouts and content_for</title>
    <link href="http://mikemayo.org/2012/rendering-a-collection-of-partials-with-content_for" />
    <id>http://mikemayo.org/2012/rendering-a-collection-of-partials-with-content_for</id>
    <updated>2012-02-02T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;While working on a Rails project recently, I ran into an interesting dilemma when trying to &lt;span class="caps"&gt;DRY&lt;/span&gt; up a big mess of partials that I had accumulated over several months.  Below I&amp;#8217;ll describe the scenario and show a way to get around some of the limitations in default Rails partial rendering.&lt;/p&gt;
&lt;h3&gt;The Problem:&lt;/h3&gt;
&lt;p&gt;You have several partials in your Rails project that are nearly identical, and you&amp;#8217;re sick of all this un-&lt;span class="caps"&gt;DRY&lt;/span&gt; code laying around. Some (or all) of these partials can be loaded multiple times on a single page via a collection of objects. Never fear, Rails has a solution for you (sort of)!&lt;/p&gt;
&lt;h4&gt;Did you know:&lt;/h4&gt;
&lt;p&gt;Partials can be &lt;a href="http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials"&gt;rendered with a layout&lt;/a&gt;? I know, my mind was blown too! The only caveat I&amp;#8217;ve found is that the layout file needs to be in the same directory as the partial, as opposed to the layouts directory, though I&amp;#8217;m not sure if this is a hard rule or just the default behavior.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= render :partial =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;my_partial_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:layout&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;my_layout_file&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Another fun fact, you can call:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= render :partial =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;my_partial_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:collection&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@my_collection_of_objects&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or if the objects in your collection have a class name that matches your partial name:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="vi"&gt;@my_collection_of_objects&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and Rails will render each of those objects into the partial.  Supposedly this is faster than looping over the objects and rendering manually, since Rails only has to lookup the partial once. One downside is that you can&amp;#8217;t (as far as I can tell) also pass a layout to this method call.&lt;/p&gt;
&lt;p&gt;Anyways on to solving the problem at hand&amp;#8230;&lt;/p&gt;
&lt;h3&gt;The Solution:&lt;/h3&gt;
&lt;p&gt;The most obvious solution to &lt;span class="caps"&gt;DRY&lt;/span&gt; up similar partials is to use the layout parameter and move all your repetitive markup to a layout view. Sometimes things don&amp;#8217;t get to be that simple, though. If, for instance, you want to have a named yield inside your partial layout, you&amp;#8217;ll quickly find yourself frustrated. Here&amp;#8217;s an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# _layout.html.erb&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;special_content&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= yield :special_content %&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;div id=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="sx"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;# _partial.html.erb&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;% content_for &lt;/span&gt;&lt;span class="ss"&gt;:special_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;This is very special&amp;#39;&lt;/span&gt; &lt;span class="sx"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;This&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;special&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For some reason, named yields inside partial layouts don&amp;#8217;t behave correctly. Instead of your expected output, you&amp;#8217;ll end up with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;special_content&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is not so special&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is not so special&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After digging around in the code, I found that you can call &lt;code&gt;content_for&lt;/code&gt; in the place of &lt;code&gt;yield&lt;/code&gt; with only the name argument and achieve similar results, however this has another issue which will require a little backstory to explain.&lt;/p&gt;
&lt;p&gt;The content for views is handled by what Rails calls a &lt;code&gt;ViewFlow&lt;/code&gt;. It exposes methods for a &lt;code&gt;content&lt;/code&gt; hash, and &lt;code&gt;yield&lt;/code&gt; and &lt;code&gt;content_for&lt;/code&gt; subsequently use those methods to access and populate the content. However when you access that content, it&amp;#8217;s not destructive; it never removes the content from that hash. This causes a problem if you&amp;#8217;re using &lt;code&gt;content_for&lt;/code&gt; in a loop, because every call you&amp;#8217;re just tacking more content onto the same hash key.&lt;/p&gt;
&lt;p&gt;What you really need for the above scenario is a way to, when accessing the content from the &lt;code&gt;ViewFlow&lt;/code&gt;, remove it from that hash so you have a clean slate on the next iteration. This is actually trivial to accomplish because the &lt;code&gt;ViewFlow&lt;/code&gt;, and therefore it&amp;#8217;s &lt;code&gt;content&lt;/code&gt; hash, are available in the view. Just add a method like this to your &lt;code&gt;ApplicationHelper&lt;/code&gt; and use it in place of your normal named yields:&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;yield_content!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;view_flow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_key&lt;/span&gt;&lt;span class="p"&gt;)&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 when looping through your collection and rendering your partials, your content should render as expected. My next goal is to get layouts behaving with rendering partials using the &lt;code&gt;:collection&lt;/code&gt; param, though I think I may have different behavior expectations than the Rails designers do on that topic.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">Using Decorators to improve your Inherited Resources experience</title>
    <link href="http://mikemayo.org/2011/using-decorators-to-improve-inherited-resources" />
    <id>http://mikemayo.org/2011/using-decorators-to-improve-inherited-resources</id>
    <updated>2011-12-22T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;At &lt;a href="http://www.twinenginelabs.com"&gt;Twin Engine Labs&lt;/a&gt; we recently discovered the joy that is Jose Valim&amp;#8217;s &lt;a href="https://github.com/josevalim/inherited_resources"&gt;Inherited Resources&lt;/a&gt;.  For the unfamiliar, it takes all those generic &lt;span class="caps"&gt;REST&lt;/span&gt; actions and views and abstracts them all out for you, so your controllers simply inherit from &lt;code&gt;InheritedResources::Base&lt;/code&gt; and you get the basics for free.  For us, that means that a large portion of our web app admins are already written for us; we just tweak as needed.&lt;/p&gt;
&lt;p&gt;My one real gripe, thus far, has been that the generated views Inherited Resources gives you are just too generic.  It defaults to displaying all the &lt;code&gt;attributes&lt;/code&gt; for an ActiveRecord resource on the form, show, and index pages, and many of those fields are simply of no use.  We use &lt;a href="https://github.com/thoughtbot/paperclip"&gt;Paperclip&lt;/a&gt; for all of our file attachments, which adds 4 database fields to represent each attachment (for an attachment named &lt;code&gt;image&lt;/code&gt; you end up with &lt;code&gt;image_file_name&lt;/code&gt;, &lt;code&gt;image_content_type&lt;/code&gt;, &lt;code&gt;image_file_size&lt;/code&gt;, and &lt;code&gt;image_updated_at&lt;/code&gt;).  None of these fields needs to actually be displayed to the user, nor will the users ever edit them directly.&lt;/p&gt;
&lt;p&gt;Then there&amp;#8217;s default Rails fields like &lt;code&gt;created_at&lt;/code&gt; and &lt;code&gt;updated_at&lt;/code&gt;, plus all your foreign keys for &lt;code&gt;belongs_to&lt;/code&gt; associations.  While you may want to display the date fields, you generally don&amp;#8217;t want those editable by a user, and I&amp;#8217;d rather show the &lt;code&gt;belongs_to&lt;/code&gt; association directly than the foreign key.  On top of this, we use &lt;a href="https://github.com/justinfrench/formtastic"&gt;Formtastic&lt;/a&gt; for generating forms, so if I could build a more reliable list of attributes and associations that were editable by a user, I could just hand them off to &lt;code&gt;semantic_form_for&lt;/code&gt; and let it works its magic.&lt;/p&gt;
&lt;p&gt;Enter the &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;Decorator&lt;/a&gt; pattern.  By creating a generic decorator to wrap my &lt;code&gt;ActiveRecord&lt;/code&gt; resource_classes, I could use Rails&amp;#8217; magic to get a more refined list, then just use that decorator in all the Inherited Resources views.  My base Decorator looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;InheritedResources&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Decorator&lt;/span&gt;
  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@klass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klass&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;form_attributes&lt;/span&gt;
      &lt;span class="n"&gt;edit_attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;editable_attributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&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="sr"&gt;/created_at|updated_at/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;edit_attrs&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;belongs_to_associations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;paperclip_attachments&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;show_attributes&lt;/span&gt;
      &lt;span class="n"&gt;editable_attributes&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;index_attributes&lt;/span&gt;
      &lt;span class="n"&gt;editable_attributes&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;editable_attributes&lt;/span&gt;
      &lt;span class="n"&gt;assocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;belongs_to_associations&lt;/span&gt;
      &lt;span class="n"&gt;attach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paperclip_attachments&lt;/span&gt;
      &lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;^id$&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;assocs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:foreign_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;assocs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blank?&lt;/span&gt;
      &lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;attach_attachments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blank?&lt;/span&gt;
      &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribute_names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&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;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:to_sym&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;belongs_to_associations&lt;/span&gt;
      &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reflect_on_all_associations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;macro&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:belongs_to&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;paperclip_attachments&lt;/span&gt;
      &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachment_definitions&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachment_definitions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="p"&gt;:&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;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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&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;p&gt;Next I added a helper method to our &lt;code&gt;ResourceController&lt;/code&gt; which all of our admin controllers inherit from:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:decorated_resource_class&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorated_resource_class&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;InheritedResources::&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;resource_class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;Decorator&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constantize&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="n"&gt;resource_class&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;InheritedResources&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Decorator&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="n"&gt;resource_class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you&amp;#8217;ll notice, I first try to instantiate a resource_class-specific version of the decorator, because I wanted to be able to subclass and override methods as needed.  Finally I just went through all the generated resource views and replaced &lt;code&gt;resource_class&lt;/code&gt; with &lt;code&gt;decorated_resource_class&lt;/code&gt; and used the relevant methods to provide the attributes I wanted (e.g: &lt;code&gt;#form_attributes&lt;/code&gt; in &lt;code&gt;_form.html.erb&lt;/code&gt;, &lt;code&gt;#show_attributes&lt;/code&gt; in &lt;code&gt;show.html.erb&lt;/code&gt;, etc&amp;#8230;).&lt;/p&gt;
&lt;p&gt;What this means is that, at least for the basic, generic pages, I no longer have to override the provided views to get the desired output.  And if I find these sane defaults don&amp;#8217;t work, but I don&amp;#8217;t need anything really custom, I can just subclass the Decorator for the specific &lt;code&gt;resource_class&lt;/code&gt; and override the methods as needed.  An example I immediately ran into was our User pages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;InheritedResources&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDecorator&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Decorator&lt;/span&gt;
    
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index_attributes&lt;/span&gt;
      &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:last_name&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="ss"&gt;:current_city&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;def&lt;/span&gt; &lt;span class="nf"&gt;show_attributes&lt;/span&gt;
      &lt;span class="n"&gt;index_attributes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;[.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&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;def&lt;/span&gt; &lt;span class="nf"&gt;form_attributes&lt;/span&gt;
      &lt;span class="n"&gt;show_attributes&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;[.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&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;p&gt;Of course, this won&amp;#8217;t cover 100% of the cases, but I found it covers 80% &amp;#8211; 90% of the views we use in a standard admin.  The rest are so customized that over-riding the views is the only option anyway.  I considered gemifying this, or making it a pull request for Inherited Resources, but since it&amp;#8217;s built around our development environment, I think for now I&amp;#8217;ll leave it as is.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">Automatically Cached Rake Routes and Annotated Models</title>
    <link href="http://mikemayo.org/2011/auto-cached-rake-routes-and-auto-annotated-models" />
    <id>http://mikemayo.org/2011/auto-cached-rake-routes-and-auto-annotated-models</id>
    <updated>2011-12-14T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;If you&amp;#8217;ve spent any time developing a Rails application, you&amp;#8217;re likely familiar with the command &lt;code&gt;rake routes&lt;/code&gt;. If you&amp;#8217;re not, this little marvel will greatly simplify your dev experience, as it prints out all the available routes in your application and their associated path helpers.&lt;/p&gt;
&lt;p&gt;However, as of late it has slowed down considerably.  I&amp;#8217;m not sure if it was with the changes in Ruby 1.9.2 or Rails 3, but running that command will take a ridiculous amount of time depending on the complexity of your project.&lt;/p&gt;
&lt;p&gt;For a base Rails project (I literally just ran &lt;code&gt;rails base_rails&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  $ time rake routes&lt;/span&gt;
&lt;span class="go"&gt;    /:controller/:action/:id           &lt;/span&gt;
&lt;span class="go"&gt;    /:controller/:action/:id(.:format) &lt;/span&gt;
&lt;span class="go"&gt;  real	0m1.969s&lt;/span&gt;
&lt;span class="go"&gt;  user	0m1.541s&lt;/span&gt;
&lt;span class="go"&gt;  sys	0m0.200s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For a moderately-sized Rails project (a client project I&amp;#8217;m currently working on):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  $ time rake routes&lt;/span&gt;
&lt;span class="go"&gt;  ... lots of routes ...&lt;/span&gt;
&lt;span class="go"&gt;  real	0m29.664s&lt;/span&gt;
&lt;span class="go"&gt;  user	0m14.373s&lt;/span&gt;
&lt;span class="go"&gt;  sys	0m2.039s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nearly 30 seconds just to get a list of the available routes, completely unacceptable.&lt;/p&gt;
&lt;p&gt;I set out yesterday with the idea of caching the output of this command in a temporary file, and to print out the cached version as long as the routes file hadn&amp;#8217;t been updated since the last cache time.  Unfortunately overwriting a Rake task isn&amp;#8217;t as easy as it should be, so I accomplished this goal with a simple Ruby script in the project directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

  &lt;span class="n"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;config/routes.rb&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;config/routes/*.rb&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;temp_f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tmp/routes&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_f&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;any?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_f&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_line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nb"&gt;require&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;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;../config/application&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Rakefile&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;orig_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
    &lt;span class="vg"&gt;$stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;routes&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;
    &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
    &lt;span class="vg"&gt;$stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orig_stdout&lt;/span&gt;
    &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_f&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_line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;While this worked, I hated that I was having to adjust to running a new command, and it meant that, if I added new routes, I was still 30 seconds away from seeing what my path helpers were.  The ideal was to have the routes cached automatically as soon as I changed my routes file.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="https://github.com/guard/guard"&gt;Guard&lt;/a&gt; and &lt;a href="https://github.com/guard/guard-annotate"&gt;Guard-Annotate&lt;/a&gt;.  Guard is a Ruby gem that wraps file observer functionality across all platforms, and Guard-Annotate is a module for Guard that hooks into &lt;a href="https://github.com/ctran/annotate_model"&gt;Annotate&lt;/a&gt;.  Annotate allows you to add the schema of your models as comments to the bottom of the model file, as well as add the output of &lt;code&gt;rake routes&lt;/code&gt; to the bottom of your routes.rb.&lt;/p&gt;
&lt;p&gt;With those 2 gems, I could just create a Guardfile in my project directory, and run &lt;code&gt;guard start&lt;/code&gt; alongside my Rails server and have all the annotations performed automatically for me.  This is a giant step in the right direction, but I also didn&amp;#8217;t want to have to run another daemon (as undoubtedly I&amp;#8217;d forget to run it 90% of the time).&lt;/p&gt;
&lt;p&gt;Another issue I ran into: Guard-Annotate was simply shelling out to &lt;code&gt;bundle exec annotate&lt;/code&gt;, which in turn was shelling out to &lt;code&gt;rake routes&lt;/code&gt; for the routes portion of the annotation.  This meant that I was still 30 seconds away from savings my routes.rb and seeing the updated annotations.  Plus there was really no need to load the entire Rails stack again (via Rake) when this is all happening in the context of a running Rails app.&lt;/p&gt;
&lt;p&gt;My solution came in a few steps:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Run &lt;code&gt;Guard.start(:notify =&amp;gt; true)&lt;/code&gt; in a thread that I spawn inside &lt;code&gt;development.rb&lt;/code&gt;.  That way Guard is run automatically when I launch my server in the dev environment.&lt;/li&gt;
	&lt;li&gt;I decided to cache the routes to a tempfile instead of annotating &lt;code&gt;routes.rb&lt;/code&gt; since it can get fairly lengthy and most of the devs I work with are used to using &lt;code&gt;rake routes&lt;/code&gt; anyways.&lt;/li&gt;
	&lt;li&gt;Create my own Guard extensions to handle Route caching.  I ripped out all the code from the &lt;code&gt;rake routes&lt;/code&gt; task and included it in the extension so no more loading another environment or shelling out unnecessarily.&lt;/li&gt;
	&lt;li&gt;Create another extension to handle Model annotations (since that was taking &amp;gt; 15 seconds as well due to shelling out to &lt;code&gt;annotate&lt;/code&gt;).&lt;/li&gt;
	&lt;li&gt;Hack my &lt;code&gt;Rakefile&lt;/code&gt; to bypass loading the environment if my cached routes file exists, and just print out its contents.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The code is a little too long to include here, so instead I&amp;#8217;ve provided &lt;a href="http://pastie.org/3017353"&gt;this pastie&lt;/a&gt; with all the relevant bits.&lt;/p&gt;
&lt;p&gt;The final outcome: Routes are cached within 0.15 seconds of saving &lt;code&gt;routes.rb&lt;/code&gt;, models updated within 0.25 seconds of updating &lt;code&gt;schema.rb&lt;/code&gt;, faster than I was able to switch to the relevant file or ALT+Tab to my terminal.  And rake routes?  See for yourself:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  $ time rake routes&lt;/span&gt;
&lt;span class="go"&gt;  #== Route Map&lt;/span&gt;
&lt;span class="go"&gt;  # Generated on 13 Dec 2011 23:59&lt;/span&gt;
&lt;span class="go"&gt;  #&lt;/span&gt;
&lt;span class="go"&gt;  ... lots of routes ...&lt;/span&gt;
&lt;span class="go"&gt;  real	0m0.676s&lt;/span&gt;
&lt;span class="go"&gt;  user	0m0.249s&lt;/span&gt;
&lt;span class="go"&gt;  sys	0m0.065s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">AutoHyde 0.1.1 Released</title>
    <link href="http://mikemayo.org/2010/auto-hyde-released" />
    <id>http://mikemayo.org/2010/auto-hyde-released</id>
    <updated>2010-12-10T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;With the launch of this blog, I&amp;#8217;ve recently come to enjoy the wonder that is &lt;a href="https://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt;.  For those unfamiliar, it&amp;#8217;s a dead-simple, blog-aware, static site generator built with Ruby, and is even used by GitHub for their Pages.&lt;/p&gt;
&lt;p&gt;My only complaint has been with automating the site regeneration and deployment.  I wanted a way to easily integrate it with GitHub&amp;#8217;s post-receive hooks so that the site is pulled and regenerated on my server after any code is pushed.&lt;/p&gt;
&lt;p&gt;AutoHyde makes that all possible.  Once installed, all you need to do is run the executable (with appropriate options) and it will start up a lightweight Sinatra server with a single route, &amp;#8216;/auto-hyde.&amp;#8217;  Then just point your GitHub post-receive hook at &lt;code&gt;http://your-server.com/auto-hyde&lt;/code&gt; and you&amp;#8217;re ready to go.&lt;/p&gt;
&lt;p&gt;Here is a list of the options available from the command-line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  $ auto-hyde -h&lt;/span&gt;
&lt;span class="go"&gt;  Usage: auto-hyde [options]&lt;/span&gt;
&lt;span class="go"&gt;    -e, --email EMAIL     Send email notification of failures to this email address&lt;/span&gt;
&lt;span class="go"&gt;    -d, --jekyll-dir DIR  Location of your Jekyll project directory, defaults to this dir&lt;/span&gt;
&lt;span class="go"&gt;    -b, --build-dir DIR   Location Jekyll will build your site to, defaults to &amp;#39;./_site&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;    -p, --port PORT       Port for Sinatra to run on, defaults to 4567&lt;/span&gt;
&lt;span class="go"&gt;        --pygments        Turn on Pygment syntax highlighting for Jekyll, defaults to off&lt;/span&gt;
&lt;span class="go"&gt;    -h, --help            Show this message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The most important options are &lt;code&gt;-j&lt;/code&gt; and &lt;code&gt;-b&lt;/code&gt;, your Jekyll blog directory and the directory you want the site generated in respectively.  When the route is hit, it will &lt;code&gt;cd&lt;/code&gt; into your blog dir, &lt;code&gt;git pull&lt;/code&gt;, and then use the &lt;code&gt;jekyll&lt;/code&gt; command line to regenerate the site.&lt;/p&gt;
&lt;p&gt;The gem is already available via Gemcutter/Rubygems, just run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  $ gem install auto-hyde&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;#8217;re interested, the code is also up on my &lt;a href="https://github.com/gotmayonase/auto-hyde"&gt;GitHub repo&lt;/a&gt;.  I must admit that I haven&amp;#8217;t tested the email functionality yet (it uses Pony), as my &lt;span class="caps"&gt;ISP&lt;/span&gt; won&amp;#8217;t allow &lt;span class="caps"&gt;SMTP&lt;/span&gt; out.  So if anyone notices a bug there, or anywhere else, please let me know.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">Node.js: Socket.IO and Buffer quirks</title>
    <link href="http://mikemayo.org/2010/node-js-socket-io-and-buffer-quirks" />
    <id>http://mikemayo.org/2010/node-js-socket-io-and-buffer-quirks</id>
    <updated>2010-12-09T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;As of late, I&amp;#8217;ve been bitten by the &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt; bug and have become distracted by a side-project with a co-worker.  I must admit this is my first time writing any Javascript outside of simple jQuery &lt;span class="caps"&gt;DOM&lt;/span&gt; manipulations, so it has been quite an experience for me.&lt;/p&gt;
&lt;p&gt;While my co-worker has written a vast majority of the code, I finally found some free time to dive in, and one of the first things I began playing with was finding a way to stream the output of a unix process to the view.  Of course the obvious choice was to use WebSockets and &lt;a href="Socket.IO"&gt;Socket.IO&lt;/a&gt; and I quickly &lt;a href="http://stackoverflow.com/questions/3499152/minimum-websocket-nodejs-tail-example"&gt;found&lt;/a&gt; a couple &lt;a href="http://blog.zacharyvoase.com/2010/11/11/sockets-and-nodes-i/"&gt;examples&lt;/a&gt; that made it look like it wouldn&amp;#8217;t be too hard.&lt;/p&gt;
&lt;p&gt;In my evening-long codefest, I came across two interesting quirks with Socket.IO/node that took up a majority of my time, and I thought I&amp;#8217;d detail them here in case anyone else runs into similar issues:&lt;/p&gt;
&lt;h4&gt;Node Buffer&lt;/h4&gt;
&lt;p&gt;We&amp;#8217;re currently using a WebWorker object to handle an out-of-request process, the output of which I want to stream to the view.  Inside the worker I created some code that looked like the following (just as an initial test for using &lt;code&gt;spawn&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;my_process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;command/to/run&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;my_process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;my_process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;stderr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This isn&amp;#8217;t quite exactly what it was doing, but suffice it to say that the output I got wasn&amp;#8217;t what I expected; it instead was this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stderr: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// stderr: Expected output from my command&lt;/span&gt;
  
  &lt;span class="c1"&gt;// Logging the data in the view directly without string concat gave this:&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { 0: 23, 1: 82:, 3: 15, ... 60: 10, length: 61 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Needless to say, I was quite confused, until I logged the output on the server side and saw this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  &amp;lt;Buffer 0a 1b 5b 31 6d 70 72 6f 6a 65 63 74 5f 74 65 73 74 1b 5b 32 32 6d 0a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A short google trip later and I found &lt;a href="http://nodejs.org/api.html#buffers-2"&gt;this&lt;/a&gt; in the node.js docs so I updated my code to call &lt;code&gt;data.toString('ascii')&lt;/code&gt; and was rewarded with the output I expected.&lt;/p&gt;
&lt;h4&gt;Socket.IO&lt;/h4&gt;
&lt;p&gt;The next time-consuming bug came when trying to stream the output from the process to the view.  The build worker that handles running the process passes the output back to the controller, which then broadcasts it via the socket to the clients.  My initial code looked something along these lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;stdout&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="s1"&gt;&amp;#39;stderr&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However, I was unable to call &lt;code&gt;stdout&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt; off the object passed in the broadcast, and when I logged to the browser console I found this odd output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;  ~j~{&amp;#39;stdout&amp;#39;:&amp;#39;This would be stdout output.&amp;#39;,&amp;#39;stderr&amp;#39;:null}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At first glance I was confused, it looked like a &lt;span class="caps"&gt;JSON&lt;/span&gt; object or an object literal, but I had no access to any of the keys inside.  I thought to myself &amp;#8220;The secret must lie in the &amp;#8216;~j~&amp;#8217; at the beginning,&amp;#8221; but Google returned no relevant results regarding that.  Eventually, after reading several other examples, I found a simple solution:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;  &lt;span class="c1"&gt;// Server-side&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;stdout&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="s1"&gt;&amp;#39;stderr&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
  
  &lt;span class="c1"&gt;//Client-side&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By doing this, I was able to access &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; off the &lt;code&gt;data&lt;/code&gt; variable.  I&amp;#8217;m still uncertain what the object originally being passed to the view was, as it was neither &lt;span class="caps"&gt;JSON&lt;/span&gt; nor an object literal, but the solution got me where I needed to be.  If anyone can explain it further, please do so; I&amp;#8217;d love to know what&amp;#8217;s going on behind the scenes here.&lt;/p&gt;
&lt;p&gt;I think it highly likely that I&amp;#8217;ve made some rookie mistakes here, but, as I stated before, I&amp;#8217;m very new to Javascript so much of this is foreign to me.  I&amp;#8217;m still trying to get past the Ruby/OO mindset and to wrap my brain around the JS way of doing things, but I&amp;#8217;m getting there.  I&amp;#8217;ll soon be reading &lt;cite&gt;&lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/ref=sr_1_1?ie=UTF8&amp;amp;qid=1291968451&amp;amp;sr=8-1"&gt;Javascript: The Good Parts&lt;/a&gt;&lt;/cite&gt;, which I hope will get me over some of these newbie difficulties I&amp;#8217;m running into.  If you have any tips or suggestions, or if you can point me towards any good guides on the subject, I&amp;#8217;d love to hear from you.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">MiniTest Events</title>
    <link href="http://mikemayo.org/2010/minitest-events" />
    <id>http://mikemayo.org/2010/minitest-events</id>
    <updated>2010-12-05T00:00:00-06:00</updated>
    <content type="html">
      &lt;p&gt;A few weeks ago I made a hack to &lt;a href="https://github.com/seattlerb/minitest"&gt;MiniTest&lt;/a&gt; to add &lt;a href="https://github.com/jeffkreeftmeijer/fuubar"&gt;Fuubar-like&lt;/a&gt; functionality.  Unfortunately the hack was a little dirty, and I wanted to make MiniTest more extendable, at least for reporting purposes.  My solution was to borrow from the Events system I wrote for &lt;a href="https://github.com/wiecklabs/harbor"&gt;Harbor&lt;/a&gt; (a web framework we wrote and use at &lt;a href="http://www.wieck.com"&gt;Wieck Media&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The concept is very simple; you just raise an event wherever you feel you need to, and pass in a context object of some kind.  Then you register an event handler, which is just a class with a call method that is executed at the time of the event raise.&lt;/p&gt;
&lt;p&gt;For example, here I am raising an event just before all of the tests begin to run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RunAnythingEvent&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;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  
  &lt;span class="n"&gt;raise_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:run_anything_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see it&amp;#8217;s using a special RunAnythingEvent context object, whose definition looks like so:&lt;/p&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;RunAnythingEvent&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BaseEvent&lt;/span&gt;
    
    &lt;span class="kp"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:runner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:suites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:options&lt;/span&gt;
    &lt;span class="kp"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:test_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:assertion_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:report&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:failures&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:skips&lt;/span&gt;
    
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="vi"&gt;@runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runner&lt;/span&gt;
      &lt;span class="vi"&gt;@output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;
      &lt;span class="vi"&gt;@suites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;
      &lt;span class="vi"&gt;@type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;
      &lt;span class="vi"&gt;@options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&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;And here is an example of an event handler for this event:&lt;/p&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;RunAnythingStartHandler&lt;/span&gt;
  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;
      &lt;span class="vi"&gt;@output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;
      &lt;span class="vi"&gt;@type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&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;call&lt;/span&gt;
      &lt;span class="vi"&gt;@output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;
      &lt;span class="vi"&gt;@output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;# Running &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s:&amp;quot;&lt;/span&gt;
      &lt;span class="vi"&gt;@output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&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;Which is registered by calling the following method off the class where the event was raised:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="n"&gt;register_event_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:run_anything_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;RunAnythingStartHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This particular example illustrates an important part of my goal.  I wanted to decouple the reporting of the tests from the actual tests themselves.  In order to further this I have created plugins that enable and disable the required event handlers which deal with outputting results in specific ways.  I have also moved all the base reporting into a plugin (&lt;code&gt;MiniTest::Reporting&lt;/code&gt;) which is enabled by default.&lt;/p&gt;
&lt;p&gt;The next step, which I&amp;#8217;ve already partially completed, is to create plugins that handle alternative output options like the progress bar and instafailing.  If you&amp;#8217;re interested, the work is being done in the &lt;a href="https://github.com/gotmayonase/minitest/tree/events"&gt;events branch&lt;/a&gt; on my Github account.  Assuming Node.js doesn&amp;#8217;t monopolize all my time, I hope to have it completed in the near future.  If you have any ideas, feel free to let me know.&lt;/p&gt;
    </content>
  </entry>
  
  <entry>
    <title type="html">MiniTest ProgressBar</title>
    <link href="http://mikemayo.org/2010/minitest-progressbar" />
    <id>http://mikemayo.org/2010/minitest-progressbar</id>
    <updated>2010-11-19T00:00:00-06:00</updated>
    <content type="html">
      &lt;div class="text"&gt;
  &lt;div class="text-body"&gt;
  	&lt;p&gt;I was recently inspired by a &lt;a href="http://jeffkreeftmeijer.com/2010/fuubar-the-instafailing-rspec-progress-bar-formatter/"&gt;blog post&lt;/a&gt; I read about a new Ruby gem called &lt;a href="https://github.com/jeffkreeftmeijer/fuubar"&gt;Fuubar&lt;/a&gt;.  The premise of this gem is to have your RSpec tests instafail, giving an immediate backtrace when a test fails or errors; that way you don&amp;#8217;t have to wait for all of your tests to complete before researching a problem.  It also makes use of one of my favorite gems, &lt;a href="https://github.com/peleteiro/progressbar"&gt;ProgressBar&lt;/a&gt;, to replace that boring standard test output of periods and letters with a progress bar.  To top it off, the output color shifts as your tests fail/error (red) or are skipped (yellow), or remains green if they all pass.  I find this test reporting to be much more informative and useful, but unfortunately we don&amp;#8217;t use RSpec (actually it was written on RSpec 2), so if I wanted this I was going to have to come up with my own solution.&lt;/p&gt; 
    &lt;p&gt;We&amp;#8217;ve actually only recently started really trying to integrate testing into our projects, and we&amp;#8217;ve chosen to use &lt;a href="https://github.com/seattlerb/minitest"&gt;MiniTest&lt;/a&gt;.  After upgrading to the latest version (2.0.0), I had high hopes that I could just mimic the behavior of the Pride extension, replace the default MiniTest::Unit.output with my own MiniTest::ProgressBar object that would convert the lovely periods and letters into the colored progress bar I longed for.  Unfortunately I quickly discovered that MiniTest doesn&amp;#8217;t expose any of the import things I needed, like a total count of tests being run.  &lt;/p&gt; 
    &lt;p&gt;I decided to start with a proof-of-concept (read: dirty override hack) just to be sure I could get the output I wanted from MiniTest.  What I ended up with looked something like this:&lt;/p&gt; 
    &lt;p&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;minitest/unit&amp;quot;&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;progressbar&amp;#39;&lt;/span&gt;

        &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Unit&lt;/span&gt;

          &lt;span class="no"&gt;COLORS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:green&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:yellow&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[33m&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:red&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31m&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[37m&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="vc"&gt;@@state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

          &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_run_suites&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;
            &lt;span class="vc"&gt;@@report_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:filter&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/./&amp;#39;&lt;/span&gt;
            &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="vg"&gt;$1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/\/(.*)\//&lt;/span&gt;

            &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;progress_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ProgressBar&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="n"&gt;type&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="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inject&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&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;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_methods&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;grep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_run_suite&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&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;_run_suite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;header&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;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_suite_header&amp;quot;&lt;/span&gt;
            &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;respond_to?&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;

            &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:filter&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/./&amp;#39;&lt;/span&gt;
            &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="vg"&gt;$1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/\/(.*)\//&lt;/span&gt;

            &lt;span class="nb"&gt;methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&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;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_methods&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;grep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;assertions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
              &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;
              &lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_assertions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

              &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;
              &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
              &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;

              &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;suite&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="nb"&gt;method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = %.2f s = &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@verbose&lt;/span&gt;
              &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
              &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@verbose&lt;/span&gt;

              &lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_assertions&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inject&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sum&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="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&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;print&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# :nodoc:&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
              &lt;span class="c1"&gt;# do nothing&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;E&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
              &lt;span class="n"&gt;current_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;
              &lt;span class="vc"&gt;@@state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:red&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;F&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
              &lt;span class="n"&gt;current_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fail&amp;quot;&lt;/span&gt;
              &lt;span class="vc"&gt;@@state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:red&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;S&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
              &lt;span class="n"&gt;current_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;skip&amp;quot;&lt;/span&gt;
              &lt;span class="vc"&gt;@@state&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="ss"&gt;:yellow&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
              &lt;span class="c1"&gt;# nothing&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@report&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;
              &lt;span class="vc"&gt;@@report_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
              &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;print_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;current_state&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="n"&gt;report&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;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;COLORS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;progress_bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;COLORS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:white&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;def&lt;/span&gt; &lt;span class="nf"&gt;state&lt;/span&gt;
            &lt;span class="vc"&gt;@@state&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="ss"&gt;:green&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;progress_bar&lt;/span&gt;
            &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;progress_bar&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;

          &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;progress_bar&lt;/span&gt;
            &lt;span class="vc"&gt;@@progress_bar&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;ProgressBar&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="s2"&gt;&amp;quot;Tests&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="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;progress_bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="vc"&gt;@@progress_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&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;print_skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;COLORS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:yellow&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;print_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&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;print_fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;COLORS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:red&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;print_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&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;print_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;COLORS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:red&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;print_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&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;print_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[K&amp;quot;&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%3d) %s&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="vc"&gt;@@report_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="nb"&gt;puts&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&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; 
    &lt;p&gt;Like I said, it&amp;#8217;s dirty, but it works.  What I&amp;#8217;m left with now is an output from running my tests that looks like this:&lt;/p&gt; 
    &lt;p&gt;&lt;img src="http://grab.by/grabs/82b1d2b18ca1d648c3481f4efbf69954.png" width="488" height="340"/&gt;&lt;/p&gt; 
    &lt;p&gt;I feel satisfied with the output.  I have a colorful progress bar as well as instafailing for efficient bug stomping.&lt;/p&gt; 
    &lt;p&gt;All of this work was done in our project as a monkey-patch, but I&amp;#8217;ve decided to try and clean this up.  So I&amp;#8217;ve forked SeattleRB&amp;#8217;s MiniTest on my &lt;a href="http://github.com/gotmayonase/minitest/"&gt;GitHub account&lt;/a&gt;, and am currently working to make this change a little cleaner.  My intention is to make the test reporting more pluggable using an event system with events being raised upon completion of individual tests, test suites, and the entire test run, that a plugin can then hook into and report in a custom manner.  As I progress further, I&amp;#8217;ll update here with how things turn out.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt; &lt;!-- end .text --&gt;
    </content>
  </entry>
  
</feed>
