<?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>ones zeros majors and minors</title>
 
 <link href="http://ozmm.org/" />
 <updated>2009-11-03T11:21:17-08:00</updated>
 <id>http://ozmm.org/</id>
 <author>
   <name>Chris Wanstrath</name>
   <email>chris@ozmm.org</email>
 </author>

 
 <link rel="self" href="http://feeds.feedburner.com/ozmmorg" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
   <title>Redis to the Resque</title>
   <link href="http://ozmm.org/posts/redis_to_the_resque.html" />
   <updated>2009-11-03T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/redis_to_the_resque</id>
   <content type="html">&lt;p&gt;&lt;a href="http://github.com/defunkt/resque"&gt;&lt;img src="http://img.skitch.com/20091103-d1auyrwgaicaac297g4eg715et.png" alt="resque" /&gt;&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SORT in Redis</title>
   <link href="http://ozmm.org/posts/sort_in_redis.html" />
   <updated>2009-10-20T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/sort_in_redis</id>
   <content type="html">&lt;p&gt;Now that &lt;a href="http://ozmm.org/posts/hurl_is_open_source.html"&gt;Hurl is open source&lt;/a&gt; I thought I'd talk a bit about one
of my favorite open source projects: &lt;a href="http://github.com/antirez/redis"&gt;Redis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Hurl we keep track of all the hurls you make, then show them to you
on the "your hurls" page:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20091020-ef3xadj582bnhjf9m4d1ypkapb.png" alt="Your Hurls" /&gt;&lt;/p&gt;

&lt;p&gt;One of the more fun features is the re-ordering of your Hurls. If I
click on the Twitter URL then hit 'Send,' I can re-issue the request
and see the new response. The next time I visit the "your hurls" page,
the Twitter URL will have moved to the top of my list:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20091020-j3a7qx21tepxqw7r5a7insqkgf.png" alt="Your Hurls" /&gt;&lt;/p&gt;

&lt;p&gt;This is probably pretty trivial in a SQL database, but Hurl uses
Redis - a key/value database. How do we do this kind of sorting?&lt;/p&gt;

&lt;p&gt;First let's talk about the three key/value types involved.&lt;/p&gt;

&lt;h3&gt;Hurls&lt;/h3&gt;

&lt;p&gt;A Hurl (in Redis) is a JSON object describing an HTTP request. Its key
is the SHA1 of its value. This is convenient because it means we won't
store duplicate values - we use Redis' &lt;a href="http://code.google.com/p/redis/wiki/SetnxCommand"&gt;SETNX&lt;/a&gt; command to only save
the value if its key doesn't already exist - and probably won't get
collisions.&lt;/p&gt;

&lt;p&gt;Let's look at one of my Hurls:&lt;/p&gt;

&lt;pre&gt;$ redis-cli get da0838427e5fef02921ca2346f59480da2e9e5d9
{
    "auth": "none",
    "id": "da0838427e5fef02921ca2346f59480da2e9e5d9",
    "method": "GET",
    "url": "http://github.com/api/v2/json/user/show/defunkt"
}&lt;/pre&gt;


&lt;p&gt;Notice we store the id with the object. We simply compute the SHA
before saving then stick it in the object - this is real handy for
generating links and whatnot later on, after pulling the object from
the db.&lt;/p&gt;

&lt;h3&gt;Your Hurls&lt;/h3&gt;

&lt;p&gt;Each user has a &lt;a href="http://code.google.com/p/redis/wiki/CommandReference#Commands_operating_on_sets"&gt;SET&lt;/a&gt; of SHAs which correspond to Hurls she has
made. For example, here's mine (I'm user #59):&lt;/p&gt;

&lt;pre&gt;$ redis-cli smembers Hurl::User:v1:59:hurls
1. da0838427e5fef02921ca2346f59480da2e9e5d9
2. eebb1e7782d0eefb5e4a82c6ee6a3779497a8d14
3. 0efea52740ebf7c388884461bda6b4a4198c4fa2
4. 59de6e57bda2a07505987a8fa40317a535e769e3&lt;/pre&gt;


&lt;p&gt;If you and I both query "google.com," we'll both share a SHA in our
Hurls list. And that's okay.&lt;/p&gt;

&lt;h3&gt;Recently Visited Hurls&lt;/h3&gt;

&lt;p&gt;Each time you make a Hurl request we store the timestamp. This is
important for the sorting.&lt;/p&gt;

&lt;p&gt;The timestamp is stored as a basic key/value pair. Here's one of mine:&lt;/p&gt;

&lt;pre&gt;$ redis-cli get Hurl::User:v1:59:hurls:da0838427e5fef02921ca2346f59480da2e9e5d9
1256015372&lt;/pre&gt;


&lt;p&gt;Simple Unix epoch format. The next time I hit "send" on that Hurl the
timestamp will be updated.&lt;/p&gt;

&lt;h3&gt;Sorting&lt;/h3&gt;

&lt;p&gt;Now that we have all those pieces in place, sorting is cake. You can
see the &lt;code&gt;sort&lt;/code&gt; call we use in lines &lt;a href="http://github.com/defunkt/hurl/blob/62673d40d4633e4e8fce2bc10af07b6b788b4368/models/user.rb#L53-57"&gt;53-57 of user.rb&lt;/a&gt;. Here's an
expanded version of it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;hurls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Hurl::User:v1:59:hurls&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:by&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Hurl::User:v1:59:hurls:*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:get&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:order&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;DESC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:limit&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:limit&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;We're telling Redis to grab each member of SET
&lt;code&gt;Hurl::User:v1:59:hurls&lt;/code&gt; then find the corresponding timestamp value
at key &lt;code&gt;Hurl::User:v1:59:hurls:*&lt;/code&gt; (where &lt;code&gt;*&lt;/code&gt; is replaced with the sha)
then order the SET by those timestamps. Once it has the ordered list
of shas, use each one as a key (again replacing the &lt;code&gt;*&lt;/code&gt; with the sha)
and return the values. Descending, first 100.&lt;/p&gt;

&lt;p&gt;What we end up with is a sorted list of Hurl objects. Beautiful!&lt;/p&gt;

&lt;p&gt;Here it is in Ruby pseudocode:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;shas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;# Find each sha and its timestamp&lt;/span&gt;
&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;smembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hurl::User:v1:59:hurls&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;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="n"&gt;shas&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hurl::User:v1:59:hurls:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Sort the shas by their timestamp&lt;/span&gt;
&lt;span class="n"&gt;shas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_by!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Return a list of all the Hurls&lt;/span&gt;
&lt;span class="n"&gt;hurls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;That's a wrap&lt;/h3&gt;

&lt;p&gt;I had a big "a-ha" moment when I finally figured out Redis'
&lt;a href="http://code.google.com/p/redis/wiki/SortCommand"&gt;SORT&lt;/a&gt;. Not because it's complicated, nor because it uses concepts
that were entirely new to me, nor because it's fast. No, the a-ha
moment was when I realized how damned simple it was.&lt;/p&gt;

