
On the Floor
One of the the best ways to improve your programming skills is to study other people's code. When your work revolves around open-source technology, you can study the code you use every day.
This has several advantages: you get to study code written by the very best programmers out there, you have an excellent idea of the problem it solves, and you gain a deeper understanding of your tools.
One of those tools is Rack, the interface, or middleware, between web servers and many popular Ruby frameworks, including our two favourites, Rails and Sinatra. Rack is an incredible piece of software that has brought an enviable consistency to Ruby web development.
Last night I was watching Olympic speed skating while sitting on the couch. I took advantage of the interminable delays between races caused by technical issues, damaged ice, and so on, to browse Rack's source code, in particular the code for Rack::Request.
It wasn't my intention to gain an understanding of the entire file, rather, I was just interested in seeing what I could learn from bits and pieces. This method caught my eye:
This looked like an interesting way of turning text like "text/plain;charset=utf-8" into a hash. Problems like this arise pretty frequently when you're doing development, so I decided to hack this apart. The easiest way to do this, I think, is to turn this bit into a stand-alone file, separate the method chains into new lines, and add a debugger line:
This allows us to step through the code line-by-line to see how content_type is transformed throughout the method. If you're interested, give it a try (just download the file and run it from the command line).
What I think is especially interesting is line 9:
This use of inject provides a simple and effective way of creating a hash from a pair of other values, in the process transforming them.
Today as I worked on a project, I found some code I wrote recently that looked like this:
Given a hash (representing an interval) like { :weeks => 4 }, this will return { :weeks => -4 }.
The similarity between this and the code from Rack was pretty self-evident. In both cases, we are creating a new collection containing transformed values from a previous collection. New version of this:
For me, this was a compelling example of the utility of reading open-source code: immediate applicability to one's own work, with the reward of better code - and better understanding.
Subscribe 
Follow us on
Twitter 
Archives
February 2012January 2012
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
May 2011
April 2011
March 2011
February 2011
January 2011
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
October 2009
September 2009
June 2009
March 2009
January 2009
December 2008
November 2008
September 2008
August 2008









Comments
I think you typo'd your new inject method:
interval.inject({}) { |interval,(k,v)| interval[k] = v.abs * -1; interval }
consider using Hash#update instead:
interval.inject({}){|interval,(k,v)| interval.update({k=>v.abs*-1})}
and line 9 from your debug example becomes:
inject({}) { |hash,(k,v)| hash.update({k.downcase => v })}
Chris, it's not a typo - inject returns the memo, which is the value I am looking for.
ozzloy, thanks for the interesting suggestion.
Chris is right, the block for inject needs to return the hash, currently in your example it returns a Fixnum.
Too bad hash doesn't have a smarter #map... http://gist.github.com/306771
I just ran into the issue that Chris pointed out and went here to recant my last comment - he's right. Thanks Chris and Ben, making the correction.
Add a Comment