&lt;p&gt;And not only is Redis' SORT simple - it made my app simpler, too. Just
check out the &lt;a href="https://github.com/defunkt/hurl/commit/d74d87a6232eeb3b306b33375ac7eb0ac9b757ae"&gt;first commit&lt;/a&gt; where we introduced SORT. We were able
to cut out my complicated, hacky implementation using Redis' LIST type
and replace it with something elegant.&lt;/p&gt;

&lt;p&gt;Why do I think the SORT implementation in Hurl is elegant? Because
it's calling into Redis, using existing features, and not
re-implementing features (poorly) in app-land.&lt;/p&gt;

&lt;p&gt;Always a win.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hurl is Open Source</title>
   <link href="http://ozmm.org/posts/hurl_is_open_source.html" />
   <updated>2009-10-20T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/hurl_is_open_source</id>
   <content type="html">&lt;p&gt;&lt;a href="http://github.com/defunkt/hurl"&gt;Yep&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="http://blog.leahculver.com/2009/10/hurl-is-now-open.html"&gt;Leah's post&lt;/a&gt; for details, including the &lt;a href="http://defunkt.github.com/hurl"&gt;Hurl
homepage&lt;/a&gt;, &lt;a href="http://twitter.com/hurlit"&gt;Hurl Twitter&lt;/a&gt;, and, of course, the &lt;a href="http://hurl.it/"&gt;live Hurl site&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>rake start</title>
   <link href="http://ozmm.org/posts/rake_start.html" />
   <updated>2009-10-16T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/rake_start</id>
   <content type="html">&lt;p&gt;I'm working on a Sinatra app that uses MongoDB. I'd love to start both Sinatra and MongoDB at the same time, then kill them at the same time, too. Luckily we can use Rake's &lt;code&gt;multitask&lt;/code&gt; for this.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:mongodb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Start MongoDB for development&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;mkdir_p&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;db&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mongod --dbpath db/&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:haystack&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Start Haystack for development&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;shotgun config.ru&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Start everything.&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;multitask&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;mongodb:start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;haystack:start&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now I can start both MongoDB and my Sinatra app with &lt;code&gt;rake start&lt;/code&gt;. It'll run in the foreground and when I Ctrl-C, both apps will be sent the Interrupt and gracefully shutdown.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Homebrew + Mysql + Snow Leopard</title>
   <link href="http://ozmm.org/posts/homebrew___mysql___snow_leopard.html" />
   <updated>2009-10-15T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/homebrew___mysql___snow_leopard</id>
   <content type="html">&lt;p&gt;I just had trouble installing and running Mysql on 5.1.39. Here's what worked:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;brew install mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This printed some instructions which got mysql running just fine, but
the &lt;code&gt;mysql&lt;/code&gt; gem decided to be difficult - uninitialized constant &lt;code&gt;MysqlCompat::MysqlRes&lt;/code&gt;. &lt;a href="http://www.ruby-forum.com/topic/192550"&gt;Some googling&lt;/a&gt; found the solution:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export ARCHFLAGS="-arch i386 -arch x86_64"
gem install mysql -- --with-mysql-dir=/usr/local \
--with-mysql-config=/usr/local/bin/mysql_config
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's assuming your homebrew prefix is &lt;code&gt;/usr/local&lt;/code&gt;. Worked for me!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Who We Hire</title>
   <link href="http://ozmm.org/posts/who_we_hire.html" />
   <updated>2009-10-14T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/who_we_hire</id>
   <content type="html">&lt;p&gt;Someone recently wrote to GitHub and asked:&lt;/p&gt;

&lt;blockquote&gt;
Basically, I'm just curious if you guys have any hints for a younger
programmer on how to escape corporate mediocrity before it becomes too
late. I know I could ask on StackOverflow or somewhere similar and get
lots of good responses, but I'm looking for an answer from a company
that I'd love to work at rather than someone who may be stuck in the
corporate world themselves and are just giving bad advice.
&lt;/blockquote&gt;


&lt;p&gt;I've written about &lt;a href="http://gist.github.com/6443"&gt;getting a job with open source&lt;/a&gt; before. But
this is more specific: who would (and do) we hire at GitHub?&lt;/p&gt;

&lt;p&gt;Simple: at GitHub we hire "The Girl or Guy Who Wrote X," where X is an
awesome project we all use or admire.&lt;/p&gt;

&lt;p&gt;What's your X?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Real-Time Web and a Git Overview</title>
   <link href="http://ozmm.org/posts/the_real_time_web_and_a_git_overview.html" />
   <updated>2009-09-09T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/the_real_time_web_and_a_git_overview</id>
   <content type="html">&lt;p&gt;I gave two talks at &lt;a href="http://www.djangocon.org/"&gt;DjangoCon 2009&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.slideshare.net/err/the-realtime-web-and-other-buzzwords" title="and Other Buzzwords"&gt;The Real-Time Web&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.slideshare.net/err/git-machine"&gt;Git: The Lean, Mean, Distributed Machine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Real-Time Web talk is mostly about comet and our experiences building &lt;a href="http://ozmm.org/posts/leafychat.html"&gt;Leafy Chat&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Git talk is the latest version of my go-to &lt;span class="caps"&gt;DVCS&lt;/span&gt; talk. I&amp;#8217;ve given it a few time but these slides are the most complete (in that they include my notes).&lt;/p&gt;
&lt;p&gt;The conference is really great so far. I&amp;#8217;ll definitely be back next year.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Lyndon</title>
   <link href="http://ozmm.org/posts/lyndon.html" />
   <updated>2009-08-26T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/lyndon</id>
   <content type="html">&lt;p&gt;Yesterday Ilya Grigorik &lt;a href="http://www.igvita.com/2009/08/25/post-javascript-dom-with-aptana-jaxer/"&gt;wrote&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&amp;#8220;I&amp;#8217;m still secretly hoping that one day our curl command client will just have a flag to return the final post-Javascript &lt;span class="caps"&gt;DOM&lt;/span&gt;.&amp;#8221;&lt;/p&gt;
&lt;p&gt;You don&amp;#8217;t have to hope and it doesn&amp;#8217;t have to be a secret, Ilya. &lt;a href="http://github.com/defunkt/lyndon"&gt;Lyndon&lt;/a&gt; is most of the way there.&lt;/p&gt;
&lt;p&gt;Tonight I committed a change that lets us pipe this into Lyndon:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Lyndon Test!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;$&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#content&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;div id=&amp;quot;hi&amp;quot;&amp;gt;Hello world!&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;It worked!&amp;#39;&lt;/span&gt;        
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&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;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;to get this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;It worked!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;We added the &lt;code&gt;Hello world!&lt;/code&gt; bit, changed the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, and removed the &lt;code&gt;script&lt;/code&gt; tags &lt;strong&gt;dynamically&lt;/strong&gt;. On the command line. With MacRuby.&lt;/p&gt;
&lt;p&gt;Joyous.&lt;/p&gt;
&lt;p&gt;Lyndon can even do a lot of the stuff &lt;a href="http://ozmm.org/posts/johnson.html"&gt;Johnson&lt;/a&gt; can do. Check the &lt;a href="http://github.com/defunkt/lyndon/tree/master#readme"&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt; for the full scoop.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hurl Preview</title>
   <link href="http://ozmm.org/posts/hurl_preview.html" />
   <updated>2009-08-23T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/hurl_preview</id>
   <content type="html">&lt;p&gt;&lt;a href="http://leahculver.com/"&gt;Leah&lt;/a&gt; and I just finished our &lt;a href="http://r09.railsrumble.com/"&gt;Rails Rumble 2009&lt;/a&gt; app. It&amp;#8217;s not ready for a public release yet, but here&amp;#8217;s the screencast to tide you over until then:&lt;/p&gt;
&lt;p&gt;&lt;object width="400" height="285" align="center"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=6238577&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=FF0022&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=6238577&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=FF0022&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="285"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;It uses Sinatra, Redis, Phusion Passenger (via nginx), jQuery, and even some Python libraries.&lt;/p&gt;
&lt;p&gt;Watch this space for the official launch announcement. Thanks to the Rumble organizers and all the sponsors!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>His Name is Robert Paulson</title>
   <link href="http://ozmm.org/posts/his_name_is_robert_paulson.html" />
   <updated>2009-08-20T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/his_name_is_robert_paulson</id>
   <content type="html">&lt;p&gt;Does it really matter what his name is? He didn&amp;#8217;t want us to know and didn&amp;#8217;t want us to call him by it.&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t call me Christopher. Call me Chris or defunkt.&lt;/p&gt;
&lt;p&gt;Either way, I&amp;#8217;m willing to bet it wasn&amp;#8217;t Jonathan. &lt;a href="http://sourceforge.net/users/jgillette/"&gt;Jonathan Gillette&lt;/a&gt; worked on &lt;a href="http://sourceforge.net/projects/javuh/"&gt;Javuh&lt;/a&gt; with _why in 2002. They both, apparently, worked at &lt;a href="http://www.inetz.com/home.html"&gt;iNetZ Media&lt;/a&gt;. Which would explain why their &lt;a href="http://whoiswhytheluckystiff.wordpress.com/"&gt;mailservers&lt;/a&gt; are they same &amp;#8211; they both were emailing from work.&lt;/p&gt;
&lt;p&gt;They both worked on the Javuh project at the same time:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20090820-t32a8pbjr536rei2gke4jbni87.png"/&gt;&lt;/p&gt;
&lt;p&gt;They both contributed different parts of the documentation:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://web.archive.org/web/20040202103137/sourceforge.net/docman/display_doc.php?docid=7198&amp;group_id=35881"&gt;&lt;br /&gt;
&lt;img src="http://img.skitch.com/20090820-mqrjwq6tnbgu8phd93haq3e3du.png"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://web.archive.org/web/20040520152934/codelab.javuh.com/"&gt;&lt;br /&gt;
&lt;img src="http://img.skitch.com/20090820-fnii9ki9w8eqggdw8irfrcxeaj.png"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://web.archive.org/web/20020603160937/http://javuh.com/psychoo/"&gt;&lt;br /&gt;
&lt;img src="http://img.skitch.com/20090820-nn9fnr7urpqnrnhgx811kmymhi.png"&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;_why joined SourceForge in 2000:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20090820-cfdrdrinr2c4pq797pcp6arrka.png"/&gt;&lt;/p&gt;
&lt;p&gt;Jonathan joined SourceForge 2001:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20090820-fqcpkqnaap57ikpnsifb7nh3dd.png"/&gt;&lt;/p&gt;
&lt;p&gt;Jonathan also worked on &lt;a href="http://sourceforge.net/projects/dbtcp/"&gt;other projects&lt;/a&gt; without _why:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sourceforge.net/users/jgillette"&gt;&lt;br /&gt;
&lt;img src="http://img.skitch.com/20090820-kmbusxp2rsc3ucmg26nx9wxmkr.png"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we can all stop obsessing about who we think he was and instead focus on who he actually was &amp;#8211; a prolific and inspiring hacker.&lt;/p&gt;
&lt;p&gt;Thanks for the memories, _why.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Rip 0.0.4</title>
   <link href="http://ozmm.org/posts/rip_0_0_4.html" />
   <updated>2009-08-13T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/rip_0_0_4</id>
   <content type="html">&lt;p&gt;I just pushed the fourth alpha release of &lt;a href="http://hellorip.com/"&gt;Rip&lt;/a&gt;. What&amp;#8217;s new? Better gem support!&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;rip install gem&lt;/code&gt; now installs gem dependencies. This is awesome. Thanks to &lt;a href="http://twitter.com/lazyatom"&gt;lazyatom&lt;/a&gt; &amp;#8211; check out &lt;a href="http://interblah.net/rip-gem-dependencies"&gt;his writeup&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;rip show PACKAGE&lt;/code&gt; to inspect a package. Supports &lt;code&gt;-f&lt;/code&gt; to see files. Again, thanks lazyatom.&lt;/li&gt;
	&lt;li&gt;Fixed bugs in gem installation.&lt;/li&gt;
	&lt;li&gt;Added &lt;a href="http://gemcutter.org/"&gt;gemcutter&lt;/a&gt; as a gem source.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rip help&lt;/code&gt; commands are now sorted alphabetically.&lt;/li&gt;
	&lt;li&gt;Improved &lt;code&gt;rip build&lt;/code&gt; &amp;#8211; Nokogiri is now supported.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next release will focus on systemwide Rip installations. See you then.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Rip 0.0.3</title>
   <link href="http://ozmm.org/posts/rip_0_0_3.html" />
   <updated>2009-08-06T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/rip_0_0_3</id>
   <content type="html">&lt;p&gt;I just pushed the third alpha release of &lt;a href="http://hellorip.com/"&gt;Rip&lt;/a&gt;. What&amp;#8217;s new?&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;New git-style help system. Thanks Ben Burkert!&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rip install blah -f&lt;/code&gt; does a &amp;#8220;force&amp;#8221; install.&lt;/li&gt;
	&lt;li&gt;Nicer &lt;code&gt;rip env list&lt;/code&gt; output.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rip env list -p&lt;/code&gt; shows a few packages from each ripenv.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rip env list ripenv&lt;/code&gt; runs &lt;code&gt;rip list&lt;/code&gt; for a specific ripenv.&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;rip use ripenv&lt;/code&gt; as an alias for &lt;code&gt;rip env use ripenv&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rip build&lt;/code&gt; now tries to run &lt;code&gt;make clean&lt;/code&gt; before &lt;code&gt;make install&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, of course, bug fixes. Also, I found a few projects that include a &lt;code&gt;deps.rip&lt;/code&gt; file. Check &amp;#8217;em out:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/grempe/amazon-ec2"&gt;amazon-ec2&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/chriseppstein/compass"&gt;Compass&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/sstephenson/sprockets"&gt;Sprockets&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/chrislloyd/tyrone"&gt;Tyrone&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/chrislloyd/pixii"&gt;Pixii&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/integrity/integrity"&gt;Integrity&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/dkubb/yardstick"&gt;Yardstick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;#8217;re getting closer to Rip 0.1.0, which will contain a big surprise. You&amp;#8217;ll love it. See you then.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>define_method and rdoc</title>
   <link href="http://ozmm.org/posts/define_method_and_rdoc.html" />
   <updated>2009-08-03T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/define_method_and_rdoc</id>
   <content type="html">&lt;p&gt;Seen in &lt;a href="http://github.com/cvillecsteele/evented-memcache-client/blob/83175e553cc5cd471277cc7101ab5d3570ff659c/lib/evented_memcache_client/sender.rb#L136-144"&gt;evented-memcache-client&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Wish these could be properly rdoc&amp;#39;d...&lt;/span&gt;
&lt;span class="sx"&gt;%w(flush_all version quit)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;define_method&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;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;book_it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;send_to_peer&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;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;I used to write a lot of Ruby code like this. &lt;code&gt;define_method&lt;/code&gt; is there &amp;#8211; why not use it, right?&lt;/p&gt;
&lt;p&gt;Remember, though: write code that is easy to read. Here&amp;#8217;s how I would rewrite the above to be rdoc friendly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flush_all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:flush_all&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;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="n"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:version&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;quit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="n"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:quit&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;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;book_it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;send_to_peer&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;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Just like that it&amp;#8217;s rdoc friendly, has less nesting, and is still easy to modify.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>New Bacondrop Icon!</title>
   <link href="http://ozmm.org/posts/new_bacondrop_icon.html" />
   <updated>2009-07-30T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/new_bacondrop_icon</id>
   <content type="html">&lt;p&gt;Thanks to &lt;a href="http://spencereholtaway.wordpress.com/"&gt;Spencer Holtaway&lt;/a&gt;, &lt;a href="http://ozmm.org/posts/bacondrop.html"&gt;Bacondrop&lt;/a&gt; now has a hot new icon:&lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://baconfile.com/defunkt/bacondrop/"&gt;&lt;img src="http://s3.amazonaws.com:80/defunkt.baconfile.com/bacondrop%2Ficon.png"&gt;&lt;/a&gt;&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Fake RubyGems in Rip</title>
   <link href="http://ozmm.org/posts/fake_rubygems_in_rip.html" />
   <updated>2009-07-28T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/fake_rubygems_in_rip</id>
   <content type="html">&lt;p&gt;Tonight I created a simple &lt;a href="http://gist.github.com/157899"&gt;Rip plugin&lt;/a&gt; which lets you install a RubyGems stub into the current ripenv, for faking out RubyGems.&lt;/p&gt;
&lt;p&gt;Why is this useful? Well, &lt;a href="http://github.com/mojombo/grit"&gt;Grit&lt;/a&gt; includes the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mime-types&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;gt;=0&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;mime/types&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Grit doesn&amp;#8217;t really &lt;em&gt;need&lt;/em&gt; RubyGems &amp;#8211; it just needs &lt;code&gt;mime/types&lt;/code&gt;. Trying to run one of Grit&amp;#8217;s tests, for instance, fails with &lt;code&gt;mime/types&lt;/code&gt; installed through any means other than RubyGems:&lt;/p&gt;
&lt;pre&gt;
$ ruby test/test_diff.rb 
/Library/Ruby/Site/1.8/rubygems.rb:826:in `report_activate_error': 
  Could not find RubyGem mime-types (&amp;gt;= 0) (Gem::LoadError)
  	from /Library/Ruby/Site/1.8/rubygems.rb:260:in `activate'
  	from /Library/Ruby/Site/1.8/rubygems.rb:67:in `gem'
  	from ./test/../lib/grit.rb:20
  	from ./test/helper.rb:1:in `require'
  	from ./test/helper.rb:1
  	from test/test_diff.rb:1:in `require'
  	from test/test_diff.rb:1
&lt;/pre&gt;
&lt;p&gt;But! after installing the plugin we can simply run &lt;code&gt;rip fake_rubygems&lt;/code&gt; to stub RubyGems in the active ripenv:&lt;/p&gt;
&lt;pre&gt;
$ rip fake_rubygems
rip: rubygems successfully faked
$ ruby test/test_diff.rb 
Loaded suite test/test_diff
Started
.
Finished in 0.000676 seconds.
&lt;/pre&gt;
&lt;p&gt;Fantastic. Check out &lt;a href="http://gist.github.com/157899"&gt;the plugin&lt;/a&gt;. For now the easiest way to install it is to manually stick it in &lt;code&gt;~/.rip/rip-commands&lt;/code&gt; (after creating the directory).&lt;/p&gt;
&lt;p&gt;So basically:&lt;/p&gt;
&lt;pre&gt;
mkdir -p ~/.rip/rip-commands
cd ~/.rip/rip-commands
wget http://is.gd/1Sgvf
&lt;/pre&gt;
&lt;p&gt;Next up: making plugin management simpler. Ta.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>FakeFS Activation</title>
   <link href="http://ozmm.org/posts/fakefs_activation.html" />
   <updated>2009-07-26T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/fakefs_activation</id>
   <content type="html">&lt;p&gt;Thanks to &lt;a href="http://github.com/nakajima"&gt;Pat Nakajima&lt;/a&gt; &lt;a href="http://github.com/defunkt/fakefs"&gt;FakeFS&lt;/a&gt; now supports activation and deactivation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fakefs/safe&amp;#39;&lt;/span&gt;

&lt;span class="no"&gt;FakeFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activate!&lt;/span&gt;
&lt;span class="c1"&gt;# your code&lt;/span&gt;
&lt;span class="no"&gt;FakeFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deactivate!&lt;/span&gt;

&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;span class="no"&gt;FakeFS&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# your code&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This means you can turn it on and off in your tests, if you please. Enjoy.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Rip 0.0.2</title>
   <link href="http://ozmm.org/posts/rip_0_0_2.html" />
   <updated>2009-07-21T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/rip_0_0_2</id>
   <content type="html">&lt;p&gt;I just pushed the second alpha release of &lt;a href="http://hellorip.com/"&gt;Rip&lt;/a&gt;. What&amp;#8217;s new?&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;C extensions are now built automatically during installation.&lt;/li&gt;
	&lt;li&gt;Rip can now uninstall itself using &lt;code&gt;sudo rip uninstall rip&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;ruby&lt;/code&gt; command for running Ruby within a specific ripenv: &lt;code&gt;rip ruby some_ripenv file.rb&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Add &lt;code&gt;RUBYBIN&lt;/code&gt; env support to &lt;code&gt;rip ruby&lt;/code&gt;: &lt;code&gt;RUBYBIN=/path/to/jruby rip ruby cheat_env cheat.rb&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Rip also respects the &lt;code&gt;RAKEBIN&lt;/code&gt; and &lt;code&gt;GEMBIN&lt;/code&gt; env variables.&lt;/li&gt;
	&lt;li&gt;Improved zshell support.&lt;/li&gt;
	&lt;li&gt;Support for the &lt;a href="http://fishshell.org"&gt;fish shell&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;rip setup&lt;/code&gt; command.&lt;/li&gt;
	&lt;li&gt;Can pass &lt;code&gt;--bindir&lt;/code&gt;, &lt;code&gt;--libdir&lt;/code&gt; and/or &lt;code&gt;--ripdir&lt;/code&gt; as to setup.&lt;/li&gt;
	&lt;li&gt;More friendly and informative &lt;code&gt;rip check&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;Rip now installs into &lt;code&gt;/usr&lt;/code&gt; by default on OS X (not &lt;code&gt;/usr/local&lt;/code&gt;)&lt;/li&gt;
	&lt;li&gt;Rogue plugins can no longer break Rip.&lt;/li&gt;
	&lt;li&gt;Packages may now respond to hooks in the installation process.&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;upgrade&lt;/code&gt; to &lt;code&gt;setup.rb&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, of course, bug fixes. Thanks to &lt;a href="http://github.com/defunkt/rip/commit/f375cf0145a3d9ac4f5db4d3b5607ec37ddd06b5"&gt;everyone who contributed&lt;/a&gt;!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Johnson</title>
   <link href="http://ozmm.org/posts/johnson.html" />
   <updated>2009-07-21T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/johnson</id>
   <content type="html">&lt;p&gt;&lt;a href="http://github.com/jbarnette/johnson"&gt;Johnson&lt;/a&gt; has long been one of my favorite Ruby projects. As the description says, &amp;#8220;Johnson wraps JavaScript in a loving Ruby embrace.&amp;#8221; In other words Johnson lets you evaluate and manipulate JavaScript with Ruby (thanks to Mozilla&amp;#8217;s Spidermonkey engine).&lt;/p&gt;
&lt;h3&gt;Ruby&lt;/h3&gt;
&lt;p&gt;A simple example from the &lt;a href="http://github.com/jbarnette/johnson/tree/master#readme"&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;johnson&amp;quot;&lt;/span&gt;

&lt;span class="no"&gt;Johnson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;4 + 4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 8&lt;/span&gt;
&lt;span class="no"&gt;Johnson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;4 + foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 8&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Why? Well, maybe you want to let people write plugins for your app in JavaScript &amp;#8211; thereby locking down and controlling the environment in a way not really possible with Ruby.&lt;/p&gt;
&lt;p&gt;Or maybe you want to run your JavaScript tests on the command line before booting up your browser.&lt;/p&gt;
&lt;p&gt;Or maybe you want to run a JavaScript &lt;span class="caps"&gt;REPL&lt;/span&gt;.&lt;/p&gt;
&lt;pre&gt;
$ johnson
js&amp;gt; 1 + 1
=&amp;gt; 2
js&amp;gt; var name = 'chris'
=&amp;gt; nil
js&amp;gt; name
=&amp;gt; "chris"
&lt;/pre&gt;
&lt;h3&gt;Emacs Lisp&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re using Emacs like me, you can setup johnson to run as your JavaScript shell by setting the custom variable &lt;code&gt;javascript-shell-command&lt;/code&gt; to &amp;#8220;johnson&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Also you can use it to execute a buffer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;js2-execute-buffer&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; 
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shell-command&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;johnson &amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;buffer-file-name&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Or a single line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;js2-execute-line&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;save-excursion&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;call-process-region&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;point-at-bol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;point-at-eol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                         &lt;span class="s"&gt;&amp;quot;johnson&amp;quot;&lt;/span&gt;
                         &lt;span class="nv"&gt;nil&lt;/span&gt;
                         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-buffer-create&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;*johnson-line*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;with-current-buffer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-buffer&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;*johnson-line*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;search-backward&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;replace-match&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;buffer-string&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kill-buffer&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;I bind these functions to &lt;code&gt;⌘r&lt;/code&gt; and &lt;code&gt;⌘R&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-key&lt;/span&gt; &lt;span class="nv"&gt;js2-mode-map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;A-r&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;js2-execute-buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-key&lt;/span&gt; &lt;span class="nv"&gt;js2-mode-map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;A-R&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;js2-execute-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Python&lt;/h3&gt;
&lt;p&gt;Python person? Try davisp&amp;#8217;s &lt;a href="http://github.com/davisp/python-spidermonkey"&gt;python-spidermonkey&lt;/a&gt; or &lt;a href="http://github.com/defunkt/python-spidermonkey"&gt;my fork&lt;/a&gt; (which does nothing but add a dead simple &lt;a href="http://github.com/defunkt/python-spidermonkey/blob/35402125a929096c3d965bba62c977c5955c7d7c/bin/pymonkey"&gt;&lt;span class="caps"&gt;REPL&lt;/span&gt; script&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s very similar to Johnson. Except, you know, for Python.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;spidermonkey&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spidermonkey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;var x = 3; x *= 4; x;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Again, the &lt;a href="http://github.com/davisp/python-spidermonkey/tree/master#readme"&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt; has it all.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>FakeFS</title>
   <link href="http://ozmm.org/posts/fakefs.html" />
   <updated>2009-07-15T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/fakefs</id>
   <content type="html">&lt;p&gt;&lt;a href="http://github.com/defunkt/fakefs"&gt;FakeFS&lt;/a&gt; is a Ruby library which transparently causes &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;Dir&lt;/code&gt;, and &lt;code&gt;FileUtils&lt;/code&gt; to use an in-memory. faux-filesystem rather than the real filesystem on disk. Why? So you don&amp;#8217;t have to deal with mocking libraries, so your tests are faster, and so you don&amp;#8217;t need a hard drive to run them.&lt;/p&gt;
&lt;p&gt;For example, this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_creates_directory&lt;/span&gt;
  &lt;span class="no"&gt;FileUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:mkdir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;directory&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;once&lt;/span&gt;
  &lt;span class="no"&gt;Library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;directory&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Becomes this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_creates_directory&lt;/span&gt;
  &lt;span class="no"&gt;Library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;directory&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;directory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;I don&amp;#8217;t know about you, but the second feels more natural to me. Also it means replacing our &lt;code&gt;mkdir&lt;/code&gt; call with a call to &lt;code&gt;mkdir_p&lt;/code&gt; won&amp;#8217;t break our tests. Because, really, it shouldn&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;Install it:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ rip install git://github.com/defunkt/fakefs.git&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And start using it in your tests:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;require 'fakefs'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There really aren&amp;#8217;t any usage examples: just write normal Ruby. If you insist, however, check out some of the &lt;a href="http://github.com/defunkt/rip/blob/master/test/env_test.rb"&gt;Rip test&lt;/a&gt; or the &lt;a href="http://github.com/defunkt/fakefs/blob/master/test/fakefs_test.rb"&gt;FakeFS tests&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Bacondrop Libraries</title>
   <link href="http://ozmm.org/posts/bacondrop_libraries.html" />
   <updated>2009-07-13T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/bacondrop_libraries</id>
   <content type="html">&lt;p&gt;&lt;a href="http://ozmm.org/posts/bacondrop.html"&gt;Bacondrop&lt;/a&gt; uses two third party libraries that are quite good.&lt;/p&gt;
&lt;p&gt;The first is &lt;a href="http://drnic.github.com/choctop"&gt;ChocTop&lt;/a&gt;, Dr Nic&amp;#8217;s library for generating DMGs and managing Sparkle. The documentation is great and the gem is dead simple to use: all I had to do was run &lt;code&gt;rake dmg&lt;/code&gt; (after installing it and running &lt;code&gt;install_choctop path/to/project&lt;/code&gt;) to get a &lt;span class="caps"&gt;DMG&lt;/span&gt; ready for distribution. It even included an &lt;code&gt;Applications&lt;/code&gt; shortcut in the &lt;span class="caps"&gt;DMG&lt;/span&gt; for easier installation. Though Bacondrop doesn&amp;#8217;t use Sparkle, I already know I&amp;#8217;ll use ChocTop in any and all Cocoa apps I write in the future.&lt;/p&gt;
&lt;p&gt;The second library is &lt;a href="http://allseeing-i.com/ASIHTTPRequest/"&gt;ASIHTTPRequest&lt;/a&gt;. It&amp;#8217;s an Objective-C wrapper for the CFNetwork &lt;span class="caps"&gt;API&lt;/span&gt; which makes it dead simple to issue &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests. The file uploading support in particular is ridiculously good:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;beginUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ASIFormDataRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestWithURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uploadProgressDelegate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;progressBar&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;didFinishSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;uploadFinished:&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;didFailSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;uploadFinished:&amp;quot;&lt;/span&gt;  
  &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forKey&lt;/span&gt;&lt;span class="ss"&gt;:&amp;quot;file&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="vi"&gt;@networkQueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@networkQueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;go&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This&amp;#8217;ll &lt;span class="caps"&gt;POST&lt;/span&gt; a file to the url of my choosing, authenticate with &lt;span class="caps"&gt;HTTP&lt;/span&gt; basic auth, hit the &lt;code&gt;uploadFinished:&lt;/code&gt; method with the request object upon completion, and even update a progress bar for me along the way. Naturally it&amp;#8217;s all done asynchronously &amp;#8211; I can fire off as many as I want using the queue.&lt;/p&gt;
&lt;p&gt;(It&amp;#8217;s not the exact code I use in Bacondrop, but it gives you an idea of how easy it is to use this library.)&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://allseeing-i.com/ASIHTTPRequest/How-to-use"&gt;documentation&lt;/a&gt; is fantastic and it even works on the iPhone. Ben Copsey really knocked this one out of the park.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Bacondrop!</title>
   <link href="http://ozmm.org/posts/bacondrop.html" />
   <updated>2009-07-12T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/bacondrop</id>
   <content type="html">&lt;p&gt;I just finished a rough 1.0 of my first MacRuby app: &lt;a href="http://baconfile.com/defunkt/bacondrop/"&gt;Bacondrop&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s a simple app for uploading files to &lt;a href="http://baconfile.com/"&gt;Baconfile&lt;/a&gt;. Which, in turn, is a simple (and slick) interface to S3.&lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://baconfile.com/defunkt/bacondrop/"&gt;&lt;img src="http://s3.amazonaws.com:80/defunkt.baconfile.com/bacondrop%2Fscreenshot1.png" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;MacRuby is great.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Leafy Chat</title>
   <link href="http://ozmm.org/posts/leafychat.html" />
   <updated>2009-07-10T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/leafychat</id>
   <content type="html">&lt;p&gt;A few weeks ago I competed in the &lt;a href="http://www.djangodash.com/"&gt;Django Dash&lt;/a&gt; along with &lt;a href="http://twitter.com/alex_gaynor"&gt;Alex Gaynor&lt;/a&gt; and &lt;a href="http://twitter.com/leahculver"&gt;Leah Culver&lt;/a&gt;. Our team ended up placing second.&lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://leafychat.com/"&gt;&lt;img src="http://img.skitch.com/20090710-9yyxf33faegu2w3m7actpmqhi.png" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;We made a comet powered, web based &lt;span class="caps"&gt;IRC&lt;/span&gt; client called &lt;a href="http://leafychat.com/"&gt;Leafy Chat&lt;/a&gt;. In fact, we just launched a redesign.&lt;/p&gt;
&lt;p&gt;Check it out.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Forking, Continued</title>
   <link href="http://ozmm.org/posts/forking_continued.html" />
   <updated>2009-01-21T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/forking_continued</id>
   <content type="html">&lt;p&gt;David Welton has posted &lt;a href="http://journal.dedasys.com/2009/01/21/more-github"&gt;a thoughtful reply&lt;/a&gt; to &lt;a href="http://ozmm.org/posts/linux_vs_classic_dev_style.html"&gt;my comment&lt;/a&gt;. Unfortunately, he missed my point. I can only assume this is due to a lack of clarity on my part. (My comment was very brief.)&lt;/p&gt;
&lt;p&gt;I mentioned the Network Graph and Fork Queue but David mentioned neither. I think he doesn&amp;#8217;t know what they are, probably because I didn&amp;#8217;t explain what they are :)&lt;/p&gt;
&lt;p&gt;So, in an effort to be more clear, let me propose an alternate workflow to David&amp;#8217;s. He says, &amp;#8220;Here&amp;#8217;s a concrete example of how things might go wrong.&amp;#8221; I see his example and think, &amp;#8220;That&amp;#8217;s a concrete example of how things have gone right.&amp;#8221;&lt;/p&gt;
&lt;p&gt;(I&amp;#8217;m going to make this visual so you don&amp;#8217;t have to take my word for it or keep jumping between here and GitHub to try it out.)&lt;/p&gt;
&lt;h3&gt;The Network Graph&lt;/h3&gt;
&lt;pre&gt;
root@fortrock:~# gem1.8 search -r actionwebservice

*** REMOTE GEMS ***

actionwebservice (1.2.6)
datanoise-actionwebservice (2.2.2)
dougbarth-actionwebservice (2.1.1)
nmeans-actionwebservice (2.1.1)
&lt;/pre&gt;
&lt;p&gt;The problem is obvious: which &lt;code&gt;actionwebservice&lt;/code&gt; should we use?&lt;/p&gt;
&lt;p&gt;Well, we know three of those gems are on GitHub. And all three of the GitHub gems have higher versions than the Rubyforge gem. So let&amp;#8217;s check GitHub first.&lt;/p&gt;
&lt;p&gt;I go to &lt;a href="http://github.com/search"&gt;http://github.com/search&lt;/a&gt; and search for &lt;code&gt;actionwebservice&lt;/code&gt;. (Actually I do this from my &lt;a href="http://www.obdev.at/launchbar/"&gt;LaunchBar&lt;/a&gt; template, but you get the idea.)&lt;/p&gt;
&lt;p&gt;In the &lt;a href="http://github.com/search?type=Everything&amp;amp;language=&amp;amp;q=actionwebservice&amp;amp;repo=&amp;amp;langOverride=&amp;amp;x=0&amp;amp;y=0&amp;amp;start_value=1"&gt;results&lt;/a&gt;, I see that the first &lt;code&gt;actionwebservice&lt;/code&gt; appearing has the most forks and watchers, and was the most recently active.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;a href="http://github.com/search?type=Everything&amp;language=&amp;q=actionwebservice&amp;repo=&amp;langOverride=&amp;x=0&amp;y=0&amp;start_value=1"&gt;
&lt;img src="http://img.skitch.com/20090121-k9e1webim3i7ejyuhgmkq8tws6.png" alt="" /&gt;
&lt;p&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We could stop right here and choose @datanoise@&amp;#8217;s fork. But let&amp;#8217;s be sure.&lt;/p&gt;
&lt;p&gt;I click on the repo and arrive at &lt;a href="http://github.com/datanoise/actionwebservice"&gt;http://github.com/datanoise/actionwebservice&lt;/a&gt;. I click on the &lt;code&gt;Network&lt;/code&gt; tab.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;p&gt;&lt;a href="http://github.com/datanoise/actionwebservice/network"&gt;&lt;br /&gt;
  &lt;img src="http://img.skitch.com/20090121-rhe2ygfkeu9msf5ew45q3h5u9y.png" alt="" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I arrive at &lt;a href="http://github.com/datanoise/actionwebservice/network"&gt;http://github.com/datanoise/actionwebservice/network&lt;/a&gt; and glance at the graph.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;a href="http://github.com/datanoise/actionwebservice/network"&gt;
&lt;img src="http://img.skitch.com/20090121-tg4xmqdm1ut8s78gxrd2t3dahr.png" alt="" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;There are commits unique to certain forks, but &lt;code&gt;datanoise&lt;/code&gt; has the most activity and the most recent commits.&lt;/p&gt;
&lt;p&gt;At this point, there&amp;#8217;s no doubt: &lt;code&gt;datanoise&lt;/code&gt; is the most recent, most active version of &lt;code&gt;actionwebservice&lt;/code&gt;. Will it always be? Who knows. But for now, this is the best choice.&lt;/p&gt;
&lt;h3&gt;The Fork Queue&lt;/h3&gt;
&lt;p&gt;We can take it a step further, too. We see there are unmerged commits &amp;#8211; changes people have made which have not been pulled into &lt;code&gt;datanoise&lt;/code&gt;. We can examine them straight from the Network Graph, or we can attempt to merge them into &lt;code&gt;actionwebservice&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I fork @datanoise@&amp;#8217;s &lt;code&gt;actionwebservice&lt;/code&gt; using the &amp;#8216;fork&amp;#8217; button, still on the Network Graph&amp;#8217;s page:&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;a href="http://github.com/datanoise/actionwebservice/network"&gt;
&lt;img src="http://img.skitch.com/20090121-pqgx4www5irpyr6jp762723729.png" alt="" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Now I have my own version of &lt;code&gt;actionwebservice&lt;/code&gt;.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;a href="http://github.com/defunkt/actionwebservice"&gt;
&lt;img src="http://img.skitch.com/20090121-fhupjq4bikpix8ft6ftdugiht4.png" alt="" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Time to visit the Fork Queue. (Only people with write access to the repository see this tab.)&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;img src="http://img.skitch.com/20090121-dxkih4t9xqnthj8wqiexn19hhm.png" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Okay, so it looks like a lot of the changes made will not apply cleanly.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;img src="http://img.skitch.com/20090121-empcj2mfx91w1by7irinwg1s7w.png" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;If any of these commits had a green background, we&amp;#8217;d be able to apply them right there on the site (as explained by the legend). But we can&amp;#8217;t.&lt;/p&gt;
&lt;h3&gt;Pull Requests&lt;/h3&gt;
&lt;p&gt;Since we can&amp;#8217;t apply the commits, we could send &lt;code&gt;datanoise&lt;/code&gt; a message asking him to check over his Fork Queue and merge in the changes that look promising. We could do it ourselves, too, by resolving the conflicts. All we&amp;#8217;d need is to clone our repository, add one of the others as a remote, then merge and fix the conflicts before pushing back to our version. After that we could even send &lt;code&gt;datanoise&lt;/code&gt; a pull request, since we&amp;#8217;ve done the work for him. Or just wait for him to check his Fork Queue and see that our changes are green.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m just going to delete my fork, though.&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;img src="http://img.skitch.com/20090121-q8m79g686d6q7fwbc7eiarwss1.png" alt="" /&gt;
&lt;/div&gt;
&lt;h3&gt;Keeping Current&lt;/h3&gt;
&lt;p&gt;Even ignoring the forking and the Fork Queue, the point is this: it&amp;#8217;s not hard to see which project is the most active. Yes, we (GitHub) need to make it more clear. We want to say &amp;#8220;this is the fork you&amp;#8217;re looking for&amp;#8221; on the first page you see. And we want that to change as the most active, latest fork changes. But, for the time being, you can figure that all out with a single click.&lt;/p&gt;
&lt;p&gt;What happens when it does change, though? Perhaps &lt;code&gt;datanoise&lt;/code&gt; will lose interest and someone else will take up development. That&amp;#8217;s the beautiful part, and that&amp;#8217;s why you just can&amp;#8217;t do GitHub without Git (or any equally powerful &lt;span class="caps"&gt;DVCS&lt;/span&gt;): switching the remote and pulling in changes from the new repository is trivial. Git doesn&amp;#8217;t care where you pull from. It is not married to a remote &lt;span class="caps"&gt;URL&lt;/span&gt; in the same way a centralized &lt;span class="caps"&gt;VCS&lt;/span&gt; like Subversion is.&lt;/p&gt;
&lt;p&gt;Imagine hitting the &lt;code&gt;datanoise&lt;/code&gt; repository and being informed &amp;#8220;this may not be the most active repository in the network. Check Person X&amp;#8217;s.&amp;#8221; Switch your remote to the new one, pull, and you&amp;#8217;re up to date. This is the type of information the Network Graph makes available, we just need to make it more visible and plain. (Heck, maybe that message could be printed out when you &lt;code&gt;git pull&lt;/code&gt; from an inactive remote.)&lt;/p&gt;
&lt;p&gt;For instance, hitting @dougbarth@&amp;#8217;s &lt;code&gt;actionwebservice&lt;/code&gt; fork and checking the Network Graph makes it obvious that &lt;code&gt;datanoise&lt;/code&gt; is the repo we want:&lt;/p&gt;
&lt;div class="photo"&gt;
&lt;a href="http://github.com/dougbarth/actionwebservice/network"&gt;
&lt;img src="http://img.skitch.com/20090121-xhman6nekg64icyer9i5cr7xkg.png" alt="" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If we were previously using @dougbarth@&amp;#8217;s fork it would be clear that @datanoise@&amp;#8217;s is the one to watch in the future.&lt;/p&gt;
&lt;h3&gt;Moving Forward&lt;/h3&gt;
&lt;p&gt;It may seem strange, and perhaps even like a lot of work. &amp;#8220;Why should I have to check to see which is the most current? In the old model, there&amp;#8217;s always a canonical repository.&amp;#8221;&lt;/p&gt;
&lt;p&gt;In the old model, &lt;code&gt;actionwebservice&lt;/code&gt; wouldn&amp;#8217;t have made it past 1.2.6. Welcome to distributed version control.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Linux vs Classic Dev Style</title>
   <link href="http://ozmm.org/posts/linux_vs_classic_dev_style.html" />
   <updated>2009-01-20T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/linux_vs_classic_dev_style</id>
   <content type="html">&lt;p&gt;I tried to leave this as a comment on &amp;#8220;Developer &amp;gt; Project, or Project &amp;gt; Developer(s)?&amp;#8221;:http://journal.dedasys.com/2009/01/10/developer-project-or-project-developer-s but the form errored and I couldn&amp;#8217;t find a contact email address.  Here it is:&lt;/p&gt;
&lt;p&gt;GitHub lets you do Linux-style fork development, or classic SourceForge style development. The difference is you have the choice.&lt;/p&gt;
&lt;p&gt;Using the Network graph you can easily see which fork in a Linux-style network has the most recent activity. It&amp;#8217;s one click away from any repository&amp;#8217;s home page, but we&amp;#8217;re working on better surfacing and summarizing the information.&lt;/p&gt;
&lt;p&gt;As for lazy developers not requesting you pull in changes, the Fork Queue lets you see unmerged changes in forks and even lets you merge them in from the web interface.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re constantly working to improve our tools and the ways you can manage your projects, as well.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>TextMate Minor Mode</title>
   <link href="http://ozmm.org/posts/textmate_minor_mode.html" />
   <updated>2008-12-02T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/textmate_minor_mode</id>
   <content type="html">&lt;p&gt;&lt;a href="http://github.com/defunkt/textmate.el"&gt;TextMate Minor Mode&lt;/a&gt; is an&lt;br /&gt;
Emacs minor mode that emulates some awesome TextMate features.&lt;/p&gt;
&lt;p&gt;Like ⌘T (find file in project).&lt;/p&gt;
&lt;div align="center"&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20081202-ftygk17r4eepyst2be45daxars.png" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;And ⇧⌘T (go to symbol in file).&lt;/p&gt;
&lt;div align="center"&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20081202-kf5965ruf94muuee6ip1y53ype.png" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;And more! Really, the&lt;br /&gt;
&lt;a href="http://github.com/defunkt/textmate.el/tree/master/README.markdown"&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
says it all.&lt;/p&gt;
&lt;p&gt;Installation:&lt;/p&gt;
&lt;pre&gt;
$ cd ~/.emacs.d/vendor
$ git clone git://github.com/defunkt/textmate.el.git
&lt;/pre&gt;
&lt;p&gt;In your emacs config:&lt;/p&gt;
&lt;pre&gt;
(add-to-list 'load-path "~/.emacs.d/vendor/textmate.el")
(require 'textmate)
(textmate-mode)
&lt;/pre&gt;
&lt;p&gt;Or just grab the elisp: &lt;a href="http://github.com/defunkt/textmate.el/raw/master/textmate.el"&gt;textmate.el&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;TextMate Minor Mode was written for &lt;a href="http://aquamacs.org/"&gt;Aquamacs&lt;/a&gt;&lt;br /&gt;
but works great on console Emacs, &lt;span class="caps"&gt;CVS&lt;/span&gt; Emacs.app and Carbon Emacs.  Try&lt;br /&gt;
it today!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Why Lisp Failed</title>
   <link href="http://ozmm.org/posts/why_lisp_failed.html" />
   <updated>2008-12-01T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/why_lisp_failed</id>
   <content type="html">&lt;p&gt;Emacs.&lt;/p&gt;
&lt;p&gt;Writing Lisp without Emacs is just too painful. If your language&lt;br /&gt;
depends on specific features of a specific editor, you better be a big&lt;br /&gt;
company like Sun or Microsoft with the mad moneys. Otherwise forget it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Learning Your Editor</title>
   <link href="http://ozmm.org/posts/learning_your_editor.html" />
   <updated>2008-11-19T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/learning_your_editor</id>
   <content type="html">&lt;p&gt;Text editors should take a lesson from video games. In many games, you have access to subset of total weapons, powers, whatever. As you advance and master the basic weapons, more weapons become available to you. By the end of the game you have direct experience with all or most of the weapons &amp;#8211; from basic to advanced.&lt;/p&gt;
&lt;p&gt;How many times have you done something cool or strange in Vim only to think, &amp;#8220;How did I do that?&amp;#8221; &lt;code&gt;video-game-mode&lt;/code&gt; would be a fun way to learn an editor: start with the basic commands and unlock more as you progress.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Singin' Singletons</title>
   <link href="http://ozmm.org/posts/singin_singletons.html" />
   <updated>2008-11-18T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/singin_singletons</id>
   <content type="html">&lt;p&gt;There&amp;#8217;s stuff I just don&amp;#8217;t understand. David Bowie, for instance. Or the Southern Hemisphere. But nothing quite boggles my mind like Ruby&amp;#8217;s &lt;code&gt;Singleton&lt;/code&gt;. Because really, it&amp;#8217;s totally unnecessary.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what &lt;em&gt;they&lt;/em&gt; want you to do with your code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net/http&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# first you setup your singleton&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cheat&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Singleton&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://cheat.errtheblog.com/&amp;#39;&lt;/span&gt;
    &lt;span class="vi"&gt;@http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@host&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&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;sheet&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="vi"&gt;@http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/s/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;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;body&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# then you use it&lt;/span&gt;
&lt;span class="no"&gt;Cheat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;migrations&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;Cheat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;yahoo_ceo&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;But that&amp;#8217;s crazy. Fight the power.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net/http&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# here&amp;#39;s how we roll&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Cheat&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;host&lt;/span&gt;
    &lt;span class="vi"&gt;@host&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://cheat.errtheblog.com/&amp;#39;&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;http&lt;/span&gt;
    &lt;span class="vi"&gt;@http&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&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;sheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/s/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;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;body&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# then you use it&lt;/span&gt;
&lt;span class="no"&gt;Cheat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;migrations&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;Cheat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;singletons&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Any why not? The &lt;span class="caps"&gt;API&lt;/span&gt; is more concise, the code is easier to test, mock, and stub, and it&amp;#8217;s still dead simple to convert into a proper class should the need arise.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Pretty Fixtures</title>
   <link href="http://ozmm.org/posts/pretty_fixtures.html" />
   <updated>2008-11-18T00:00:00-08:00</updated>
   <id>http://ozmm.org//posts/pretty_fixtures</id>
   <content type="html">&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# in whatever test helper you use&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;defunkt&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:defunkt&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;github&lt;/span&gt;
    &lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:github&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# in your tests&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A user&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;belongs to a repository&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="n"&gt;defunkt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Somethin&amp;#8217; like that.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Sugar</title>
   <link href="http://ozmm.org/posts/sugar.html" />
   <updated>2008-10-30T00:00:00-07:00</updated>
   <id>http://ozmm.org//posts/sugar</id>
   <content type="html">&lt;p&gt;The console is part of your app. Treat yourself right.&lt;/p&gt;
&lt;script src="http://gist.github.com/21160.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&lt;br /&gt;
$ ./console &lt;br /&gt;
Loading production environment (Rails 2.0.2)&lt;br /&gt;
&amp;gt;&amp;gt; me = User / :defunkt&lt;br /&gt;
=&amp;gt; #&amp;lt;User id: 2, &amp;#8230; &amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt; repo = User / :defunkt / :gist&lt;br /&gt;
=&amp;gt; #&amp;lt;Repository id: 61713, &amp;#8230; &amp;gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src="http://gist.github.com/21162.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&lt;br /&gt;
User.instance_eval do&lt;br /&gt;
  def /(name)&lt;br /&gt;
    find_by_login(name.to_s)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
Repository.instance_eval do&lt;br /&gt;
  def /(name)&lt;br /&gt;
    find_by_name(name.to_s)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;/pre&gt;&lt;/noscript&gt;</content>
 </entry>
 
 
</feed>
