<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Ruby Best Practices</title><link>http://blog.rubybestpractices.com/</link><description>Increase your productivity -- Write Better Code</description><language>en-us</language><item><title>Ruby Mendicant University is a Go!</title><description>&lt;blockquote&gt;
&lt;p&gt;Born less than 24 hours ago, my &lt;a href="http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html"&gt;Ruby Mendicant University idea&lt;/a&gt; is already more than a third of the way to having its &lt;a href="http://pledgie.com/campaigns/11063"&gt;initial costs  covered.&lt;/a&gt; In less than 12 hours, we&amp;#8217;ve had 35 people &lt;a href="http://spreadsheets.google.com/viewform?formkey=dHlLM2E1ZllqN2hSWWhIWFBXRmthN2c6MQ"&gt;request a copy of the entrance exam.&lt;/a&gt; So now that the idea is validated, it&amp;#8217;s time to begin on the execution.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;You can keep up on the latest news by following the &lt;a href="http://seacreature.posterous.com/tag/rubymendicant"&gt;rubymendicant&lt;/a&gt; tag at &lt;a href="http://seacreature.posterous.com"&gt;seacreature.posterous.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;i&gt;PS: This morning, I decided that &lt;a href="http://seacreature.posterous.com/19694115"&gt;I want to consolidate my blogging and tweeting,&lt;/a&gt; so most of my content will be posted to my new posterous blog rather than here at &lt;span class="caps"&gt;RBP&lt;/span&gt; blog.   Also, I am moving my twitter account over to &lt;a href="http://twitter.seacreature"&gt;@seacreature&lt;/a&gt; exclusively, rather than using &lt;a href="http://twitter.com/rubypractices"&gt;@rubypractices.&lt;/a&gt;   While this isn&amp;#8217;t quite an announcement of ending the &lt;span class="caps"&gt;RBP&lt;/span&gt; Blog project, it&amp;#8217;s a step in that direction.  Thanks so much for your attention and feedback over the last year or so.  Hope to see you on the other side!&lt;/i&gt;&lt;/small&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 04 Jun 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/026-ruby-mendicant-university-is-a-go.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/026-ruby-mendicant-university-is-a-go.html</guid></item><item><title>IDEA: Ruby Mendicant University</title><description>&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:  You can &lt;a href="http://pledgie.com/campaigns/11063"&gt;donate now at Pledgie&lt;/a&gt; / I know this is early, but in the spirit of Ruby Mendicant, I&amp;#8217;m looking for those trusting individuals who will give with altruistic intentions first, I&amp;#8217;ll spend my time convincing everyone else later :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2: More details to come, but those who wish to receive a copy of the entrance exam should &lt;a href="http://is.gd/cBNH9"&gt;sign up via this google form.&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Back in 2008, the highlight of my year was the &lt;a href="http://majesticseacreature.com/mendicant/"&gt;Ruby Mendicant&lt;/a&gt; project.  Through some stroke of luck, I ended up getting enough funding from independent community donations to take 22 weeks off of work to focus on building &lt;a href="http://prawn.majesticseacreature.com"&gt;Prawn&lt;/a&gt;, a pure ruby &lt;span class="caps"&gt;PDF&lt;/span&gt; generation library that is now nearing its 1.0 release.&lt;/p&gt;
&lt;p&gt;Now in 2010, I&amp;#8217;d like to do the same thing for Ruby training and education.  Similar to my &lt;a href="http://www.oreillynet.com/ruby/blog/2008/03/id_love_to_quit_my_job_sort_of.html"&gt;original post that spawned Ruby Mendicant&lt;/a&gt;, the details are currently fuzzy in my head, but I have enough of a rough outline to collect some comments on.&lt;/p&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;I want to run a free online school designed to help intermediate Ruby programmers master their craft.  Each session would include up to 20 or so participants and run for 3 weeks.&lt;/p&gt;
&lt;p&gt;The basic activities would include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;an entrance exam (basic coding problem and questionnaire)&lt;/li&gt;
	&lt;li&gt;selected readings in freely available Ruby books and online resources&lt;/li&gt;
	&lt;li&gt;individual and group code review&lt;/li&gt;
	&lt;li&gt;realistic problems to work on and discuss&lt;/li&gt;
	&lt;li&gt;Q&amp;amp;A sessions&lt;/li&gt;
	&lt;li&gt;a final exam (which if passed, would earn the student &amp;#8216;alumni&amp;#8217; status)&lt;/li&gt;
	&lt;li&gt;possibly some pre-recorded or live presentations&lt;/li&gt;
	&lt;li&gt;a mailing list for students to discuss questions with me&lt;/li&gt;
	&lt;li&gt;online discussions with guest speakers from our community.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal would be to keep these classes going on a rolling basis, so that we could reach a large number of students in the course of a year.  If we did a schedule like 3 weeks on, 1 week off, we could do 13 sessions in a year, allowing me to reach up to 260 students.&lt;/p&gt;
&lt;p&gt;Of the available slots, I would also like to reserve a certain amount of them for &amp;#8220;hardship&amp;#8221; situations.  People who are currently out of work, those who are in tough economic climates, or have some sort of difficulty in their lives that this opportunity could really help them overcome.  I have not yet figured out how to do this without introducing a ton of bias in my selections, and I have no way of verifying these details, but it seems like a good idea in theory to me at least.&lt;/p&gt;
&lt;p&gt;At least some of the sessions would be open to the community at large, and at least some of the material would be released under an open documentation license.  This way, while the core focus would be on affecting big change for small groups at a time, the whole community could benefit from the existence of this program as well.&lt;/p&gt;
&lt;h3&gt;Funding&lt;/h3&gt;
&lt;p&gt;The up front cost of building the material is large, enough where I would need to take a couple days off a week from consulting work for a period of 8 weeks or so to come up with adequate material.  While the replacement cost for that work is pretty high (over 6k), I could probably still get by well enough if I had about $3000 in donations to produce the initial material.&lt;/p&gt;
&lt;p&gt;The promising thing about the above lesson plan is that since a lot of it is interactive and tailored to individual efforts, once I build the core lesson plan, actually running the &amp;#8220;school&amp;#8221; will be comparatively less work.  I won&amp;#8217;t know at all until I actually run it, but I would expect that I could keep the school up and running for about $1500 a month.&lt;/p&gt;
&lt;p&gt;But in the Mendicant spirit, I only would want to keep this thing going if it was of value to the community.  So rather than looking for donations for the running of the school up front, I would only raise money to cover the initial costs of content creation.&lt;/p&gt;
&lt;p&gt;Whether the school lives or dies, grows or shrinks, would be based on the generosity of previous students as well as that of the community at large.&lt;/p&gt;
&lt;h3&gt;Schedule&lt;/h3&gt;
&lt;p&gt;If I could raise enough money by the end of June, I could then shift my schedule around in July and August to allow me to work on content creation.  That would let me start the first class around the first week of September.&lt;/p&gt;
&lt;h3&gt;Why Me?&lt;/h3&gt;
&lt;p&gt;Besides the &lt;a href="http://http://majesticseacreature.com/mendicant/"&gt;Ruby Mendicant&lt;/a&gt; project, I have also taught trainings at the Lone Star Ruby Conference (2008,2009), and am also part of the trio hosting &lt;a href="http://thecompleatrubyist.com/"&gt;The Compleat Rubyist&lt;/a&gt;.  I have written two books that are now completely free for people to download and read.  And other stuff.&lt;/p&gt;
&lt;p&gt;Trust me.  I&amp;#8217;d be good at this :)&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re wondering what&amp;#8217;s in it for me:  I believe that free education is one of the most valuable things in the world, and I also learn a ton by teaching others.  If I can make enough money to offset my costs and maintain a decent house-and-wife life, I feel like this is a super good use of my time.&lt;/p&gt;
&lt;h3&gt;What do you think?&lt;/h3&gt;
&lt;p&gt;Right now, feedback is key.  I only want to take this project on if I think it&amp;#8217;ll be a sure thing.   Please respond, answering these questions:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Would you want to attend this online school?&lt;/li&gt;
	&lt;li&gt;Would you be willing to donate to help with its creation?&lt;/li&gt;
	&lt;li&gt;Would you recommend this program to others?&lt;/li&gt;
	&lt;li&gt;What can I do to make it even more awesome?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks in advance for your suggestions.  Here&amp;#8217;s hoping that we can make this work :)&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:  You can &lt;a href="http://pledgie.com/campaigns/11063"&gt;donate now at Pledgie&lt;/a&gt; / I know this is early, but in the spirit of Ruby Mendicant, I&amp;#8217;m looking for those trusting individuals who will give with altruistic intentions first, I&amp;#8217;ll spend my time convincing everyone else later :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2: More details to come, but those who wish to receive a copy of the entrance exam should &lt;a href="http://is.gd/cBNH9"&gt;sign up via this google form.&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 03 Jun 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html</guid></item><item><title>If you want to see the wizard, go to Oz.</title><description>&lt;p&gt;Back in June of 2005, I booked a flight out to Oklahoma City, OK, but it might as well have been to Oz.  I was off to see the wizard who had been teaching me black magic in both Perl and Ruby throughout my high school days.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.grayproductions.net"&gt;James Edward Gray II&lt;/a&gt; and I had somehow convinced Ruby Central, Inc. that a &lt;a href="http://rubyforge.org/projects/gambit"&gt;web game framework&lt;/a&gt; was worth a Codefest grant, and we used the money as a chance to finally meet each other in person.  At the time, we decided to build things from scratch, since Rails 0.12 didn&amp;#8217;t quite have the features we needed :)&lt;/p&gt;
&lt;p&gt;Not counting the friends I talked into studying programming here and there, this was my first time ever working side by side with another hacker.  I didn&amp;#8217;t know what to expect, but by the time I left, I couldn&amp;#8217;t believe that what we had done was possible.  Safe to say, JEG2 blew my mind, in the way that any good wizard can.   Here&amp;#8217;s what I wrote just after returning home in June 2005:&lt;/p&gt;
&lt;blockquote&gt;&lt;i&gt;&lt;br /&gt;
The last nine days were amazing. Exploited undocumented features of WEBRick.&lt;br /&gt;
Making use of circular logic flows, making code do things that it wasn&amp;#8217;t built&lt;br /&gt;
to do. Pushing the limits, building truly clever tools and libraries that will&lt;br /&gt;
make people&amp;#8217;s lives easier, and more fun. &lt;br /&gt;
&lt;br /&gt;
I myself feel like I&amp;#8217;m standing a little taller after all the hard work we&lt;br /&gt;
did. That was hacking in it&amp;#8217;s purest nature, and though I don&amp;#8217;t like to self&lt;br /&gt;
attribute that word, there is nothing else to describe it. Ideas flowed any &lt;br /&gt;
hour of the day, even in our dreams. No one tried to take charge, I didn&amp;#8217;t get &lt;br /&gt;
mad when James replaced bits of my code with something better, and James &lt;br /&gt;
didn&amp;#8217;t get mad when I questioned his logic and pushed him to raise the bar. In &lt;br /&gt;
the rare occasion that I proved James wrong on something, he&amp;#8217;d just shrug his &lt;br /&gt;
shoulders, embrace The Right Way, and go with it.&lt;br /&gt;
&lt;br /&gt;
We joked around a lot referring to certain programming practices as &amp;#8220;The way &lt;br /&gt;
of life&amp;#8221;. Though that is quite silly when it applies to 80 character linewrap &lt;br /&gt;
or a certain tab width, it was something that motivated us. We could look at &lt;br /&gt;
our code, and at a glance see if it was following &amp;#8220;The way&amp;#8221; or not. When it &lt;br /&gt;
wasn&amp;#8217;t, we waited for something better to come along, and then we did what we &lt;br /&gt;
had to do to make it happen.&lt;br /&gt;
&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, I was just a kid at the time, but I knew something important had just happened.  Most importantly I realized that the kind of interaction you can have over the internet, though amazing, pales in comparison to face-to-face interaction.  Here&amp;#8217;s what James had to say shortly after our first meeting:&lt;/p&gt;
&lt;blockquote&gt;&lt;i&gt;&lt;br /&gt;
&amp;#8220;We&amp;#8217;ve just completed nine solid days of development on Gambit. Now&lt;br /&gt;
that&amp;#8217;s a &amp;#8220;Codefest&amp;#8221; alright! I thought I would share a little with&lt;br /&gt;
the curious about how I think it went&amp;#8230;&lt;br /&gt;
&lt;br /&gt;
Greg Brown flew out to my home in Oklahoma so we could work on&lt;br /&gt;
Gambit. It was nice to finally meet face-to-face. We&amp;#8217;ve actually&lt;br /&gt;
programmed together on many projects these last couple of years, but&lt;br /&gt;
this was the first time we didn&amp;#8217;t do it over the Internet. We&amp;#8217;re&lt;br /&gt;
both grateful to the wonderful people at Ruby Central for giving us&lt;br /&gt;
that opportunity.&lt;br /&gt;
&lt;br /&gt;
We&amp;#8217;ve had practice, so we work pretty well together by now. Greg&lt;br /&gt;
would probably say that I&amp;#8217;ve almost beat all his bad habits out of&lt;br /&gt;
him. ;) True or not, I know he&amp;#8217;s always challenging me and pushing&lt;br /&gt;
me to new limits of what I can build. I think we both learned a lot&lt;br /&gt;
from working together on this project.&lt;br /&gt;
&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;While there is a certain amount of altruism involved in mentoring a novice, it is an act that pays you back tenfold.  Every concept that you can teach another person is one that you must master through and through, in ways that you&amp;#8217;d never even scratch the surface of on your own.&lt;/p&gt;
&lt;p&gt;Whether he realizes it or not, James revealed a secret to me during that hackfest, one that is to blame for all of my future successes in programming: &lt;i&gt;Share your experiences and knowledge with others, and you win.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Fast forward to 2010, and obviously JEG2 and I have come a long way.  We&amp;#8217;ve both done talks throughout the US, and James even made it over to Japan last year.  We&amp;#8217;ve both published books on Ruby, and made more friends in the community than we ever imagined possible back in 2005.  While part of me feels indebted to James still, I feel like I&amp;#8217;ve paid it forward through my works.  That made our mentorship role turn into a friendly rivalry, where we both keep pushing each other to get better at what we do, even if indirectly.&lt;/p&gt;
&lt;p&gt;James had a big head start, so he normally beats me to the punch on things.  Up until recently, I had only one thing under my belt that JEG2 didn&amp;#8217;t: I had &lt;a href="http://2007.goruco.com/volunteers/"&gt;helped design and run a Ruby conference&lt;/a&gt;. Not one to be outdone, JEG2 has decided to level that playing field by running &lt;a href="http://reddirtrubyconf.com"&gt;Red Dirt RubyConf&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Red Dirt RubyConf: Your ticket to Oz&lt;/h3&gt;
&lt;p&gt;If you like what I&amp;#8217;ve been doing in Ruby, you now know that I owe it all to JEG2.  Here&amp;#8217;s the good news:  He&amp;#8217;s now inviting all of you to his neck of the woods to spend some time hacking, learning, and sharing.  &lt;b&gt;But you need to act fast, &lt;a href="http://reddirtrubyconf.com/register_to_attend"&gt;registration&lt;/a&gt; closes Friday, April 23!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Red Dirt RubyConf is a unique two day conference which blends training in with a uniquely themed single track session lineup.  In it, you won&amp;#8217;t just get to meet James, but also some other amazing Ruby people as well, including Dave Thomas and Jim Weirich.&lt;/p&gt;
&lt;p&gt;The conference is run by James, his lovely wife Dana (who I could write a whole other post about), and some other great folks from the Oklahoma Ruby group.  If you head out there, I can promise you that you&amp;#8217;ll have an awesome time, learn a ton, and meet some amazing people.&lt;/p&gt;
&lt;p&gt;Unfortunately, I won&amp;#8217;t be able to attend, but I&amp;#8217;ll sure be there in spirit.  If you do make it there, tell James I said hi, and have a great time!&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;DISCLOSURE&lt;/span&gt;: I told James I&amp;#8217;d be writing something to promote Red Dirt, but he didn&amp;#8217;t ask me to do this, and he had no idea what I&amp;#8217;d come up with.  So I take 100% responsibility for the contents of this article.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 21 Apr 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/024-wizard-of-oz.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/024-wizard-of-oz.html</guid></item><item><title>rubyproblems.com is now live!</title><description>&lt;p&gt;Back on St. Patrick&amp;#8217;s day, I had made the following plug about rubyproblems.com at the bottom of my last post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This site will provide realistic exercises that test your Ruby and general coding skills, along with detailed tutorials written in the style of &lt;span class="caps"&gt;RBP&lt;/span&gt; explaining possible solutions to the problems. The exercises will be free and open to everyone, the solutions we&#8217;ll be selling as nicely typeset, professionally edited, &lt;span class="caps"&gt;DRM&lt;/span&gt;-free &lt;span class="caps"&gt;PDF&lt;/span&gt; download&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am pleased to announce that this service did indeed launch yesterday, and that you can give it a try by heading over to &lt;a href="http://rubyproblems.com"&gt;rubyproblems.com&lt;/a&gt; now.  If you need a bit more information, consider checking out &lt;a href="http://rubybestpractices.com/rubyproblems-teaser.swf"&gt;this screencast&lt;/a&gt; or &lt;a href="http://rubyproblems.blogspot.com/2010/04/were-live.html"&gt;this announcement&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While this is still a bit of an experiment for us, we&amp;#8217;re really excited to see how things turn out.  Those who liked my book should love this site, which is why I&amp;#8217;m announcing it here.&lt;/p&gt;
&lt;p&gt;But now, the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog should return to its non-marketing-hype self.  In fact, I really want to find the time to write about why I think this is the most horrible syntax ever:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
describe Array do
  its(:length) { should == 0 }
end
&lt;/pre&gt;
&lt;p&gt;But I suppose that bit of flame bait will need to wait until a later day :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 07 Apr 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/023-rubyproblems.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/023-rubyproblems.html</guid></item><item><title>Full Book Now Available For Free!</title><description>&lt;p&gt;The last few weeks have been a wild ride.  Starting in January, I&amp;#8217;ve been releasing a chapter at a time here on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog, and many of those chapters were pretty well commented on.  Just for the sake of completeness, here&amp;#8217;s a link back to each of those posts:&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html"&gt;Chapter 6: When Things Go Wrong&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html"&gt;Chapter 7: Reducing Cultural Barriers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, I&amp;#8217;d like to invite you to just &lt;a href="http://sandal.github.com/rbp-book/pdfs/rbp_1-0.pdf"&gt;grab the whole thing&lt;/a&gt; and read it at your leisure.  This includes the final chapter &amp;#8220;Skillful Project Maintenance&amp;#8221;, as well as the three appendixes: &amp;#8220;Writing Backwards Compatible Code&amp;#8221;, &amp;#8220;Leveraging Ruby&amp;#8217;s Standard Library&amp;#8221;, and &amp;#8220;Ruby Worst Practices&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Since the book is now open source, if you find something you don&amp;#8217;t like about it, it&amp;#8217;s your responsibility to help make it better!  But if you do like it as it is, it might be more pleasant to read in print or on your Kindle, so you might want to pick it up from &lt;a href="http://oreilly.com/catalog/9780596523015/"&gt;O&amp;#8217;Reilly&lt;/a&gt; or &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Manuscript and Production Files&lt;/h3&gt;
&lt;p&gt;You can find the details about the &lt;a href="http://github.com/sandal/rbp-book"&gt;manuscript and production files on github&lt;/a&gt;, now released under a Creative Commons license.  It might be a little while before I can put some time into making this contributor friendly, but those looking to experiment or explore a bit are certainly welcome.  The manuscript is written using the &lt;a href="http://www.methods.co.nz/asciidoc/"&gt;amazing asciidoc toolchain&lt;/a&gt;, which means the plaintext files you see in the git repository actually are what I used to generate something very close to the final print version of &lt;span class="caps"&gt;RBP&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So that&amp;#8217;s pretty much it.  While this will soon mark a new beginning, this figuratively and literally marks the last chapter in the history of &lt;span class="caps"&gt;RBP&lt;/span&gt; being &amp;#8220;my book&amp;#8221;.  It&amp;#8217;s yours now, do what you want with it.  If you have interesting ideas that you want to run by me, I&amp;#8217;d be happy to help however I can.  Otherwise, enjoy and have fun!&lt;/p&gt;
&lt;h3&gt;But I finished the &lt;span class="caps"&gt;RBP&lt;/span&gt; book and I want more!  What should I do?&lt;/h3&gt;
&lt;p&gt;Okay, you got me.  I&amp;#8217;ve been trying to take the &amp;#8220;spirit&amp;#8221; of &lt;span class="caps"&gt;RBP&lt;/span&gt; and apply it to two new projects, both a little more interactive in nature.  For those who enjoyed the book, you may be interested in these two resources, both on the horizon.&lt;/p&gt;
&lt;p&gt;The first is &lt;a href="http://rubyproblems.com"&gt;rubyproblems.com&lt;/a&gt;.  This site will provide realistic exercises that test your Ruby and general coding skills, along with detailed tutorials written in the style of &lt;span class="caps"&gt;RBP&lt;/span&gt; explaining possible solutions to the problems.  The exercises will be free and open to everyone, the solutions we&amp;#8217;ll be selling as nicely typeset, professionally edited, &lt;span class="caps"&gt;DRM&lt;/span&gt;-free &lt;span class="caps"&gt;PDF&lt;/span&gt; downloads.  We launch April 6th, 2010, but if you &lt;a href="http://rubyproblems.com/login"&gt;register now&lt;/a&gt;, you&amp;#8217;ll get a free solution download when the site goes live.  Whether you plan on buying content or not, the exercises themselves should provide great learning opportunities.  If you liked &lt;span class="caps"&gt;RBP&lt;/span&gt;, you&amp;#8217;ll definitely like Ruby Problems.&lt;/p&gt;
&lt;p&gt;The second chance to bolster what you&amp;#8217;ve learned in &lt;span class="caps"&gt;RBP&lt;/span&gt; is to attend a &lt;a href="http://thecompleatrubyist.com/"&gt;Compleat Rubyist&lt;/a&gt; training event.  This is a joint venture between David A. Black, Jeremy McAnally, and myself that&amp;#8217;s designed to provide a crash course in going from &amp;#8220;knowing Ruby&amp;#8221; to &amp;#8220;being awesome at Ruby&amp;#8221;.  We did one of these in Tampa, FL in January, and it was blast.  Our next one is scheduled for the Chicago area on June 18-19.  We plan to do this as a regular thing, so if you can&amp;#8217;t make it out to the Midwest, let us know where we should be going to find you!  If you want a little more detail, you can check out &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/359006"&gt;my RubyTalk announcement about the upcoming event&lt;/a&gt;, and perhaps take a look at the &lt;a href="http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html"&gt;Tampa retrospective&lt;/a&gt; here on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog.&lt;/p&gt;
&lt;h3&gt;Disclaimer&lt;/h3&gt;
&lt;p&gt;While I typically hate direct marketing, I am absolutely excited about the above two things, and so I felt compelled to mention them as good &amp;#8216;next steps&amp;#8217; as you go beyond &lt;span class="caps"&gt;RBP&lt;/span&gt;.  Doing these as commercial projects won&amp;#8217;t ever make me rich, but it does allow me to take time away from billable work and really focus on producing awesome content and engaging with those who could learn something from it.  So just know that whenever you send a bit of cash my way, you&amp;#8217;re supporting a fellow hacker who will keep giving back at every opportunity.&lt;/p&gt;
&lt;p&gt;But for those a bit weary of marketing gimmicks, the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog will be going back to its pristine &amp;#8220;no fluff, just stuff&amp;#8221; program after today.  It is a little hard to keep new content flowing, but we&amp;#8217;ll do the best we can.  Until then, happy hacking!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 17 Mar 2010 16:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/022-rbp-now-open.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/022-rbp-now-open.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 7</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first five chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html"&gt;Chapter 6: When Things Go Wrong&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;In 2010, programmers no longer have an excuse for not having a baseline understanding of multilingualization and localization techniques.  But for those who have not yet taken a crash course, this chapter on &amp;#8220;Reducing Cultural Barriers&amp;#8221; provides a primer that should be good enough to get you started.&lt;/p&gt;
&lt;p&gt;Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch07.pdf"&gt;download Chapter 7 now&lt;/a&gt;.  You&amp;#8217;re encouraged to participate in the discussion here once you&amp;#8217;ve had a chance to play with some of the ideas from the book. Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.16) for the final chapter, &amp;#8220;Skillful Project Maintenance&amp;#8221;, which covers Ruby&amp;#8217;s built in project management tools, and some of the techniques surrounding them.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet (though I&amp;#8217;m getting closer now, finally!)&lt;/p&gt;
&lt;p&gt;If you like what you see, please buy the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  I imagine that seeing decent sales numbers will encourage O&amp;#8217;Reilly to keep moving towards making their content openly available, which would totally rock.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents for the manuscript are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 09 Mar 2010 14:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 6</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first five chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;This chapter on what to do &amp;#8220;When Things Go Wrong&amp;#8221; turned out to be one of the most enjoyable ones to write.  Having a strong ability to troubleshoot and debug code is a powerful skill to have, and I do my best to share all my secrets here.&lt;/p&gt;
&lt;p&gt;Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch06.pdf"&gt;download Chapter 6 now&lt;/a&gt;.  You&amp;#8217;re encouraged to participate in the discussion here once you&amp;#8217;ve had a chance to play with some of the ideas from the book. Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.09) for Chapter 7, &amp;#8220;Reducing Cultural Barriers&amp;#8221;, which covers multilingualization (m17n) and localization (L10n) techniques.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet (though I&amp;#8217;m getting closer now, finally!)&lt;/p&gt;
&lt;p&gt;If you like what you see, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  I imagine that seeing decent sales numbers will encourage O&amp;#8217;Reilly to keep moving towards making their content openly available, which would totally rock.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents for the manuscript are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 02 Mar 2010 07:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 5</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first four chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re willing to participate in the discussion afterwards, go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch05.pdf"&gt;download Chapter 5 now&lt;/a&gt;.  Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;This chapter was supposed to be my &amp;#8220;fun&amp;#8221; topic, but turned out to be more practical than I expected.  I had originally started out writing about how to do functional programming in Ruby, but later realized that was an incredibly bad idea.   Ruby isn&amp;#8217;t a great functional programming language, but certain functional programming techniques do still pay off.  This chapter is about those techniques.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.02) for Chapter 6, &amp;#8220;When Things Go Wrong&amp;#8221;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting several more weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 23 Feb 2010 15:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 4</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first three chapters, and discussion has been great.  If you haven&amp;#8217;t seen them already, check out the first week&amp;#8217;s &lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;discussion on testing&lt;/a&gt;, and then head over and look at the &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;double header on &lt;span class="caps"&gt;API&lt;/span&gt; design and metaprogramming&lt;/a&gt;.  These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re willing to participate in the discussion afterwards, go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch04.pdf"&gt;download Chapter 4 now&lt;/a&gt;.  Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;While chapters 2 and 3 were about somewhat subtle features, this chapter is as concrete as they come.  Those with some Perl blood in them should find it familiar, as it&amp;#8217;s all about how to munge text and move stuff around on your filesystem.  But those who struggle with the scripting side of Ruby should find a number of techniques that will make their job easier.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.02.23) for Chapter 5, &amp;#8220;Functional Programming Techniques&amp;#8221;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting several more weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 16 Feb 2010 15:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html</guid></item><item><title>RBP is useless without you</title><description>&lt;p&gt;&lt;em&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2010.02.13: Lots of folks have taken the initiative to comment after reading this, and others have pointed out that they indeed need more time before they can comment.  But since people seem generally interested in seeing Ch4 sooner rather than later, I&amp;#8217;ll release it on Tuesday.  Coincidentally, there is a great post I found on HN that does a better job than I did summarizing how tech books (especially &lt;span class="caps"&gt;RBP&lt;/span&gt;) ought to be read.  If you haven&amp;#8217;t seen it yet, go read &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;Kenjitsu&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Since I&amp;#8217;ve posted the &lt;a href="http://github.com/sandal/rbp-book/tree/gh-pages/pdfs/"&gt;first three chapters&lt;/a&gt;, my amazon ratings have gone way up, and I&amp;#8217;ve seen lots of people mention the book on twitter.  This is great for marketing, but as you may know, I care much more about the actual content here.&lt;/p&gt;
&lt;p&gt;Things started out great!  We had an &lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;awesome discussion about testing&lt;/a&gt; two weeks ago and I expected to see the same on &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;APIs and metaprogramming&lt;/a&gt;.  But as it turned out, only two brave souls offered up their thoughts, even though lots of people downloaded the content.  That was a big disappointment to me, and now I&amp;#8217;m trying to guess at what went wrong.&lt;/p&gt;
&lt;p&gt;One possibility is that I&amp;#8217;ve oversaturated folks, so I&amp;#8217;m giving everyone an extra week to &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;comment on Ch2-3&lt;/a&gt; before I put out the &amp;#8220;Text Processing and File Management&amp;#8221; chapter.  Hopefully, by next Friday we&amp;#8217;ll have a good discussion going there, and the Ch4 release will just keep the ball rolling.&lt;/p&gt;
&lt;p&gt;But far more grave, is my fear that some folks might be too timid to express their thoughts about the material, perhaps because it&amp;#8217;s in book form rather than written up in some generic blog post.  This to me, is exactly what will prevent them from getting anything worthwhile out of my book.  So if you&amp;#8217;ve been holding back comments just because you didn&amp;#8217;t want to challenge RBP&amp;#8217;s &amp;#8220;bookiness&amp;#8221; out in the open, please don&amp;#8217;t.  I can handle all sorts of criticism, and the book will benefit as a result of it.&lt;/p&gt;
&lt;p&gt;I am very serious about the idea that &amp;#8220;Best Practices&amp;#8221; really don&amp;#8217;t have much value in a vacuum. I&amp;#8217;m certain that the benefits that my book can offer its readers are maximized in open conversation.  This is why I made sure to build an eventual open content licensing into RBP&amp;#8217;s contract, and why I&amp;#8217;m releasing free chapters now.&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;RBP&lt;/span&gt; is useless without you, so please, participate.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 12 Feb 2010 05:24:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/017-rbp-useless.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/017-rbp-useless.html</guid></item><item><title>Weekend Reading: RBP Chapters 2-3</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;p&gt;If you missed &lt;a href="http://www.blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;last week&amp;#8217;s post&lt;/a&gt;, which introduces chapter 1, you&amp;#8217;ll want to check that out.  There was some great discussion among readers that add a lot to what I had to say in the book.  I expect we&amp;#8217;ll see the same thing happen this time around.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topics&lt;/h3&gt;
&lt;p&gt;This week, I&amp;#8217;m releasing two chapters, &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch02.pdf"&gt;Designing Beautiful APIs&lt;/a&gt; and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch03.pdf"&gt;Mastering the Dynamic Toolkit&lt;/a&gt;.  Incase the latter sounds familiar, it is indeed the book&amp;#8217;s sample chapter.  But it also happens to be my favorite chapter in the book, so I didn&amp;#8217;t want to skip over it without a chance for discussion.&lt;/p&gt;
&lt;p&gt;So remember, if you click those links, your responsibility is to participate in the discussion here by offering up your thoughts about what you&amp;#8217;ve read.  Best practices cannot be rules that are simply absorbed and followed if they are to be of any use&amp;#8230; instead, they must be extracted from and influenced by those who work with the real problems that they are meant to solve.&lt;/p&gt;
&lt;p&gt;It would be great to hear your experiences with the topics these chapters cover, even if they&amp;#8217;re not directly related to the book content.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting eight weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway that&amp;#8217;s all for now, enjoy the chapters and let me know what you think!&lt;/em&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 05 Feb 2010 14:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html</guid></item><item><title>Weekend Reading: RBP Chapter 1</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;p&gt;For the next 8 weeks, I will post a chapter from &lt;span class="caps"&gt;RBP&lt;/span&gt; every Friday.  You don&amp;#8217;t need to pay me a cent if you download it, but what I do want you to do is leave a comment here sharing your thoughts once you&amp;#8217;ve finished reading.  This way, we can use RBP&amp;#8217;s content as a jumping off point for conversation, rather than treating it like some sort of static rulebook. Through this process, we can discover what our common practices really are.  Over time, I will incorporate these ideas back into the manuscript, helping to keep the book up to date and relevant.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;The first chapter I am releasing is &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch01.pdf"&gt;Driving Code Through Tests&lt;/a&gt;,  which covers a number testing philosophies and techniques.  It aims to be framework agnostic, but leans on the Test::Unit &lt;span class="caps"&gt;API&lt;/span&gt; for its examples.  The core idea of this chapter is to expose folks to the &amp;#8220;spirit&amp;#8221; of testing, rather than just the mechanics of it.&lt;/p&gt;
&lt;p&gt;Upon re-reading this chapter in the winter of 2010 having written it in the spring of 2008, there are definitely a couple things I think differently about now.  But as it turns out, I was more surprised by how much hasn&amp;#8217;t changed, and how well this chapter seems to have stood the test of time.  Of course, you may disagree, and I encourage you to tell me so if that&amp;#8217;s the case. :)&lt;/p&gt;
&lt;p&gt;Ready to get started?  Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch01.pdf"&gt;download the chapter&lt;/a&gt; now.  Remember, if you click that link, I&amp;#8217;m expecting you to post back here with your thoughts (or alternatively, write a response on your own blog and send me a link).  If you find a technical error, you can report it via &lt;a href="http://github.com/sandal/rbp-book/issues"&gt;Github issues&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting eight weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway that&amp;#8217;s all for now, enjoy the chapter and let me know what you think!&lt;/em&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 29 Jan 2010 14:32:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html</guid></item><item><title>Reflections from "The Compleat Rubyist"</title><description>&lt;p&gt;Ever since 2005, I&amp;#8217;ve been attending and speaking at Ruby events.  But the one thing I always wanted to do was run training sessions.  Thankfully, over the last couple years, &lt;span class="caps"&gt;LSRC&lt;/span&gt; has allowed me to get my feet wet &amp;#8212; but only as one of many excellent choices in a lineup of Ruby&amp;#8217;s best and brightest.  Until last weekend, I had never participated in professional training event that stood on its own.&lt;/p&gt;
&lt;p&gt;What eventually became &amp;#8220;The Compleat Rubyist&amp;#8221; training, was originally an idea for &amp;#8220;The Compleat Rubyist&amp;#8221; book promotion.  Jeremy McAnally, David A. Black, and myself have all written Ruby books, and they seem to compliment each other well.  But in doing this, we realized that it would be more valuable, and more fun, to bring our show out on the open road rather than package it up in a box set.&lt;/p&gt;
&lt;p&gt;Thus, our training event was born, and we set our sights on Tampa, FL for its first incarnation.&lt;/p&gt;
&lt;h3&gt;The Training&lt;/h3&gt;
&lt;p&gt;Instead of having a linear, specific set of bullet points to teach from, we broke our training into four half-day sessions that are representive of some of the most important topics in the Ruby ecosystem.  This gave us a lot of leeway to adjust our materials and discussions based on individual student needs.   The topics we picked were &amp;#8220;Ruby Versions and Implementations&amp;#8221;, &amp;#8220;Metaprogramming&amp;#8221;, &amp;#8220;Testing&amp;#8221;, and &amp;#8220;Style and Substance&amp;#8221;.   Though these may seem a bit amorphous on first sight, they do a pretty good job of covering four key topics that a budding Rubyist must understand and come to appreciate.&lt;/p&gt;
&lt;p&gt;Here are just a few thoughts from each of the modules, after seeing how things played out in class.&lt;/p&gt;
&lt;h4&gt;Ruby Versions and Implementations&lt;/h4&gt;
&lt;p&gt;One of the main things that keep people from trying out the alternative Ruby implementations and the various versions of Ruby is that they&amp;#8217;re understandably afraid of messing up their systems.  So David took a three-pronged approach to helping students overcome that fear.&lt;/p&gt;
&lt;p&gt;The easiest stepping stone, perhaps, was to use &lt;a href="http://ruby-versions.net/"&gt;ruby-versions.net&lt;/a&gt;.  This great resource (maintained by David), lets you try out all sorts of ruby versions and implementations via a shell account so that you don&amp;#8217;t need to worry about touching anything on your own machine.  While this isn&amp;#8217;t meant to be a long term solution, it&amp;#8217;s probably the easiest way that you can try out pretty much any version of Ruby without having to go hunt down, install, and configure their packages.&lt;/p&gt;
&lt;p&gt;In addition to this, David showed folks how to make use of multiruby (a tool that&amp;#8217;s part of ZenTest).  My favorite example of the whole day was one showing that using Ruby 1.8.7, it&amp;#8217;s possible to write code that works on neither 1.8.6 nor 1.9.1, which lead into a whole other interesting discussion:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  $ multiruby -e "p 'hello'.map(&amp;amp;:upcase)"

  VERSION = 1.8.6-p388
  CMD     = ~/.multiruby/install/1.8.6-p388/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  -e:1: wrong argument type Symbol (expected Proc) (TypeError)

  RESULT = pid 3988 exit 1

  VERSION = 1.8.7-p249
  CMD     = ~/.multiruby/install/1.8.7-p249/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  ["HELLO"]

  RESULT = pid 3991 exit 0

  VERSION = 1.9.1-p378
  CMD     = ~/.multiruby/install/1.9.1-p378/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  -e:1:in `&amp;lt;main&amp;gt;': undefined method `map' for "hello":String (NoMethodError)

  RESULT = pid 3995 exit 1

  TOTAL RESULT = 2 failures out of 3

  Passed: 1.8.7-p249
  Failed: 1.8.6-p388, 1.9.1-p378
&lt;/pre&gt;
&lt;p&gt;We also took a look at &lt;a href="http://rvm.beginrescueend.com/"&gt;rvm&lt;/a&gt; , which is another neat tool for managing multiple Ruby versions.  While not necessarily a tool for every possible need, it is a very easy way of managing multiple rubies side by side without trashing your system-wide configurations.&lt;/p&gt;
&lt;p&gt;Between these three tools, the students ended up with all they needed to explore the different implementations and versions for themselves.   But that was really just the beginning.   David then went on to discuss the various peculiarities across the board, and was sure to discuss where certain implementations or versions excel, and where they fall behind.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m happy to say that while very few of the students in our class had even tried Ruby 1.9 before our training, every one of them had the opportunity to do so before this session ended.&lt;/p&gt;
&lt;h4&gt;Meta-programming&lt;/h4&gt;
&lt;p&gt;At one point in time, everyone using Ruby thought meta-programming was some sort of magic.  But in a post-Rails world, it is increasingly easy to help folks understand that all of this &amp;#8220;voodoo&amp;#8221; we do is really just making use of public method calls provided by Ruby objects that allow you to modify Ruby itself.  Once a decent understanding of Ruby&amp;#8217;s object model is established, all of the rest of the puzzle pieces just seem to fall into place.&lt;/p&gt;
&lt;p&gt;This session had a lot of great discussions, and several exercises to encourage students to actively learn the tricks of the trade.   Along the way, we stumbled across this interesting distinction between &lt;tt&gt;undef_method&lt;/tt&gt; and &lt;tt&gt;remove_method&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    def foo
      "bar"
    end
  end

  class B &amp;lt; A
    def foo
      "baz"
    end

    remove_method :foo
  end

  class C
    def foo 
      "bar"
    end
  end

  class D &amp;lt; C
    def foo
      "baz"
    end

    undef_method :foo
  end

  p B.new.foo # "bar"

  p D.new.foo # raise NoMethodError
&lt;/pre&gt;
&lt;h4&gt;Testing&lt;/h4&gt;
&lt;p&gt;Fortunately, virtually all of our students had experience with test driven development of some sort or another.  I think that&amp;#8217;s a big difference between the Ruby ecosystem today and of say, 5 years ago.  But similar to versions and implementations, there are so many choices out there that it&amp;#8217;s hard to know what&amp;#8217;s what.  Jeremy kicked off this module with a state of the union address, breaking down the various different philosophies and toolchains there are out there, and what each of them bring to the table.&lt;/p&gt;
&lt;p&gt;Once we got people thinking about the different options for testing out there, we decided to give them a glimpse behind the curtain to realize just how non-magical testing could be.  To do this, we demonstrated not one, but two minimal testing frameworks that we built in less than a page or two of code to demonstrate the key concepts.  While neither of these tools would be sensible to use in production, they both show how non-magical a test runner is under the hood.&lt;/p&gt;
&lt;p&gt;Finally, David gave an open ended testing exercise that was a big hit.   Pizza came, but some of our students ignored it until we reminded them to take a break.   Many kept working on through lunch, all pairing together and actively discussing all sorts of language questions that went far beyond the scope of the exercise.&lt;/p&gt;
&lt;h4&gt;Style and Substance&lt;/h4&gt;
&lt;p&gt;This was my topic, and it went way better than I could have expected it to.  I had a lot more content prepared than what I ended up getting to, mainly because we decided to collect some of the open questions that had come up in class and discuss those before running our scheduled content.  The infamous class variable problem was discussed in great detail, and while I thought I had mastered their weaknesses, I even managed to mess up one of my assumptions about their behavior.  Incase you&amp;#8217;ve never been exposed to this fun before:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    @@foo = "from A"
  end
   
  class B &amp;lt; A
    @@foo = "from B"
  end
   
  # What's the value of @@foo in A now...?
   
  class A
    puts @@foo
  end
   
  # =&amp;gt; from B
   
  # They're shared up the hierarchy?? BOOOO!!!
  # What's even worse? This -&amp;gt;
   
  class C
  end
   
  class D &amp;lt; C
    @@bar = "Magically different..."
  end
   
  class C
    @@bar = "And delicious."
  end
   
  class D
    puts @@bar
    # =&amp;gt; Magically different...
  end
   
  class C
    puts @@bar
    # =&amp;gt; And delicious.
  end
   
  # ZOMG THEY'RE NOT SHARED NOW.
&lt;/pre&gt;
&lt;p&gt;Of course, the only sensible style advice here is to not use class variables at all, and since class instance variables can do the job just as well, that&amp;#8217;s not really a big deal.  We discussed how to do that, and then moved on to the regularly scheduled content.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not sure whether we had an especially strong set of students or if people are just starting to &amp;#8220;get&amp;#8221; basic Ruby style idioms, but based on the first day and a half, it was evident that our students didn&amp;#8217;t need to be told these basic things.   Instead, I talked about &amp;#8220;Ruby Style and Substance&amp;#8221; at a more philosophical and design-oriented level, which is where I think our community tends to be weakest.  Without giving too much away, a lot of my examples stemmed from discussions we&amp;#8217;ve been having about refactoring Prawn before it&amp;#8217;s 1.0 release, so you can check out our mailing list for a whole bunch of interesting design discussions if you want access to some of the raw materials I used for this session.&lt;/p&gt;
&lt;p&gt;In the end, we gave everyone a chance to try their hand at basic &lt;span class="caps"&gt;API&lt;/span&gt; design for a fictional library we cooked up.  I&amp;#8217;m proud to say that every one of our students produced something that would be passable in an open source project.  Ideally speaking, I&amp;#8217;d like to say some of them took inspiration from what they learned in class, but no matter how they ended up there, I&amp;#8217;m happy to see people writing code that looks like it comes from Ruby. This is especially encouraging considering that every one of our students came to Ruby after Rails was popularized.&lt;/p&gt;
&lt;h3&gt;The Event&lt;/h3&gt;
&lt;p&gt;We wanted &amp;#8220;The Compleat Rubyist&amp;#8221; to be not just a training, but an &amp;#8220;event&amp;#8221; as well.  Because we were trying to keep registration costs low, we didn&amp;#8217;t have much officially scheduled for this, but Tampa.rb really helped us pull through.  Folks congregated at the nearby bar and restaurant Bahama Breeze from the time class ended until late into the evening Friday night.   It was nice to have a mixture of students from the training and locals who just stopped by to hang out and say hi.  I can honestly say that the sort of conversations I was having that night were on par with any I&amp;#8217;ve had at the various conferences I&amp;#8217;ve been at, but without all the associated commotion.&lt;/p&gt;
&lt;p&gt;Pizza lunch on Saturday was a great way for us to leave a large chunk of semi-unscheduled time to discuss whatever topics students had on their mind.  With a relatively small class size, I was able to get to know a number of the attendees, unlike my experience at most conferences these days.&lt;/p&gt;
&lt;p&gt;While I expected to have a good time, I ended up having a blast.  Based on my discussions with Jeremy and David, and the feedback from our students, I gather most others did as well.&lt;/p&gt;
&lt;h3&gt;The Future&lt;/h3&gt;
&lt;p&gt;While the Tampa, FL Compleat Rubyist event is now a thing of the past, we&amp;#8217;re already thinking about how we can bring this session to other places.  I was a little worried before the event that I wouldn&amp;#8217;t want to just go somewhere else and do the same show, but now I know that every one of these is going to be different, since so much of the content was based on interaction with our attendees.&lt;/p&gt;
&lt;p&gt;So, if the stuff I&amp;#8217;ve said here interests you, you should follow &lt;a href=http://twitter.com/compleatrubyist&gt;compleatrubyist on twitter&lt;/a&gt;.  We used our account actively during the event to share various little tips, and probably will continue to do that over time.  But that&amp;#8217;s also the place where you&amp;#8217;ll see announcements about upcoming events, or ask us any questions you might have.&lt;/p&gt;
&lt;p&gt;While I don&amp;#8217;t typically like to use this blog for active marketing, I can honestly say that &amp;#8220;The Compleat Rubyist&amp;#8221; was a lot of fun, and that I think our students learned a ton.  If folks like these summaries, I&amp;#8217;ll try to get one out after each event.  But it will be more fun, of course, if you come join us!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Mon, 25 Jan 2010 15:36:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html</guid></item><item><title>Learning From Bad Ideas</title><description>&lt;p&gt;When we know something is ugly or &amp;#8220;evil&amp;#8221;, we&amp;#8217;re quick to replace it with what we know to be a better solution.  But if we don&amp;#8217;t know &lt;strong&gt;why&lt;/strong&gt; the solution is better, it makes it hard for us to investigate those things that look reasonable on the surface, yet have weaknesses just beneath the skin.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll run through a quick example of what I mean, and then, it&amp;#8217;ll be your turn to run with it and report back here.  While I don&amp;#8217;t use this approach all the time, I find it&amp;#8217;s a neat tool to have handy when you&amp;#8217;re trying to push your understanding of your code just a little bit farther.&lt;/p&gt;
&lt;h3&gt;Continuations are Evil?&lt;/h3&gt;
&lt;p&gt;It&amp;#8217;s pretty common knowledge that continuations in Ruby are evil.  But let&amp;#8217;s pretend we didn&amp;#8217;t know that.  We might end up catching ourselves writing code like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  table.each do |row|
    call_cc do |next_row|
      row.each do |field|
        if field.valid?
          do_something_with(field)
        else
          STDERR.puts "skipping a bad row"
          next_row[]
        end 
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;The continuation approach actually doesn&amp;#8217;t look so bad.  All we&amp;#8217;re doing is iterating over a two-dimensional structure and skipping ahead to the next row if there is a problem with any of the fields. But having to pass along the &lt;tt&gt;next_row&lt;/tt&gt; callback seems a bit heavy handed, and also makes one wonder what sort of magic it might be concealing.  Preserving the same basic flow, we could be using &lt;tt&gt;catch&lt;/tt&gt; / &lt;tt&gt;throw&lt;/tt&gt; instead, lowering the conceptual baggage:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  table.each do |row|
    catch(:next_row) do
      row.each do |field|
        if field.valid?
          do_something_with(field)
        else
          STDERR.puts "skipping a bad row"
          throw :next_row
        end 
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;So, now, we have something that looks more-or-less like a transactional block, which gets aborted when you throw &lt;tt&gt;:next_row&lt;/tt&gt;.  Not too bad, but if you&amp;#8217;re like me, you probably get annoyed about having your eyes bounce up and down while you trace the flow, in both of these examples.  We can fix that, of course:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def process(row)
    row.each do |field|
      if field.valid?
        do_something_with(field)
      else
        STDERR.puts "skipping a bad row"
        return
      end
    end
  end
  
  table.each { |row| process(row) }
&lt;/pre&gt;
&lt;p&gt;Now this is more like it!  This code is probably the same as what a beginner might write, but it&amp;#8217;s also the clearest out of what we&amp;#8217;ve seen here.  But without it as a point of reference, neither the &lt;tt&gt;catch&lt;/tt&gt; / &lt;tt&gt;throw&lt;/tt&gt; or &lt;tt&gt;callcc&lt;/tt&gt; solutions would look terrible.&lt;/p&gt;
&lt;p&gt;Through this quick little set of examples, I found a good reason &lt;strong&gt;not&lt;/strong&gt; to use continuations for this particular use case.  Arriving back at a simple solution by starting with a &amp;#8220;clever&amp;#8221; one and reducing it down to the fundamentals was a refreshing experience for me.&lt;/p&gt;
&lt;h3&gt;Your Homework&lt;/h3&gt;
&lt;p&gt;Now it&amp;#8217;s your turn.  I&amp;#8217;m encouraging you to ignore &amp;#8220;Best Practices&amp;#8221; and the common idioms that we often accept as gospel.&lt;/p&gt;
&lt;p&gt;Pick one technique that&amp;#8217;s typically considered a no-no and do the best you can to use it in a somewhat reasonable way.  You don&amp;#8217;t want to waste your time with something that not even the most muddy-eyed coder would touch with a ten-foot pole, as you won&amp;#8217;t learn much that way.  Instead, work with something that looks fine or even clever at a first glance.&lt;/p&gt;
&lt;p&gt;Then, try to fix up what you built by using more idiomatic, simpler code.  Your goal is to create something that still looks good, but isn&amp;#8217;t as much as a liability (conceptually) as what you started with.  If you fail to do so, the worst thing that could happen is that you may have come across a new idiom worth sharing with others.  But more likely, with a little effort you&amp;#8217;ll have no trouble uncovering the wisdom behind whatever idiom you were putting to the test.&lt;/p&gt;
&lt;p&gt;What&amp;#8217;s the difference?  Now, something that used to be a somewhat arbitrary rule to you is now common sense.  As contexts shift, you may need to conduct new experiments, but repeat this exercise often enough and you&amp;#8217;ll start to see a powerful intuition develop that allows you to internalize your design decisions rather than running through a punch list of patterns.  And at least for me, I find that experience a lot more fun.  I hope you will, too.&lt;/p&gt;
&lt;p&gt;If you try out this exercise, please share what you&amp;#8217;ve done, either via a link to your own blog, or a &lt;a href="http://gist.github.com"&gt;gist&lt;/a&gt;.  I&amp;#8217;m interested in how many bad ideas we can rack up here. :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sun, 22 Nov 2009 22:57:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/013-good-to-be-bad.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/013-good-to-be-bad.html</guid></item><item><title>Be Nice and Have Fun</title><description>&lt;p&gt;Yet again, we&amp;#8217;re experiencing &lt;a href="http://news.ycombinator.com/item?id=773106"&gt;a firestorm&lt;/a&gt; that will shake things up and change the Ruby community in a big way.  But like anything else, the best thing we can do is remember that the sky is not falling, and that all internet drama is ephemeral at best.&lt;/p&gt;
&lt;p&gt;Sure, we&amp;#8217;ll all dearly miss a valued community member who inspired many of us.  But thanks to distributed revision control systems, we&amp;#8217;ll be able to commemorate _why through his works, currently being &lt;a href="http://github.com/whymirror"&gt;mirrored on github&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;So what do we do in this post _why world?  The answer to that is fairly simple: the same thing we&amp;#8217;ve been doing.  The true spirit of the Ruby community (and even the free software hacker community at large) is to work on fun stuff, and try to be nice to people.  If we can keep that up, the sky will not fall, and may even make room for new stars to light up the present darkness.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll let this brief statement stand on its own here, as &lt;span class="caps"&gt;RBP&lt;/span&gt; has no intentions of becoming a gossip blog, but feel free to leave your thoughts in the comments.&lt;/p&gt;
&lt;p&gt;Expect a new Ruby 1.9 series post some time before or just after &lt;span class="caps"&gt;LSRC&lt;/span&gt;.  Until then, keep your heads up folks.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;: I have Aaron Patterson to thank for expressing what I was thinking in words &amp;#8216;do fun stuff and try to be nice&amp;#8217;&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 21 Aug 2009 11:25:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/012-be-nice-and-have-fun.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/012-be-nice-and-have-fun.html</guid></item><item><title>Should I Tap that Hash?  (Ruby 1.9 Style)</title><description>&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: Be sure to read the comments.  I&amp;#8217;ve already learned a lot from them, and you might, too.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Though the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book covers Ruby 1.9, it is decidedly not a &amp;#8220;Ruby 1.9 Best Practices&amp;#8221; book.   The reason for this, of course, is that common idioms for Ruby 1.9 haven&amp;#8217;t evolved yet.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s work together to change that.   Every week until Ruby 1.9.2 comes out, I&amp;#8217;ll be coming up with short, manageable bits of Ruby 1.9 code for discussion, as part of a &amp;#8220;Ruby 1.9 Style&amp;#8221; series.  These should not be taken to be authoritative in any way, but instead work as conversation starters so that we can move forward as a community and separate the good from the bad when hacking code on Ruby 1.9.&lt;/p&gt;
&lt;p&gt;Rather than describing in detail how this series will work, I&amp;#8217;ll just begin with some real content and you can get a sense of the format from that.  The only key thing is to remember to not be lazy, and to actually comment on these posts.  Ruby 1.9 is basically the wild west right now, and its going to take quite a few sound voices to tame it.  So be sure to share your thoughts after you take a look at the proposed idiom below.&lt;/p&gt;
&lt;h3&gt;Object#tap, a seemingly benign addition.&lt;/h3&gt;
&lt;p&gt;Ruby 1.9 gives us &lt;tt&gt;tap&lt;/tt&gt;.  And &lt;tt&gt;tap&lt;/tt&gt; is sort of neat because it can be useful as a debugging tool, especially in &lt;a href="http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions.html"&gt;chained code&lt;/a&gt;.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt;  [1,2,3].map { |x| x + 1 }.tap { |y| p y }.inject(:+)
  [2, 3, 4]
  =&amp;gt; 9
&lt;/pre&gt;
&lt;p&gt;There isn&amp;#8217;t much conceptual weight here, either.  Essentially, you&amp;#8217;re looking at something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def tap
    yield(self)
    self
  end
&lt;/pre&gt;
&lt;p&gt;But hmm, doesn&amp;#8217;t that look familiar?&lt;/p&gt;
&lt;h3&gt;Object#tap as an alternative to ActiveSupport&amp;#8217;s returning&lt;/h3&gt;
&lt;p&gt;Those who work with Rails or with ActiveSupport in some other capacity will have seen &lt;tt&gt;returning&lt;/tt&gt;.  The problem it is meant to solve is seen in the code below.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def ugly
    results = {}

    [:x, :y, :z].each do |letter|
      results[letter] = rand(100)
    end

    results
  end
&lt;/pre&gt;
&lt;p&gt;Using &lt;tt&gt;returning&lt;/tt&gt;, this can be cleaned up a bit:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def sexy
  returning({}) do |results|
    [:x, :y, :z].each do |letter|
      results[letter] = rand(100)
    end
  end
end
&lt;/pre&gt;
&lt;p&gt;This code &lt;strike&gt;is definitely more &lt;span class="caps"&gt;DRY&lt;/span&gt;, and&lt;/strike&gt; looks pretty clean.  The only problem with it is that since it relies on ActiveSupport, you&amp;#8217;re essentially sifting through DHH&amp;#8217;s junk drawer for a piece of non-standard functionality for a fairly basic purpose.  While it may not be a &amp;#8220;Rails Best Practice&amp;#8221;, I tend to shy away from this sort of thing to keep from being too dependent on a framework that I only use part of the time.&lt;/p&gt;
&lt;p&gt;But if we think for a second, how would &lt;tt&gt;returning&lt;/tt&gt; be implemented?  Something like this, right?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def returning(obj)
    yield(obj)
    obj
  end
&lt;/pre&gt;
&lt;p&gt;Go check out the end of the previous section.  What we can see now is that &lt;tt&gt;returning&lt;/tt&gt; is just &lt;tt&gt;Object#tap&lt;/tt&gt; inside out!  So what happens when we use &lt;tt&gt;tap&lt;/tt&gt; that way?  Let&amp;#8217;s take a look.&lt;/p&gt;
&lt;h3&gt;Tapping that Hash.&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve started on a few Ruby 1.9 production apps, and that&amp;#8217;s where I first ran into attempting to use &lt;tt&gt;tap&lt;/tt&gt; as if it were &lt;tt&gt;returning&lt;/tt&gt;.  Take a look at this bit of code:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def times_for_period(date)
    days = work_days_for_period(date)
    regular_hours_by_week = Hash.new(0)

    { :regular_hours =&amp;gt; 0, :other_hours =&amp;gt; Hash.new(0) }.tap do |results|
      days.each do |d|
        times = d.times

        results[:regular_hours] += times[:regular_hours]
        regular_hours_by_week[d.date.cweek] += times[:regular_hours]

        times[:other_hours].each { |k,v| results[:other_hours][k] += v }
      end

      results[:weekly_hours] = regular_hours_by_week.keys.sort.map do |k| 
        regular_hours_by_week[k]
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;What I&amp;#8217;m doing here is calling &lt;tt&gt;tap&lt;/tt&gt; on a default hash and then populating it via the code within the block.  If I was simply iterating over some values, I might use &lt;tt&gt;inject&lt;/tt&gt; or &lt;tt&gt;each_with_object&lt;/tt&gt;, but my needs were a little more complicated here.&lt;/p&gt;
&lt;p&gt;This approach adds a little complexity, but in my experience, having to explicitly return a collection at the end of a method can be cumbersome, and I frequently forget about it during refactoring and cause my tests to go red on me.&lt;/p&gt;
&lt;p&gt;What do you think? Is &lt;tt&gt;Object#tap&lt;/tt&gt; the new &lt;tt&gt;returning&lt;/tt&gt;?  Or should we put this knife carefully back into DHH&amp;#8217;s junk drawer for safekeeping? I&amp;#8217;m pretty sure Rails didn&amp;#8217;t invent this functionality, but that&amp;#8217;s where a lot of us might have encountered it first.&lt;/p&gt;
&lt;p&gt;Help me decide whether this is elegant or nasty in the comments below.&lt;/p&gt;
&lt;h3&gt;A Gentle Reminder&lt;/h3&gt;
&lt;p&gt;I have to warn you, some of my ideas might be bad.  I&amp;#8217;ll be posting code that I find interesting or stuff that I don&amp;#8217;t know exactly how I feel about.  If we hit a dud from time to time, it&amp;#8217;s only to be expected.  But if you want to help me out, consider contributing content to this series.  If you have an idea for a guest post, go ahead and email me with the details, and I&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;Looking forward to your thoughts on this one and many more in the coming weeks!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 05 Aug 2009 12:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html</guid></item><item><title>25th Post!</title><description>&lt;p&gt;This is the 25th post to &lt;span class="caps"&gt;RBP&lt;/span&gt; blog!  Hooray!&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve been really happy with how things have gone so far.  Conversations have been for the most part civil and lively, we haven&amp;#8217;t run out of content, and the blog has seen new content nearly every week.&lt;/p&gt;
&lt;p&gt;I know that we aren&amp;#8217;t seeing as many voices on a week to week basis as we hoped for, but let&amp;#8217;s face it, people are bound to get busy.  That having been said, it&amp;#8217;d be great to know what readers are thinking about our content so far.&lt;/p&gt;
&lt;p&gt;So, what do you think?  Ranging from technical issues to ones of personal taste, it&amp;#8217;d be nice to know what keeps &lt;span class="caps"&gt;RBP&lt;/span&gt; in your feed reader, and what we can do to keep it there.  All feedback is welcome, so go ahead and let us know what&amp;#8217;s on your mind.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve got a great idea for a post, a series, or just some minor nitpick you want to voice, go for it.  So far we&amp;#8217;ve gained a lot from user responses, so I&amp;#8217;d like to keep with that tradition and keep the feedback loop tight.&lt;/p&gt;
&lt;p&gt;Now that you&amp;#8217;ve seen 25 posts, how should the next 25 look?&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Jul 2009 05:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/010-twenty-five.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/010-twenty-five.html</guid></item><item><title>Code Blocks: Ruby's Swiss Army Knife</title><description>&lt;p&gt;&lt;b&gt;The following blog post is a direct excerpt from the &lt;a href="http://oreilly.com/catalog/9780596523008/"&gt;Ruby Best Practices&lt;/a&gt; book.  If you&amp;#8217;ve been enjoying this blog, you&amp;#8217;d probably love the book, so I&amp;#8217;ve decided to release some content here to give you a sense of what to expect.  Enjoy!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: For those coming from other languages, Ruby&amp;#8217;s &lt;a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29#Blocks_and_iterators"&gt;code blocks&lt;/a&gt; are inherently &lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29"&gt;closures&lt;/a&gt; , and provide syntactic sugar for methods that accept &lt;tt&gt;Proc&lt;/tt&gt; objects (Ruby&amp;#8217;s anonymous functions).  While not strictly necessary for understanding this article, a solid grasp on what closures are and how they work will take you far.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;In Ruby, code blocks are everywhere. If you&#8217;ve ever used &lt;tt&gt;Enumerable&lt;/tt&gt;, you&#8217;ve worked with blocks. But what are they? Are they simply iterators, working to abstract away our need for the for loop? They certainly do a good job of that:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; ["Blocks","are","really","neat"].map { |e| e.upcase } 
  =&amp;gt; ["BLOCKS", "ARE", "REALLY", "NEAT"]
&lt;/pre&gt;
&lt;p&gt;But other blocks don&#8217;t really iterate over collections&#8212;they just do helpful things for us. For example, they allow us to write something like:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  File.open("foo.txt","w") { |f| f &amp;lt;&amp;lt; "This is sexy" } 
&lt;/pre&gt;
&lt;p&gt;instead of forcing us to write this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  file = File.open("foo.txt","w") 
  file &amp;lt;&amp;lt; "This is tedious" 
  file.close 
&lt;/pre&gt;
&lt;p&gt;So blocks are useful for iteration, and also useful for injecting some code between pre-processing and post-processing operations in methods. But is that all they&#8217;re good for? Sticking with Ruby built-ins, we find that isn&#8217;t the case. Blocks can also shift our scope temporarily, giving us easier access to places we want to be:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
 "This is a string".instance_eval do 
    "O hai, can has reverse? #{reverse}. kthxbye" 
  end 
  #=&amp;gt; "O hai, can has reverse? gnirts a si sihT. kthxbye" 
&lt;/pre&gt;

&lt;p&gt;But blocks aren&#8217;t necessarily limited to code that gets run right away and then disappears. They can also form templates for what to do down the line, springing to action when called for:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; foo = Hash.new { |h,k| h[k] = [] } 
  =&amp;gt; {} 
  &amp;gt;&amp;gt; foo[:bar] 
  =&amp;gt; [] 
  &amp;gt;&amp;gt; foo[:bar] &amp;lt;&amp;lt; 1 &amp;lt;&amp;lt; 2 &amp;lt;&amp;lt; 3 
  =&amp;gt; [1, 2, 3] 
  &amp;gt;&amp;gt; foo[:baz] 
  =&amp;gt; [] 
&lt;/pre&gt;
&lt;p&gt;So even if we label all methods that accept a block as iterators, we know the story runs deeper than that. With this in mind, we can leverage some basic techniques to utilize any of the approaches shown here, as well as some more advanced tricks. By doing things in a way that is consistent with Ruby itself, we can make life easier for our users. Rather than piling on new concepts, we can allow them to reuse their previous knowledge. Let&#8217;s take a look at a few examples of how to do that now.&lt;/p&gt;
&lt;h3&gt;Working with Enumerable&lt;/h3&gt;
&lt;p&gt;The most common use of blocks in Ruby might be the most trivial. The following class implements a basic sorted list, and then mixes in the &lt;tt&gt;Enumerable&lt;/tt&gt; module. The block magic happens in &lt;tt&gt;each()&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class SortedList 
    include Enumerable 
  
    def initialize 
      @data = [] 
    end 
  
    def &amp;lt;&amp;lt;(element) 
      (@data &amp;lt;&amp;lt; element).sort! 
    end 
  
    def each 
      @data.each { |e| yield(e) } 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;Our &lt;tt&gt;each()&lt;/tt&gt; method simply walks over each element in our &lt;tt&gt;@data&lt;/tt&gt; array and passes it through the block provided to the method by calling yield. The resulting iterator works exactly the same as &lt;tt&gt;Array#each&lt;/tt&gt; and &lt;tt&gt;Hash#each&lt;/tt&gt; and all the Ruby built-ins, and indeed simply wraps &lt;tt&gt;Array#each&lt;/tt&gt; in this case:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; a = SortedList.new 
  =&amp;gt; #&amp;lt;SortedList:0x5f0e74 @data=[]&amp;gt; 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 4 
  =&amp;gt; [4] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 5 
  =&amp;gt; [4, 5] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 1 
  =&amp;gt; [1, 4, 5] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 7 
  =&amp;gt; [1, 4, 5, 7] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 3 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; x = 0 
  =&amp;gt; 0 
  &amp;gt;&amp;gt; a.each { |e| x += e } 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; x 
  =&amp;gt; 20
&lt;/pre&gt;
&lt;p&gt;This shouldn&#8217;t be surprising. What is really the interesting bit is that by including the module &lt;tt&gt;Enumerable&lt;/tt&gt;, we gain access to most of the other features we&#8217;re used to working with when processing Ruby&#8217;s built-in collections. Here are just a few examples:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; a.map { |e| "Element #{e}" } 
  =&amp;gt; ["Element 1", "Element 3", "Element 4", "Element 5", "Element 7"] 
  &amp;gt;&amp;gt; a.inject(0) { |s,e| s + e } 
  =&amp;gt; 20 
  &amp;gt;&amp;gt; a.to_a 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; a.select { |e| e &amp;gt; 3 } 
  =&amp;gt; [4, 5, 7] 
&lt;/pre&gt;
&lt;p&gt;In a lot of cases, the features provided by &lt;tt&gt;Enumerable&lt;/tt&gt; will be more than enough for traversing your data. However, it&#8217;s often useful to add additional features that build on top of the the &lt;tt&gt;Enumerable&lt;/tt&gt; methods. We can show this by adding a simple reporting method to &lt;tt&gt;SortedList&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class SortedList 
    def report(head) 
      header = "#{head}\n#{'-'*head.length}" 
      body = map{|e| yield(e)}.join("\n") + "\n" 
      footer = "This report was generated at #{Time.now}\n" 
      [header, body, footer].join("\n") 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;which, when run, produces output like this:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; puts a.report("So many fish") { |e| "#{e} fish" } 
  So many fish 
  ------------ 
  1 fish 
  3 fish 
  4 fish 
  5 fish 
  7 fish 
  This report was generated at 2008-07-22 22:47:20 -0400 
&lt;/pre&gt;
&lt;p&gt;Building custom iterators is really that simple. This provides a great deal of flexibility, given that the code block can execute arbitrary expressions and do manipulations of its own as it walks across the elements. But as mentioned before, blocks can be used for more than just iteration.&lt;/p&gt;
&lt;h3&gt;Using Blocks to Abstract Pre- and Postprocessing&lt;/h3&gt;
&lt;p&gt;We looked at the block form of File.open() as an example of how blocks can provide an elegant way to avoid repeating tedious setup and teardown steps. However, files are surely not the only resources that need to be properly managed. Network I/O via sockets is another place where this technique can come in handy.&lt;/p&gt;
&lt;p&gt;On the client side, we&#8217;d like to be able to create a method that allows us to send a message to a server, return its response, then cleanly close the connection. The first thing that comes to mind is something simple like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 

  class Client 

    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 

    def send_message(msg) 
      socket = TCPSocket.new(@ip,@port) 
      socket.puts(msg) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
  
  end
&lt;/pre&gt;
&lt;p&gt;This is reasonably straightforward, but what happens when we want to add another method that waits to receive a message back from the server?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 
  
  class Client 
    
    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 
    
    def send_message(msg) 
      socket = TCPSocket.new(@ip,@port) 
      socket.puts(msg) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
    
    def receive_message 
      socket = TCPSocket.new(@ip,@port) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;This is starting to look messy, as we have repeated most of the code between &lt;tt&gt;send_message&lt;/tt&gt; and &lt;tt&gt;receive_message&lt;/tt&gt;. Ordinarily, we&#8217;d break off the shared code into a private method that the two could share, but the trouble here is that the difference between these two methods is in the middle, not in a single extractable chunk. This is where blocks come to the rescue:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 

  class Client 
    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 
  
    def send_message(msg) 
      connection do |socket| 
        socket.puts(msg) 
        socket.gets 
      end 
    end 

    def receive_message 
      connection { |socket| socket.gets } 
    end
     
    private 
    
    def connection 
      socket = TCPSocket.new(@ip,@port) 
      yield(socket) 
    ensure 
      socket.close 
    end 
  
  end
&lt;/pre&gt;
&lt;p&gt;As you can see, the resulting code is a lot cleaner. As long as we use our &lt;tt&gt;connection()&lt;/tt&gt; method with a block, we won&#8217;t need to worry about opening and closing the &lt;tt&gt;TCPSocket&lt;/tt&gt;; it&#8217;ll handle that for us. This means we&#8217;ve captured that logic in one place, and can reuse it however we&#8217;d like.&lt;/p&gt;
&lt;p&gt;To make things a bit more interesting, let&#8217;s take a look at a simple server with which this code can interact, which gives us a chance to look at yet another way that blocks can be useful in interface design.&lt;/p&gt;
&lt;h3&gt;Blocks as Dynamic Callbacks&lt;/h3&gt;
&lt;p&gt;There is a lot of power in being able to pass around code blocks just like they were any other object. This allows for the capability of creating and storing dynamic callbacks, which can later be looked up and executed as needed.&lt;/p&gt;
&lt;p&gt;In order to play with our &lt;tt&gt;Client&lt;/tt&gt; code from the previous example, we&#8217;re going to create a trivial &lt;tt&gt;TCPServer&lt;/tt&gt; that attempts to match incoming messages against patterns to determine how it should respond. Rather than hardcoding behaviors into the server itself or relying on inheritance to handle responses, we will instead allow responses to be defined through ordinary method calls accompanied by a block. Our goal is to get an interface that looks like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 

  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 

  server.run
&lt;/pre&gt;
&lt;p&gt;The first two examples are fairly simple, matching a single word and then responding with a generic message and timestamp. The third example is a bit more interesting, repeating the client&#8217;s name back in the response message. This will be accomplished by querying a simple &lt;tt&gt;MatchData&lt;/tt&gt; object, which is yielded to the block.&lt;/p&gt;
&lt;p&gt;Though making this work might seem like black magic to the uninitiated, a look at its implementation reveals that it is actually a fairly pedestrian task:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Server 
    
    def initialize(port=3333) 
      @server   = TCPServer.new('127.0.0.1',port) 
      @handlers = {} 
    end 
    
    def handle(pattern, &amp;amp;block) 
      @handlers[pattern] = block 
    end 
    
    def run 
      while session = @server.accept 
        msg = session.gets 
        match = nil 
        @handlers.each do |pattern,block| 
          if match = msg.match(pattern) 
            break session.puts(block.call(match)) 
          end 
        end 
        unless match 
          session.puts "Server received unknown message: #{msg}" 
        end 
      end 
    end
     
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;handle()&lt;/tt&gt; method slurps up the provided block using the &lt;tt&gt;&amp;amp;block&lt;/tt&gt; syntax, and stores it in a hash keyed by the given pattern. When &lt;tt&gt;Server#run&lt;/tt&gt; is called, an endless loop is started that waits for and handles client connections. Each time a message is received, the hash of handlers is iterated over. If a pattern is found that matches the message, the associated block is called, providing the match data object so that the callback can respond accordingly.&lt;/p&gt;
&lt;p&gt;If you&#8217;d like to try this out, use the following code to spin up a server:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 
  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  server.run
&lt;/pre&gt;
&lt;p&gt;Once you have that running and listening for connections, execute the following client code:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  client = Client.new 
  
  ["Hello", "My name is Greg", "Goodbye"].each do |msg| 
    response = client.send_message(msg) 
    puts response 
  end 
&lt;/pre&gt;
&lt;p&gt;You will get back something like this:&lt;/p&gt;
&lt;pre&gt;
  Hello from server at Wed Jul 23 16:15:37 -0400 2008 
  Nice to meet you Greg! 
  Goodbye from server at Wed Jul 23 16:15:37 -0400 2008 
&lt;/pre&gt;
&lt;p&gt;It would be easy to extend both the client and server to do more interesting things that build on this very simple foundation. Feel free to take a few minutes to play around with that, and then we&#8217;ll look at one more block trick that&#8217;s fairly common in Ruby.&lt;/p&gt;
&lt;h3&gt;Blocks for Interface Simplification&lt;/h3&gt;
&lt;p&gt;Does it feel like the word &#8220;server&#8221; is written too many times in this code?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 
  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  server.run 
&lt;/pre&gt;
&lt;p&gt;When you see code like this, it might be a sign that you could do better. Although there are merits to this somewhat standard approach, we can cheat a little bit with blocks (of course) and make things prettier. It would be nice to be able to write this instead:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  Server.run do 
    handle(/hello/i) { "Hello from server at #{Time.now}" } 
    handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
    handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  end 
&lt;/pre&gt;
&lt;p&gt;As you may recall from an earlier example, it is possible to execute a block within the scope of an instantiated object in Ruby. Using this knowledge, we can implement this handy shortcut interface as a simple class method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Server 
    # other methods same as before 
    def self.run(port=3333,&amp;amp;block) 
      server = Server.new(port) 
      server.instance_eval(&amp;amp;block) 
      server.run 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;This is all you need to get the new interface running, and rounds off our quick exploration of the different ways that you can use blocks to improve your &lt;span class="caps"&gt;API&lt;/span&gt; design while simplifying your method implementations.  Let&amp;#8217;s recap with a few tips before we wrap up here.&lt;/p&gt;
&lt;h3&gt;Things to Remember&lt;/h3&gt;
&lt;p&gt;Keep the following things in mind when using blocks as part of your interface:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If you create a collection class that you need to traverse, build on top of Enumerable rather than reinventing the wheel.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;If you have shared code that differs only in the middle, create a helper method that yields a block in between the pre/postprocessing code to avoid duplication of effort.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;If you use the &amp;amp;block syntax, you can capture the code block provided to a method inside a variable. You can then store this and use it later, which is very useful for creating dynamic callbacks.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Using a combination of &amp;amp;block and instance_eval, you can execute blocks within the context of arbitrary objects, which opens up a lot of doors for highly customized interfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;The return value of yield (and block.call) is the same as the return value of the provided block.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Did you enjoy this post?&lt;/h3&gt;
&lt;p&gt;If you had fun reading this, definitely consider picking up a copy of &lt;a href="http://oreilly.com/catalog/9780596523008/"&gt;Ruby Best Practices&lt;/a&gt; .  If you need more convincing, there is a whole &lt;a href="http://cdn.oreilly.com/books/9780596523008/Mastering_the_Dynamic_Toolkit.xml.pdf"&gt;sample chapter&lt;/a&gt; for you to check out in addition to this excerpt.  If you&amp;#8217;ve already picked up the book and are enjoying it, tell your friends, and consider leaving a review on the &lt;a href="http://www.amazon.com/gp/product/0596523009"&gt;Amazon product page&lt;/a&gt; .  If you don&amp;#8217;t have enough time for that, go help me win the &lt;a href="http://rubytrends.com/styles/book/trends/134"&gt;popularity contest&lt;/a&gt; over at RubyTrends, as there are several books that I admire that still need to be overcome :)&lt;/p&gt;
&lt;p&gt;As always, I welcome your thoughts and feedback.  Let me know what you think of the techniques shown here, or share your own personal favorite code block trick.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Jul 2009 04:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html</guid></item><item><title>The Decorator Delegator Disco</title><description>&lt;p&gt;As promised, we&amp;#8217;re back with more design discussion and hopefully some interesting ideas.  Let&amp;#8217;s start with a quick recap of what has happened so far.&lt;/p&gt;
&lt;p&gt;First, &lt;a href="http://sandimetz.com/"&gt;Sandi Metz&lt;/a&gt; posted on her blog about &lt;a href="http://sandimetz.com/2009/06/ruby-case-statements-and-kindof.html"&gt;type specific coupling&lt;/a&gt; that a &lt;tt&gt;case&lt;/tt&gt; statement can introduce.  Her proposed solution encouraged us to pass the responsibilities down to the individual objects, which is certainly desirable.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rubybestpractices.com/about/aaronp.html"&gt;Aaron Patterson&lt;/a&gt; got in the mix, pointing out the issues that can happen when you are too aggressive about adding methods to core Ruby.  When Sandi suggested that &lt;a href="http://en.wikipedia.org/wiki/Double_dispatch"&gt;Double Dispatch&lt;/a&gt; might be a way around this problem, Aaron responded with an &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html"&gt;implementation using the visitor pattern&lt;/a&gt; to accomplish this sort of thing.&lt;/p&gt;
&lt;p&gt;I had not seen Aaron&amp;#8217;s initial work before setting out to solve the problem on my own, and ended up taking an entirely different path to get there.  I&amp;#8217;m not much of a patterns guy, but after I had a working implementation, it seems like the approach I took mostly represents a combination of &lt;a href="http://en.wikipedia.org/wiki/Delegation_pattern"&gt;Delegation&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;Decoration&lt;/a&gt; techniques.&lt;/p&gt;
&lt;h3&gt;A quick demo&lt;/h3&gt;
&lt;p&gt;I think this code will be easier to understand if I show how it is used right up front.  So here&amp;#8217;s a tiny slice to get started with:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module ActionView
    module Helpers 
       class Extensions
          extend Decoration
        
          decorator_for(Array) do
            def as_array
              self
            end
          end
        
          decorator_for(Object) do
            def as_array
              [self]
            end
          end
       end
     
       # totally incomplete, just returns decorated object
       def form_for(record_or_name_or_array, *args, &amp;amp;block)
         Extensions.decorate(record_or_name_or_array)
       end
    end
  end

  include ActionView::Helpers

  p form_for(:foo).as_array #=&amp;gt; [:foo]
  p form_for(Object.new).as_array #=&amp;gt; [#&amp;lt;Object:0x3f47ec&amp;gt;]
  p form_for([1,2,3]).as_array #=&amp;gt; [1,2,3]
&lt;/pre&gt;
&lt;p&gt;In the code above, I&amp;#8217;ve implemented Sandi&amp;#8217;s &lt;tt&gt;as_array&lt;/tt&gt; helper.  I left the actual &lt;tt&gt;form_for&lt;/tt&gt; implementation very incomplete, causing it just to return the decorated object.  This is for example purposes only, so you could see that we can indeed call &lt;tt&gt;as_array&lt;/tt&gt; successfully.&lt;/p&gt;
&lt;p&gt;Before we check out how this all works, here are two extra hints about what this approach is affording us.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  my_obj = [1,2,3]
  decorated = form_for(my_obj)
  
  p decorated.as_array #=&amp;gt; [1,2,3]
  
  # Raises NoMethodError
  [1,2,3].as_array
  
  # Also raises NoMethodError
  p my_obj.as_array 
&lt;/pre&gt;
&lt;p&gt;As you can see, if core extensions are like a meat cleaver, this approach is more like using a scalpel, no changes bleed out into unexpected places.  Now that we see how it is used, let&amp;#8217;s take a look under the hood of &lt;tt&gt;Decorate&lt;/tt&gt; to see how it is built.&lt;/p&gt;
&lt;h3&gt;The &lt;tt&gt;Decorate&lt;/tt&gt; module&lt;/h3&gt;
&lt;p&gt;Though fairly densely packed, the whole implementation of &lt;tt&gt;Decorate&lt;/tt&gt; is pretty tiny.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'delegate'

# with minor tweaks from tjstankus
module Decoration
  def decorator_for(*types, &amp;amp;block)
    types.each do |type|
      decorators[type] = Module.new(&amp;amp;block)
    end
  end
 
  def decorators
    @decorators ||= {}
  end
 
  def decorate(target)
    obj = SimpleDelegator.new(target)
    
    # walk in reverse order so most specific patches get applied LAST
    target.class.ancestors.reverse.each do |a|
      if decorators[a]
        obj.extend(decorators[a])
      end
    end
    
    return obj
  end
end
&lt;/pre&gt;
&lt;p&gt;Here, we are taking advantage of &lt;tt&gt;SimpleDelegator&lt;/tt&gt;, a class provided from Ruby&amp;#8217;s &lt;i&gt;delegate&lt;/i&gt; standard library.  Here&amp;#8217;s a quick glimpse of how it works:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; require "delegate"
=&amp;gt; true

&amp;gt;&amp;gt; a = [1,2,3]
=&amp;gt; [1, 2, 3]

&amp;gt;&amp;gt; b = SimpleDelegator.new(a)
=&amp;gt; [1, 2, 3]
&amp;gt;&amp;gt; b &amp;lt;&amp;lt; 4
=&amp;gt; [1, 2, 3, 4]
&amp;gt;&amp;gt; b.delete_at(1)
=&amp;gt; 2

&amp;gt;&amp;gt; b
=&amp;gt; [1, 3, 4]
&amp;gt;&amp;gt; a
=&amp;gt; [1, 3, 4]

&amp;gt;&amp;gt; b.class
=&amp;gt; SimpleDelegator
&amp;gt;&amp;gt; a.class
=&amp;gt; Array
&lt;/pre&gt;
&lt;p&gt;Essentially, &lt;tt&gt;SimpleDelegator&lt;/tt&gt; provides an easy way to wrap an object within a proxy.  This gives us a convenient place to hang per-object behavior without mutating the original object.&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; def b.kitties
  &amp;gt;&amp;gt;   "MEEEOW"
  &amp;gt;&amp;gt; end
  &amp;gt;&amp;gt; b.kitties
  =&amp;gt; "MEEEOW"
  &amp;gt;&amp;gt; a.kitties
  NoMethodError: undefined method `kitties' for [1, 3, 4]:Array
  	from (irb):15
&lt;/pre&gt;
&lt;p&gt;You probably see where this is going now, so let&amp;#8217;s get back to &lt;tt&gt;Decorate&lt;/tt&gt; module.  If we look at &lt;tt&gt;decorator_for&lt;/tt&gt;, we can get a good sense of how all this magic comes together:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def decorator_for(*types, &amp;amp;block)
  types.each do |type|
    decorators[type] = Module.new(&amp;amp;block)
  end
end

def decorators
  @decorators ||= {}
end
&lt;/pre&gt;
&lt;p&gt;Here, we see that &lt;tt&gt;decorator_for&lt;/tt&gt; basically takes a type or list of types, and a block.  The block is then used to define the body of an anonymous module that gets stashed away in a hash for later use.  So going back to our example code, we see that the following definitions are actually module definitions.  They could have even been written this way:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Extensions
   extend Decoration
 
   module ArrayDecorator
     def as_array
       self
     end
   end
 
  module ObjectDecorator
     def as_array
       [self]
     end
  end
  
  decorators[Array]  = ArrayDecorator
  decorators[Object] = ObjectDecorator
end
&lt;/pre&gt;
&lt;p&gt;Of course, this lacks the necessary sugar shock, so I show it only to make the implementation clearer.  But now that we have a way to stack up modules with per-object behavior in them, and a place to hang that per-object behavior off of, we only need a mechanism to apply it. For this functionality, we turn to the &lt;tt&gt;decorate&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def decorate(target)
    obj = SimpleDelegator.new(target)
  
    # walk in reverse order so most specific patches get applied LAST
    target.class.ancestors.reverse.each do |a|
      if decorators[a]
        obj.extend(decorators[a])
      end
    end
  
    return obj
  end
&lt;/pre&gt;
&lt;p&gt;We want to be able to preserve the ability to use &lt;tt&gt;super&lt;/tt&gt; in our decorated method calls, and we definitely wanted to pick up extensions to objects higher in the inheritance chain without any duplication.  So this meant we needed to do something a little more complicated than key the target object&amp;#8217;s type directly to a decorator module.&lt;/p&gt;
&lt;p&gt;Rather than just picking the most recent ancestor, this code walks the chain in reverse order so that the modules can neatly stack on top of one another.  In short, this means that the decorator for &lt;tt&gt;Object&lt;/tt&gt; gets applied before the one for &lt;tt&gt;Array&lt;/tt&gt; so that you can emulate an inheritance relationship in your extensions.&lt;/p&gt;
&lt;p&gt;This pretty much sums up the whole implementation, so let&amp;#8217;s just take a look at one more example before evaluating the pros and cons of this approach.&lt;/p&gt;
&lt;h3&gt;An alternative to core extensions&lt;/h3&gt;
&lt;p&gt;Here is a bit of code that completely covers the &lt;a href="http://github.com/skmetz/rails/blob/cffbc4399288be2fb7e15f67680089dbb36a7152/actionpack/lib/action_view/helpers/form_helper_core_extensions.rb"&gt;core extensions&lt;/a&gt; that Sandi needed for her &lt;a href="http://github.com/skmetz/rails/commit/cffbc4399288be2fb7e15f67680089dbb36a7152"&gt;Rails patch&lt;/a&gt;, without the core extensions:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;   
  class Extensions

     extend Decoration
     
     decorator_for Symbol, String do
       def form_object_name
         self
       end

       def as_fields_for_form_object(args)
         args.first
       end

       def acts_like_model?
         false
       end
     end

     decorator_for Array do
       def as_form_object
         last
       end

       def as_array
         self
       end
     end

     decorator_for Object do
       def as_form_object
         self
       end

       def as_fields_for_form_object(args)
         as_form_object
       end

       def form_object_name
         ActionController::RecordIdentifier.singular_class_name(self)
       end

       def as_array
         [self]
       end

       def acts_like_model?
         true
       end
     end
     
  end
&lt;/pre&gt;
&lt;p&gt;You would use the same approach I suggested before to wire this up, something like &lt;tt&gt;Extensions.decorate(my_obj)&lt;/tt&gt;&lt;/p&gt;
&lt;h3&gt;Pros for this solution&lt;/h3&gt;
&lt;p&gt;There are definitely things about this technique that I like.  The obvious benefit is that it prevents core hackery, and even goes a step beyond something like &lt;tt&gt;my_object.extend(SomethingSpecial)&lt;/tt&gt;, since it only extends behavior into a throwaway proxy object.&lt;/p&gt;
&lt;p&gt;Another clear benefit is that defining extensions is about as easy as it is to do raw core extensions.  Because the blocks are used as module definitions, you can do pretty much anything you&amp;#8217;d ordinarily do when defining methods.  This lowers the amount of &amp;#8216;special stuff&amp;#8217; you need to remember.&lt;/p&gt;
&lt;p&gt;Perhaps the most interesting thing however, is that this approach can be used to apply customized behavior to several types of objects at once, and can also be used to apply behaviors based on what mixins are included in an object.  This means there is nothing stopping you from doing something like &lt;tt&gt;decorator_for(Enumerable)&lt;/tt&gt; or &lt;tt&gt;decorator_for(Comparable)&lt;/tt&gt;, which provides you a little extra flexibility beyond the traditional inheritance hierarchy.&lt;/p&gt;
&lt;p&gt;Another interesting aspect of this is that decorators can be implemented at a per-module (or per-class) level, which means that different libraries can have different extensions without interfering with each other.&lt;/p&gt;
&lt;p&gt;Keep in mind, it&amp;#8217;s not all roses.  Let&amp;#8217;s take a look at some of the pitfalls.&lt;/p&gt;
&lt;h3&gt;Cons for this solution&lt;/h3&gt;
&lt;p&gt;A major drawback here is that we&amp;#8217;re still relying on types.  Whether its a class or module, we still expect an object to be a certain thing, which sort of goes against traditional duck typing in which we&amp;#8217;d rather make assumptions based on what an object can do rather than what it is.  So it might be nicer to apply these decorators based on what the target object responds to, not what ancestors it has.&lt;/p&gt;
&lt;p&gt;There is also the performance overhead factor.  I have not benchmarked yet, but I suspect that the cost of both building up a &lt;tt&gt;SimpleDelegator&lt;/tt&gt; and doing proxy calls is non-negligible.  While this may not be an issue in many cases, for code that needs to run in tight loop or be scaled heavily, this approach may be too heavy for its benefits to outweigh its costs.  But of course, this is a huge &lt;span class="caps"&gt;YMMV&lt;/span&gt; situation, and without hard numbers it&amp;#8217;s tough to say to what extent this would be a huge issue.&lt;/p&gt;
&lt;p&gt;Perhaps the most fatal flaw with the current setup is that &lt;tt&gt;respond_to?&lt;/tt&gt; gets delegated to the target object, so with the current implementation, unless you define &lt;tt&gt;respond_to?&lt;/tt&gt; yourself, it will not pick up any of your new methods.  I imagine that this is something that can be fixed, I just have not looked into it yet.&lt;/p&gt;
&lt;p&gt;Finally, there is the legitimacy problem.  As Sandi said in the comments on Aaron&amp;#8217;s article, &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html#comment-11553586"&gt;sometimes a case statement is just a case statement&lt;/a&gt;.  If we go around filling all our code with high-architecture bazookas when all that was needed was a pen-knife, there are bound to be consequences.  Is this overkill or awesome?  I don&amp;#8217;t really know, and I imagine it depends on the situation.&lt;/p&gt;
&lt;h3&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;When Aaron and I compared our solutions to Sandi&amp;#8217;s problem, we basically concluded that both of our approaches might be useful for different things.  Aaron&amp;#8217;s shines when dealing with providing type-specific implementations of a particular behavior, which is mostly just the visitor pattern shining through.  My approach is probably better for situations in which you need to collect several behaviors in one place.&lt;/p&gt;
&lt;p&gt;Ultimately, this may be a matter of preference, depending on whether you want to abstract things based on the method level or the object level.  Of course, sometimes neither is necessary, and that may be an important fact to remember.&lt;/p&gt;
&lt;p&gt;I am very much interested in what readers have to say.  Please check out &lt;a href="http://sandimetz.com/2009/06/ruby-case-statements-and-kindof.html"&gt;Sandi&amp;#8217;s article&lt;/a&gt; , then &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html"&gt;Aaron&amp;#8217;s&lt;/a&gt; , then let me know here which approaches you might take along with their context.  If you have your own ideas that are totally different than ours, I want to know about that too.&lt;/p&gt;
&lt;p&gt;We need more conversations like these in our community, so let&amp;#8217;s start here and see where it takes us.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sat, 27 Jun 2009 16:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/008-decorator-delegator-disco.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/008-decorator-delegator-disco.html</guid></item><item><title>Quack Attack: Making Your Code More Rubyish</title><description>&lt;p&gt;I&amp;#8217;ve been doing some &lt;span class="caps"&gt;FFI&lt;/span&gt; work recently, which means that I&amp;#8217;ve needed to  wrap underlying C libraries so that I can call them from Ruby.  While I won&amp;#8217;t get into how the low level wrappers work, I can show you what the raw &lt;span class="caps"&gt;API&lt;/span&gt; calls look like for just a few functions:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  trip = API.PCMSNewTrip(server_id)
  API.PCMSNumStops(trip)
  API.PCMSAddStop(trip, string)
  API.PCMSGetStop(trip, index, string_ptr, buffer_size)
  API.PCMSDeleteStop(trip, index)
  API.PCMSClearStop(trip)
&lt;/pre&gt;
&lt;p&gt;All things considered, this looks pretty good for a direct wrapper on top of a C library.  In fact, it&amp;#8217;s relatively simple to mirror this to a more normalized Ruby layout.  We can start by noticing that these calls are basically object oriented, focusing on the &lt;tt&gt;Trip&lt;/tt&gt; object.  While a &lt;tt&gt;Trip&lt;/tt&gt; has other responsibilities, among them is managing a list of stops.  With this in mind, we can flesh out a basic &lt;tt&gt;Trip&lt;/tt&gt; object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Trip
  def initialize(server_id)
    @server_id = server_id
    @pointer = API.PCMSNewTrip(@server_id)
    @stops = StopList.new(self)
  end
  
  attr_reader :stops
  
  def call(*args)
    API.send("PCMS#{args.first}",  @pointer, *args[1..-1])
  end
end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;Trip#call&lt;/tt&gt; helper removes some of the duplication for us, but it&amp;#8217;ll be easier to see how it works in just a moment.  For now, it&amp;#8217;s worth pondering what a &lt;tt&gt;StopList&lt;/tt&gt; should be.&lt;/p&gt;
&lt;p&gt;If you look at the functions listed for dealing with stops, you&amp;#8217;ll notice they map nicely to one of Ruby&amp;#8217;s structures.  We&amp;#8217;re dealing with an ordered list of objects that can be added to and removed from.  It can also be queried for its length, and deleted entirely.  These features sure sound a lot like Ruby&amp;#8217;s &lt;tt&gt;Array&lt;/tt&gt; object, don&amp;#8217;t they?&lt;/p&gt;
&lt;p&gt;With this in mind, let&amp;#8217;s do a quick experiment in interface design:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class StopList

  include Enumerable

  def initialize(trip)
    @trip = trip
  end

  def length
    @trip.call :NumStops
  end

  def &amp;lt;&amp;lt;(loc)
    @trip.call :AddStop, loc
  end

  def [](index)
    ptr = FFI::MemoryPointer.new(:char, 100)
    @trip.call :GetStop, index, ptr, 101
    ptr.read_string
  end

  def delete_at(index)
    @trip.call :DeleteStop, index
  end

  def each
    length.times do |i|
      yield self[i]
    end
  end

  def clear
    @trip.call :ClearStops
  end

end
&lt;/pre&gt;
&lt;p&gt;Without paying too much attention to the implementation details, let&amp;#8217;s take a look at what behaviors this new object supports:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  t = Trip.new(server_id)
  
  t.stops &amp;lt;&amp;lt; "New Haven, CT"
  t.stops &amp;lt;&amp;lt; "Naugatuck, CT"
  t.stops &amp;lt;&amp;lt; "Boston, MA"
  
  p t.stops.length #=&amp;gt; 3
  
  p t.stops[2] #=&amp;gt; "02205 Boston, MA, Suffolk"
  
  t.stops.delete_at(1)
  p t.stops[1] #=&amp;gt; "02205 Boston, MA, Suffolk"
  
  p t.stops.map { |e| e.upcase } #=&amp;gt; [ "06511 NEW HAVEN, CT, NEW HAVEN",
                                 #     "02205 BOSTON, MA, SUFFOLK" ]
  
  t.stops.clear
  p t.stops.length #=&amp;gt; 0
&lt;/pre&gt;
&lt;p&gt;If this sort of interaction looks familiar to you, it&amp;#8217;s because you&amp;#8217;ve likely already done things like this thousands of times.  But to make it blindingly obvious, let&amp;#8217;s replace Trip#stops with an Array.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
stops = []

stops &amp;lt;&amp;lt; "New Haven, CT"
stops &amp;lt;&amp;lt; "Naugatuck, CT"
stops &amp;lt;&amp;lt; "Boston, MA"

p stops.length #=&amp;gt; 3

p stops[2] #=&amp;gt; "Boston, MA"

stops.delete_at(1)
p stops[1] #=&amp;gt; "Boston, MA"

p stops.map { |e| e.upcase } #=&amp;gt; ["NEW HAVEN, CT", "BOSTON, MA"]

stops.clear
p stops.length #=&amp;gt; 0
&lt;/pre&gt;
&lt;p&gt;You&amp;#8217;ll notice that aside from lacking the location name normalization that our real code does implicitly, the key points we&amp;#8217;ve highlighted have exactly the same behavior, using exactly the same interface.  One benefit is immediately obvious after seeing this; the &lt;span class="caps"&gt;API&lt;/span&gt; for &lt;tt&gt;StopList&lt;/tt&gt; doesn&amp;#8217;t require you to learn anything new.&lt;/p&gt;
&lt;p&gt;A more subtle gain that comes with this approach is that so long as it is restricted to the subset which &lt;tt&gt;StopList&lt;/tt&gt; supports, code which expects an &lt;tt&gt;Array&lt;/tt&gt;-like thing does not need to change, either.&lt;/p&gt;
&lt;p&gt;For example, the following code will work just fine with either an &lt;tt&gt;Array&lt;/tt&gt; or a &lt;tt&gt;StopList&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def humanized(list)
  list.each_with_index do |e,i|
    puts "#{e} (#{i+1} / #{list.length})"
  end
end
&lt;/pre&gt;
&lt;p&gt;This makes things easier to test, and easier to be re-used for different purposes.  Both are solid reasons for using this technique.&lt;/p&gt;
&lt;p&gt;Of course, I&amp;#8217;ve been glossing over a semi-major issue in the original code here, which I am sure has frustrated our more pedantic readers.  The current &lt;tt&gt;StopList&lt;/tt&gt; code, while quite useful, does not quack perfectly with Array.  We needn&amp;#8217;t look far for signs of divergence.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
p t.stops &amp;lt;&amp;lt; "Chicago, IL" #=&amp;gt; 1
p t.stops.delete_at(2)     #=&amp;gt; 1
p t.stops.clear            #=&amp;gt; nil
&lt;/pre&gt;
&lt;p&gt;These side-effect bearing functions are returning their C based values, which are different than what you&amp;#8217;d expect from a Ruby &lt;tt&gt;Array&lt;/tt&gt;.  Luckily, each of these are easy to remedy.&lt;/p&gt;
&lt;p&gt;In the case of the append operator (&amp;lt;&amp;lt;), we should return the  &lt;tt&gt;StopList&lt;/tt&gt; itself, to permit chaining:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def &amp;lt;&amp;lt;(loc)
  @trip.call :AddStop, loc
  return self
end
&lt;/pre&gt;
&lt;p&gt;To play nice with &lt;tt&gt;Array&lt;/tt&gt;, our &lt;tt&gt;delete_at&lt;/tt&gt; method should return the deleted object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def delete_at(index)
    obj = self[index]
    @trip.call :DeleteStop, index
    return obj
  end
&lt;/pre&gt;
&lt;p&gt;Finally, since &lt;tt&gt;clear&lt;/tt&gt; may also be chained, it should return the original object as well.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def clear
  @trip.call :ClearStops
  return self
end
&lt;/pre&gt;
&lt;p&gt;With these fixes in place, we can re-visit our previous example:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
p t.stops &amp;lt;&amp;lt; "Chicago, IL" #=&amp;gt; #&amp;lt;Trip::StopList:0x0fcac ...&amp;gt;
p t.stops.delete_at(2)     #=&amp;gt; "60607 Chicago, IL, Cook"
p t.stops.clear            #=&amp;gt; #&amp;lt;Trip::StopList:0x0fcac ...&amp;gt;
&lt;/pre&gt;
&lt;p&gt;There are probably some other minor details to catch, but now that our &lt;tt&gt;Array&lt;/tt&gt;-ish &lt;tt&gt;StopList&lt;/tt&gt; is &amp;#8220;Good Enough For Government Work&amp;#8221;, we have a nice stopping point.  Let&amp;#8217;s wrap things up with a little summary of things to remember.&lt;/p&gt;
&lt;h3&gt;Guidelines For Making Your Code More &amp;#8220;Rubyish&amp;#8221;&lt;/h3&gt;
&lt;p&gt;This is just one technique among many for improving your code, but I&amp;#8217;d argue its a fairly important one. If you have a structure that mimics a subset of a core Ruby object&amp;#8217;s capabilities, you can gain a lot by standardizing on a compatible interface.  While sometimes the similarities end at the &lt;tt&gt;Enumerable&lt;/tt&gt; and &lt;tt&gt;Comparable&lt;/tt&gt; mixins, it&amp;#8217;s reasonable to stretch things farther when it makes sense to do so.  If you go that route (as we did here), there are just a few things to keep in mind:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You don&amp;#8217;t need to implement every last feature of a core Ruby object in order to use this technique.  So many functions rely on just a handful of available methods, that it makes sense to use this technique even when your problem domain is very small.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;For the features you do implement, take care to maintain the same interface both on input and output.  It&amp;#8217;s fine to not support certain use cases, or to add extensions for new ones, but you should not diverge in the behaviors you do implement unless you have a good reason to.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Pay close attention to the return values of side-effect inducing functions, especially the ones mentioned in this article.  Many Ruby methods are designed to be chainable, and breaking that feature can create a mess.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;While this technique opens the door for using primitive objects for testing higher level functions, do not forget to adequately test the functionality of the actual objects you are implementing.  Basically, make sure your code really quacks like a duck before substituting it with a duck somewhere else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i&gt;To our readers:  Where have you seen good uses of this technique in action?  Have you tried it yourself and run into any problems?  Please give your answers to these questions, as well as any other discussion points in the comments.&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 09 Jun 2009 13:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/007-rubyish-code.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/007-rubyish-code.html</guid></item><item><title>RubySpec as a Community Resource (Interview w. Brian Ford)</title><description>&lt;p&gt;Though I still need to collect the details, I&amp;#8217;m about to start on another major open source project, called &lt;a href="http://github.com/madriska/unity"&gt;Unity&lt;/a&gt; .  It will be a &lt;a href="http://pledgie.com/campaigns/4640"&gt;community driven effort&lt;/a&gt; to provide a nice web resource that builds on top of the &lt;a href="http://rubyspec.org/"&gt;RubySpec&lt;/a&gt; project with reporting and search capabilities.&lt;/p&gt;
&lt;p&gt;But readers might wonder what RubySpec has to do with them, if they are not language implementers.  Here&amp;#8217;s what &lt;a href="http://blog.brightredglow.com/"&gt;Brian Ford&lt;/a&gt; had to say.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;i&gt;&lt;h4&gt;In an ideal world, what would the RubySpec project do for the Ruby community?&lt;/h4&gt;&lt;/p&gt;
&lt;p&gt;1. Provide a reasonably precise definition of the Ruby programming language so that there can be a certain degree of uniformity among the implementations. The goal is for the Ruby user to not have to think about which implementation her code runs on until she needs to, rather than writing code that works on one implementation and porting it if necessary. All software has a life cycle and the needs of the software are not always constant. A Ruby programmer should be able to develop using &lt;span class="caps"&gt;MRI&lt;/span&gt; on their laptop and deploy on Rubinius or JRuby without missing a beat, for example. Note that I use &amp;#8220;Ruby user&amp;#8221; and &amp;#8220;Ruby programmer&amp;#8221; with a distinction. A Ruby user might be anyone who relies on or provides software written in Ruby, not just someone who writes software in Ruby. So I envision a uniform definition of Ruby benefiting every strata of the Ruby community.&lt;/p&gt;
&lt;p&gt;2. Provide quality assurance and regression notification for &lt;span class="caps"&gt;MRI&lt;/span&gt; and all implementations. People put a huge amount of trust in an implementation when they decide to invest large amounts of money in developing a software product. We&amp;#8217;d like them to get some assurance for the trust they put in. Programmers are human and make mistakes. Automating the detection of mistakes is a no-brainer.&lt;/p&gt;
&lt;p&gt;3. Improving the quality of Ruby as a language by discovering dusty corners and inconsistencies. Recently, a number of inconsistencies in bang methods (e.g. String#lstrip!) were discovered by one of the RubySpec contributors. Matz quickly fixed up the issues. (You can read the gory details here: http://redmine.ruby-lang.org/issues/show/1550). Ruby as a programming language certainly exists in Matz&amp;#8217;s brain. But Ruby as an implementation (&lt;span class="caps"&gt;MRI&lt;/span&gt;) exists in many developers&amp;#8217; brains. RubySpec is an attempt to expose all that knowledge and those assumptions in an objective manner.&lt;/p&gt;
&lt;p&gt;4. Experimentation with implementations and the Ruby language itself. I have recently implemented nearly a dozen variations of Hash for Rubinius to determine which algorithms perform best. In each case, I start by writing code that will pass the RubySpec Hash specs. The specs have been generalized to use a helper method rather than referencing the Hash class constant directly. This has been a huge benefit, especially in Rubinius where the core library Hash class is written entirely in Ruby. I can inherit from Hash and override any methods to write a completely new implementation that does not interfere with the existing Hash class. The RubySpecs also provide a huge safety net and testing ground for trying out new language features and seeing how they interact with existing features.&lt;/p&gt;
&lt;p&gt;5. A learning tool that provides Ruby programmers with concrete examples of code that demonstrates every single Ruby language feature. The Pickaxe book may have better prose, but when it comes to comprehensiveness, I want RubySpec to be number one. And while we have a lot of work to do to make the spec description strings better, you can already learn a lot about Ruby by reading the specdoc output.&lt;/p&gt;
&lt;h4&gt; With everything changing so fast, I imagine keeping the specs up to date is a constant struggle. How do implementers keep up with what&amp;#8217;s going on?&lt;/h4&gt;
&lt;p&gt;Some things are changing fast but when you look at how many distinct behaviors RubySpec covers, a lot isn&amp;#8217;t changing. It&amp;#8217;s hard keeping up with the 1.9 changes. So far in Rubinius, we haven&amp;#8217;t targeted 1.9 specifically, but we have a contributor, Marc-Andre Lafortune, who has added a ton of 1.8.7 and 1.9 features to the core libraries. As with anything, you do it one thing at a time. Having RubySpec available to tell you if you are doing it right is a big help.&lt;/p&gt;
&lt;h4&gt; I would really love to make RubySpec a household name in the general Ruby community. The project I&amp;#8217;m breaking ground on now (called Unity), will hopefully help do this. What sort of information do you think is most valuable to pull out from RubySpec, and who do you see benefiting from it? &lt;/h4&gt;
&lt;p&gt;Again, the primary goal of RubySpec is to provide a definition of the Ruby programming language along with a way to test that an implementation conforms to the definition. So primary pieces of information are which specs pass and which fail on a given implementation. Evan and I have discussed adding a scoring mechanism to MSpec that provides a single percentage number as a measure of an implementation&amp;#8217;s conformance to the standard set by RubySpec. This is something that can give users better information about an implementation&amp;#8217;s completeness when it goes bandying about benchmarking numbers. I&amp;#8217;ll be implementing this in MSpec shortly.&lt;/p&gt;
&lt;h4&gt; RubySpec spans a &lt;strong&gt;ton&lt;/strong&gt; of functionality. It&amp;#8217;s amazing to see how much work has already been done. However, there must be some dark spots still left. What areas of Ruby are still not adequately specified? &lt;/h4&gt;
&lt;p&gt;That is the 10 million dollar question. We can infer something about completeness based on implementations like JRuby that run applications the same as &lt;span class="caps"&gt;MRI&lt;/span&gt; and pass the vast majority of the RubySpec cases. When implementations discover bugs in their own code and enhance the RubySpec coverage, we get a nice closed feedback loop.&lt;/p&gt;
&lt;p&gt;A lot of the standard library still needs to be covered. There are also some little used methods in the core library that lack specs. The procedural-style methods in Kernel come to mind (e.g. using methods without receivers like #gets, #puts, #sub, etc. that operate on $_). We have a utility that creates the spec files for methods and leaves marker specs that we tag as incomplete. In Rubinius, for example, you can run &amp;#8216;bin/mspec tag &amp;#8212;list incomplete&amp;#8217; and get a printout of specs that need to be reviewed for completeness.&lt;/p&gt;
&lt;p&gt;Ultimately, we need a uniform methodology for auditing the completeness and accuracy of the specs. This is still a work in progress.&lt;/p&gt;
&lt;h4&gt; Charles Oliver Nutter (of JRuby) chimes in with some additional feedback on this question: &lt;/h4&gt;
&lt;p&gt;I would inject another small answer here:&lt;/p&gt;
&lt;p&gt;In my experience with RubySpec, the areas least covered are unfortunately often the areas least understood and therefore those most in need of coverage. For example, OpenSSL specs are practically nonexistent, and yet it&amp;#8217;s such a crucial bit of functionality for any app doing &lt;span class="caps"&gt;SSL&lt;/span&gt; (as a client or a server) or working with any &lt;span class="caps"&gt;PKI&lt;/span&gt; or certificate stuff. But it&amp;#8217;s also very hard to test&amp;#8230;most people have zero knowledge of crypto, and so finding people that can write those specs is about as easy as finding people that can write OpenSSL wrappers for new implementations. So there&amp;#8217;s definitely specific areas of RubySpec that need someone with domain knowledge to dive in.&lt;/i&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;As you can see, RubySpec is a vibrant, exciting project with a lot of challenges it needs to face.  My plans are to do my part by building up the Unity app to make this awesome body of work more accessible to the Ruby community at large.   But definitely don&amp;#8217;t wait on it before getting involved, check out RubySpec today and see if there is a way you can pitch in, especially if you think you can help with some of the projects mentioned here.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;To our readers: What sorts of things can you see RubySpec being used for?  What kind of data are you interested in seeing reports on?   Do you think Brian&amp;#8217;s goals for RubySpec are attainable?  Share your thoughts in the comments below.&lt;/b&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 04 Jun 2009 07:52:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/006-brian-ford-rubyspec.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/006-brian-ford-rubyspec.html</guid></item><item><title>Reading Ruby's Standard Library for Fun and Profit</title><description>&lt;p&gt;&lt;b&gt;Note: This post is inspired by JEG2&amp;#8217;s excellent code reading talk at &lt;span class="caps"&gt;MWRC&lt;/span&gt; 2009, called &lt;a href="http://mwrc2009.confreaks.com/13-mar-2009-10-30-littlebigruby-james-edward-grey-ii.html"&gt;LittleBIGRuby&lt;/a&gt;  Go watch it if you have time, then come back and read this.  You might also want to check out the &lt;a href="http://on-ruby.blogspot.com/2009/05/questions-five-ways-code-reading.html"&gt;Question 5 Ways&lt;/a&gt; interview at Pat Eyler&amp;#8217;s &amp;#8220;On Ruby&amp;#8221; blog for more code reading goodness.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We all need to hunt bugs and we all need to integrate our code with other systems. Some of us need to make use of undocumented libraries, and others need to examine code to perform security audits.  Why is it then, that so many developers suck at reading code?&lt;/p&gt;
&lt;p&gt;Almost a decade ago, Joel Spolsky would have told you it&amp;#8217;s harder to &lt;a href="http://www.joelonsoftware.com/articles/fog0000000069.html"&gt;read code than it is to write it&lt;/a&gt; , and that was probably true at one point.  But times have changed, and in a language like Ruby, this definitely does not have to be the case.  As an avid code reader, I&amp;#8217;ll let you in on a secret: All you need to do is practice!&lt;/p&gt;
&lt;p&gt;Beginners and even intermediate developers may need a lot of hand holding at first, that&amp;#8217;s only to be expected.  However, if you want to progress to higher levels of understanding, you must turn to the source.  The merits of higher level idioms and design strategies won&amp;#8217;t be very clear until you need to understand someone else&amp;#8217;s code.  Once you start digging around in someone else&amp;#8217;s code base, you&amp;#8217;ll learn a lot about your own strengths and weaknesses.&lt;/p&gt;
&lt;p&gt;But where should you start?  It&amp;#8217;s tempting to suggest that you should just follow your favorite projects on Github and keep an eye on the patches as they fly.  However, this can be a bit overwhelming at first, and it may be hard to keep up with the velocity and transient nature of active open source projects.  For this reason, I suggest picking a slower moving target that is still useful to you.  Ruby&amp;#8217;s Standard Library fits this description perfectly.&lt;/p&gt;
&lt;h3&gt;How I Read Code&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m going to walk through the process I generally follow when I&amp;#8217;m reading code for the purpose of understanding its implementation.  I sometimes change things up when I have a particular goal in mind, but most of what I&amp;#8217;m about to cover is generally applicable to digging into any new code base.  Keep in mind though, our goal here is mainly just to explore a bit and maybe learn a thing or to along the way.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve chosen the Observable library here because it is small, self-contained, and easy to understand.  There are many libraries like this in the stdlib, so if you feel motivated after reading this post, you might want to go searching for a few other low hanging fruit to test your skills on.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve done what I can to boil the process down to a few repeatable steps, so you&amp;#8217;re welcome to follow along at home if you&amp;#8217;d like.&lt;/p&gt;
&lt;h4&gt;Start with a simple example.&lt;/h4&gt;
&lt;p&gt;I don&amp;#8217;t like diving into code without at least a little bit of context.  So this means that before I go source diving, I&amp;#8217;ll typically use the &lt;span class="caps"&gt;API&lt;/span&gt; documentation (if it exists), to code up a simple example.   If I can&amp;#8217;t find documentation, I&amp;#8217;ll search the web for examples.   It&amp;#8217;s relatively rare to come up completely empty, and a bit of a warning sign if you do.  But since Observable is well &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html"&gt;documented&lt;/a&gt; , it&amp;#8217;s easy enough to come up with something.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re dealing with the Observer design pattern (also known as Pub-Sub), and the first idea that came to mind here for me was a simple chat model.  Users could subscribe to a room and the room would publish the messages that were processed to them.  I wanted the transcripts to be personalized, so that they looked something like this:&lt;/p&gt;
&lt;pre&gt;
  = Greg's Transcript =
  Me: Hi
  Jia: Hello
  Me: Fun, huh?
  Jia: Yeah!

  = Jia's Transcript =
  Gregory: Hi
  Me: Hello
  Gregory: Fun, huh?
  Me: Yeah!
&lt;/pre&gt;
&lt;p&gt;Thinking from the outside in, we can imagine the Ruby code used to generate this output:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  room = Room.new

  greg   = Person.new("Gregory", room)
  jia    = Person.new("Jia", room)

  greg.says "Hi"
  jia.says "Hello"

  greg.says "Fun, huh?"
  jia.says "Yeah!"

  puts "= Greg's Transcript ="
  puts greg.transcript + "\n"

  puts "= Jia's Transcript ="
  puts jia.transcript
&lt;/pre&gt;
&lt;p&gt;Ultimately, what the &lt;tt&gt;Observable&lt;/tt&gt; module buys us is the ability to track subscribers implicitly rather than explicitly.  While it&amp;#8217;d be pretty easy to roll your own code here, you can see in the following definition that &lt;tt&gt;Observable&lt;/tt&gt; provides a few shortcuts for us:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "observer"

  class Room 
    include Observable

    def receive(message, sender)
      changed
      notify_observers(message, sender)
    end
  end

  class Person
    def initialize(name, room)
      @name, @room = name, room
      @transcript  = ""
      @room.add_observer(self)
    end

    attr_reader :transcript, :name

    def update(message, sender)
      if sender == self
        message = "Me: #{message}\n"
      else
        message = "#{sender.name}: #{message}\n"
      end
    
      @transcript &amp;lt;&amp;lt; message
    end

    def says(message)
      @room.receive(message, self)
    end
  end
&lt;/pre&gt;
&lt;p&gt;This is all the code you need to reproduce the desired output, so if you&amp;#8217;re&lt;br /&gt;
interested in tinkering with it a bit, go ahead and do that now.  The real purpose of doing this however was not to implement something useful.   Instead, it was to identify some entry points into &lt;tt&gt;Observable&lt;/tt&gt; that can be our first areas of focus.&lt;/p&gt;
&lt;p&gt;If you look over the code carefully, you find that &lt;tt&gt;changed&lt;/tt&gt;, &lt;tt&gt;notify_observers&lt;/tt&gt;, and &lt;tt&gt;add_observer&lt;/tt&gt; are the keys to what makes our code tick (And incidentally, the only parts that we didn&amp;#8217;t implement ourselves.)  Let&amp;#8217;s dig a little deeper with those targets in mind.&lt;/p&gt;
&lt;h4&gt;Hunt for tests, if they exist.&lt;/h4&gt;
&lt;p&gt;Many of Ruby&amp;#8217;s standard libraries have tests distributed with the source, some do not.  Unfortunately in the case of &lt;tt&gt;Observable&lt;/tt&gt;, I couldn&amp;#8217;t find any tests for it in the Ruby source distribution.  However, that didn&amp;#8217;t mean that it was time to give up.  In cases where &lt;span class="caps"&gt;MRI&lt;/span&gt;/&lt;span class="caps"&gt;YARV&lt;/span&gt; do not have tests, you can try to turn to the great &lt;a href="http://github.com/rubyspec/rubyspec"&gt;RubySpec project&lt;/a&gt;, which is attempting to codify the behavior of Ruby with executable RSpec-like tests.&lt;/p&gt;
&lt;p&gt;As it turns out, RubySpec has &amp;#8220;several tests&amp;#8221;: for &lt;tt&gt;Observable&lt;/tt&gt;.  They are split up by each individual function.  As an example, here are the specs for &lt;tt&gt;notify_observers&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  describe "Observer#notify_observers" do
 
    before(:each) do
      @observable = ObservableSpecs.new
      @observer = ObserverCallbackSpecs.new
      @observable.add_observer(@observer)
    end
 
    it "must call changed before notifying observers" do
      @observer.value.should == nil
      @observable.notify_observers("test")
      @observer.value.should == nil
    end
 
    it "verifies observer responds to update" do
      lambda {
        @observable.add_observer(@observable)
      }.should raise_error(NoMethodError)
    end
 
    it "receives the callback" do
      @observer.value.should == nil
      @observable.changed
      @observable.notify_observers("test")
      @observer.value.should == "test"
    end
 
  end
&lt;/pre&gt;
&lt;p&gt;This code uses some helper objects, which are defined as follows:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'observer'
 
  class ObserverCallbackSpecs
    attr_reader :value
 
    def initialize
      @value = nil
    end
 
    def update(value)
      @value = value
    end
  end
 
  class ObservableSpecs
    include Observable
  end
&lt;/pre&gt;
&lt;p&gt;You can see how the structure of these mirror our earlier example.  When you combined them with the specs, you learn quite a bit about this method.&lt;/p&gt;
&lt;p&gt;First of all, &lt;tt&gt;notify_observers&lt;/tt&gt; doesn&amp;#8217;t do anything if you don&amp;#8217;t first call the &lt;tt&gt;changed&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "must call changed before notifying observers" do
    @observer.value.should == nil
    @observable.notify_observers("test")
    @observer.value.should == nil
  end
&lt;/pre&gt;
&lt;p&gt;Also, we see that any of the observers used need to implement the &lt;tt&gt;update&lt;/tt&gt; callback, matching the signature of &lt;tt&gt;notify_observers&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "verifies observer responds to update" do
    lambda {
      @observable.add_observer(@observable)
    }.should raise_error(NoMethodError)
  end
&lt;/pre&gt;
&lt;p&gt;Of course, when the callback exists and the observable object has been marked as changed, we see a successful result:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "receives the callback" do
    @observer.value.should == nil
    @observable.changed
    @observable.notify_observers("test")
    @observer.value.should == "test"
  end
&lt;/pre&gt;
&lt;p&gt;While these specs aren&amp;#8217;t necessarily giving us every last detail, they provide a general outline of what to expect when we look directly at the source.  This will help us avoid getting overwhelmed when working through the actual implementation. I&amp;#8217;ll leave it to you to check out the rest of the  &lt;a href="http://github.com/rubyspec/rubyspec/tree/1250e42264782c860259046ff93719a3e6a9f03e/library/observer"&gt;Observable specs&lt;/a&gt; if you&amp;#8217;d like.  Doing so may help you understand the code in the following section.&lt;/p&gt;
&lt;h4&gt;Dig into the source with kindness and curiosity&lt;/h4&gt;
&lt;p&gt;The main purpose of reading over the tests first is that they give you a bit of insight into what behaviors the implementation code needs to satisfy.  Assuming you didn&amp;#8217;t skip the last section, it should be pretty clear what&amp;#8217;s going on in the following method definition:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def notify_observers(*arg)
    if defined? @observer_state and @observer_state
      if defined? @observer_peers
        @observer_peers.each { |k, v| k.send v, *arg }
      end
      @observer_state = false
    end
  end
&lt;/pre&gt;
&lt;p&gt;Of course, the &amp;#8216;why&amp;#8217; is as important as the &amp;#8216;how&amp;#8217; when you&amp;#8217;re exploring someone else&amp;#8217;s code. Without looking any farther, one thing that tripped me up was this line:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  if defined? @observer_state and @observer_state
&lt;/pre&gt;
&lt;p&gt;It was immediately clear to me what it did, but not why it was needed.  Upon further investigation, I remembered one of my bad habits.  The following code will issue a warning as written:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module A
    def foo
      @foo
    end
  end

  class B
    include A
  end

  B.new.foo
&lt;/pre&gt;
&lt;p&gt;However, we can avoid this warning using the exact same approach used in &lt;tt&gt;Observable&lt;/tt&gt;, simply by checking whether the instance variable is defined before accessing it:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module A
    def foo
      @foo if defined?(@foo)
    end
  end
&lt;/pre&gt;
&lt;p&gt;Yes, this is more verbose, and seems a bit redundant.  But writing code this way does have a real benefit.   If you follow this convention of checking whether an instance variable is defined whenever you aren&amp;#8217;t sure it will be, this warning can be used to easily catch typos.  The following example, when run with warnings enabled, will illustrate how:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    def foo
      @foo = 10
      bar
    end

    def bar
      @bar = @fooo
    end
  end

  A.new.foo
&lt;/pre&gt;
&lt;p&gt;At this point, I already found a helpful reminder by walking through this code.  While the rest of the source was an interesting read, this was my takeaway.  Please go ahead and read the &lt;a href="http://pastie.org/488486"&gt;full source&lt;/a&gt; and let me know in the comments if you found anything of interest.&lt;/p&gt;
&lt;p&gt;In fact, I have a question for our readers.  Can you find any reason why the following code is written as it is?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # Query the changed state of this object.
  #
  def changed?
    if defined? @observer_state and @observer_state
      true
    else
      false
    end
  end
&lt;/pre&gt;
&lt;p&gt;This looks a bit like a wart to me, and if anything, seems like a long way to go in order to avoid &lt;tt&gt;!!obj&lt;/tt&gt;.   But maybe someone else sees it in a different light?  Actually, that reminds me&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Caveats about the Standard Library&lt;/h3&gt;
&lt;p&gt;While Ruby&amp;#8217;s stdlib is a great place to learn new things, not everything in it is downright beautiful.   Some things are older than others, some reflecting the rust that comes when code is not updated to reflect the latest techniques.&lt;/p&gt;
&lt;p&gt;Furthermore, standard library code tends to be less clever than the sort of stuff we might write for our scripts and gems, by design.  You&amp;#8217;ll find that in many places, explicit and simple code is favored over tricky stuff.  I imagine this is for maintainability purposes.&lt;/p&gt;
&lt;p&gt;Like anything else, you&amp;#8217;ll need to do a bit of hunting to find the right code to learn from.   This practice in and of itself will prove to be useful, so don&amp;#8217;t be afraid if you run across some cruft now and again.&lt;/p&gt;
&lt;p&gt;Of course, another good thing about reading code is that it often inspires us to write code.  While looking through the standard library, consider putting together documentation patches, adding tests, and fixing things you don&amp;#8217;t like.  I&amp;#8217;m sure the folks on &lt;a href="http://www.ruby-lang.org/en/community/mailing-lists/"&gt;ruby-core&lt;/a&gt; would be happy to look at your contributions, and it&amp;#8217;s another great way to learn.&lt;/p&gt;
&lt;h3&gt;Key Things To Remember&lt;/h3&gt;
&lt;p&gt;Code reading is just as important as code writing.  The standard library has about 100 places for you to look for inspiration, and its more likely than not that you&amp;#8217;ll find something of interest if you pick one at random.  If you repeat this process, you&amp;#8217;ll get a better understanding of how Ruby itself works, and be able to carry this experience into your own work.&lt;/p&gt;
&lt;p&gt;Start by playing with some examples, then look for tests, either in the source or in the RubySpec project.  Once you feel like you understand how to use a feature, investigate how it works, and then ask yourself why it is written the way it is.  Don&amp;#8217;t expect to understand the whole thing all at once, and don&amp;#8217;t worry if it takes some time to adjust to someone else&amp;#8217;s style.&lt;/p&gt;
&lt;p&gt;If you do this often enough, you&amp;#8217;ll gain a valuable skill that&amp;#8217;ll pay off like crazy, especially if you work on open source software.  You&amp;#8217;ll notice both patterns and anti-patterns, and this will influence the code you write.  In the end, your fellow code readers will thank you :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sun, 24 May 2009 18:25:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/005-code-reading-stdlib.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/005-code-reading-stdlib.html</guid></item><item><title>Hello World (Literally)</title><description>&lt;p&gt;If Google Analytics is right, we&amp;#8217;ve reached 68 countries in the last three days.  Although I guess this doesn&amp;#8217;t mean much at all on the internet, I think it still makes for a pretty map:&lt;/p&gt;
&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/-OyFgPdlht14elpNP9-G8A?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_hoiny8_4IEY/Sf_dRKHgzcI/AAAAAAAAALM/yFs0gVNO1To/s800/blog-rbp.png" width="600" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;p&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/gregory.t.brown/RBP?feat=embedwebsite"&gt;&lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Of course, I&amp;#8217;d like to back up these statistics with some direct data, so I&amp;#8217;ve got three questions for our readers:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Where are you from?&lt;/li&gt;
	&lt;li&gt;What is the Ruby scene like where you live?&lt;/li&gt;
	&lt;li&gt;What would you like to see on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please join in the conversation and let us know who you are.  So far, the discussions on this blog have been great and I want to get to know more of our readers.  We&amp;#8217;ll resume regularly scheduled deep tech content soon, but hopefully this small diversion will prove to be interesting.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 05 May 2009 06:42:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/hello_world.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/hello_world.html</guid></item><item><title>Fun with Class.new</title><description>&lt;p&gt;&lt;i&gt;Update: I came across an inlink to this page that was layering in advertisements in a frame. Luckily, there are &lt;a href="http://github.com/sandal/rbp-blog/commit/97df49430262beb8ddbb067fba5f1756efd4aac5"&gt;technical solutions&lt;/a&gt; to at least some social problems, and you may now browse again in peace :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve worked with Ruby for at least a little while, you might already know that classes in Ruby are objects themselves, in particular, instances of &lt;tt&gt;Class&lt;/tt&gt;.  Before I get into the fun stuff, let&amp;#8217;s quickly recap what that means.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the ordinary way we define classes, as you all have seen.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Point
    def initialize(x,y)
      @x, @y = x,y
    end
    
    attr_reader :x, :y
    
    def distance(point)
      Math.hypot(point.x - x, point.y - y)
    end
  end 
&lt;/pre&gt;
&lt;p&gt;The interesting thing is that the previous definition is essentially functionally equivalent to the following:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  Point = Class.new do
    def initialize(x,y)
      @x, @y = x,y
    end
  
    attr_reader :x, :y
  
    def distance(point)
      Math.hypot(point.x - x, point.y - y)
    end
  end
&lt;/pre&gt;
&lt;p&gt;This always struck me as a beautiful design decision in Ruby, because it reflects the inherent simplicity of the object model while exposing useful low level hooks for us to use.  Building on this neat concept of anonymously defined classes, I&amp;#8217;ll share a few tricks that have been useful to me in real projects.&lt;/p&gt;
&lt;h3&gt;Cleaner Exception Definitions&lt;/h3&gt;
&lt;p&gt;This sort of code has always bugged me:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module Prawn
    module Errors
     
       class FailedObjectConversion &amp;lt; StandardError; end
     
       class InvalidPageLayout &amp;lt; StandardError; end        
     
       class NotOnPage &amp;lt; StandardError; end

       class UnknownFont &amp;lt; StandardError; end   

       class IncompatibleStringEncoding &amp;lt; StandardError; end     

       class UnknownOption &amp;lt; StandardError; end

    end
  end
&lt;/pre&gt;
&lt;p&gt;Although there are valid reasons for subclassing a &lt;tt&gt;StandardError&lt;/tt&gt;, typically the only reason I am doing it is to get a named exception to rescue.  I don&amp;#8217;t plan to ever add any functionality to its subclass beyond a named constant.  However, if we notice that &lt;tt&gt;Class.new&lt;/tt&gt; can be used to create subclasses, you can write something that more clearly reflects this intention:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module Prawn
    module Errors
       FailedObjectConversion = Class.new(StandardError)
            
       InvalidPageLayout = Class.new(StandardError)     
     
       NotOnPage = Class.new(StandardError)

       UnknownFont = Class.new(StandardError)

       IncompatibleStringEncoding = Class.new(StandardError)     

       UnknownOption = Class.new(StandardError) 

    end
  end
&lt;/pre&gt;
&lt;p&gt;This feels a bit nicer to me, because although it&amp;#8217;s somewhat clear that these are still subclasses, I don&amp;#8217;t have an ugly empty class definition that will never be filled.  Of course, we could make this more &lt;span class="caps"&gt;DRY&lt;/span&gt; if we mix in a little &lt;tt&gt;const_set&lt;/tt&gt; hackery:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
module Prawn
  module Errors
  
    exceptions = %w[ FailedObjectConversion InvalidPageLayout NotOnPage
                    UnknownFont IncompatibleStringEncoding UnknownOption ]

    exceptions.each { |e| const_set(e, Class.new(StandardError)) }

  end
end
&lt;/pre&gt;
&lt;p&gt;Even with this concise definition, you&amp;#8217;ll still get the functionality you&amp;#8217;d expect:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; Prawn::Errors::IncompatibleStringEncoding.ancestors
=&amp;gt; [Prawn::Errors::IncompatibleStringEncoding, StandardError, Exception, Object, Kernel]
&amp;gt;&amp;gt; raise Prawn::Errors::IncompatibleStringEncoding, "Bad string encoding"
Prawn::Errors::IncompatibleStringEncoding: Bad string encoding
	from (irb):33
	from :0
&lt;/pre&gt;
&lt;p&gt;You can even take it farther than this, dynamically building up error classes by a naming convention.  If that sounds interesting to you and you don&amp;#8217;t mind the fuzziness of a &lt;tt&gt;const_missing&lt;/tt&gt; hook, you&amp;#8217;ll want to check out James Gray&amp;#8217;s blog post &lt;a href="http://blog.grayproductions.net/articles/summoning_error_classes_as_needed"&gt;&amp;#8220;Summoning Error Classes As Needed&amp;#8221;&lt;/a&gt;.  Though I tend to be a bit more conservative, there are definitely certain places where a hack like this can come in handy.&lt;/p&gt;
&lt;p&gt;The drawback of using any of these methods discussed here is that they don&amp;#8217;t really play well with RDoc.   However, there are easy ways to work around this, and James details some of them in his post.   In general, it&amp;#8217;s a small price to pay for greater clarity and less work in your code.&lt;/p&gt;
&lt;p&gt;Continuing on the theme of dynamically building up subclasses, we can move on to the next trick.&lt;/p&gt;
&lt;h3&gt;Safer Class Level Unit Testing&lt;/h3&gt;
&lt;p&gt;In my experience, it&amp;#8217;s a little bit tricky to test code that maintains state at the class level.  I&amp;#8217;ve tried everything from mocking out calls, to creating a bunch of explicit subclasses, and even have done something like &lt;tt&gt;klass = SomeClass.dup&lt;/tt&gt; in my unit tests.  While all of these solutions may do the trick depending on the context, there is a simple and elegant way that involves (you guessed it) &lt;tt&gt;Class.new&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a quick example from a patch I submitted to the &lt;em&gt;builder&lt;/em&gt; library that verifies a fix I made to the &lt;tt&gt;BlankSlate&lt;/tt&gt; class:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def test_reveal_should_not_bind_to_an_instance
    with_object_id = Class.new(BlankSlate) do
      reveal(:object_id)
    end

    obj1 = with_object_id.new
    obj2 = with_object_id.new

    assert obj1.object_id != obj2.object_id,
       "Revealed methods should not be bound to a particular instance"
  end
&lt;/pre&gt;
&lt;p&gt;Notice here that although we are doing class level logic, this test is still atomic and does not leave a mess behind in its wake.  We get to use the real &lt;tt&gt;reveal()&lt;/tt&gt; method, which means we don&amp;#8217;t need to think up the mocking interface.  Because we only store this anonymous subclass in a local variable, we know that our other tests won&amp;#8217;t be adversely affected by it, it&amp;#8217;ll just disappear when the code falls out of scope.  The code is clear and expressive, which is a key factor in tests.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re looking for more examples like this, you&amp;#8217;ll want to look over the rest of the &lt;tt&gt;BlankSlate&lt;/tt&gt; &lt;a href="http://github.com/jimweirich/builder/blob/c41c8914bec84f0009869e96ad6ebb39987896d3/test/test_blankslate.rb"&gt;test case&lt;/a&gt; .  I just followed Jim Weirich&amp;#8217;s lead here, so you&amp;#8217;ll see a few other examples that use a similar trick.&lt;/p&gt;
&lt;p&gt;For those interested, the thing that sparked my interest in writing this article today was a tiny bit of domain specific code I had cooked up for my day to day work, which needed to implement a nice interface for filtering search queries at the class level before they were executed.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class FreightOffer::Rail &amp;lt; FreightOffer
    hard_constraint do |query|
      query[:delivery] - query[:pickup] &amp;gt; 5.days
    end

    soft_constraint do |query|
      query[:asking_price] &amp;lt; 5000.to_money
    end
  end
&lt;/pre&gt;
&lt;p&gt;While it&amp;#8217;s easy to test these constraints once they&amp;#8217;re set up for a particular model, I wanted to be able to test drive the constraint interface itself at the abstract level. The best way I could come up with was to write tests that used &lt;tt&gt;Class.new&lt;/tt&gt; to generate subclasses of &lt;tt&gt;FreightOffer&lt;/tt&gt; to test against, which worked well.  While I won&amp;#8217;t post those tests here, it&amp;#8217;s a good exercise if you want to get the feel for this technique.&lt;/p&gt;
&lt;p&gt;The next trick is a little bit different than the first two, but can really come in handy when you want to inject a little syntactic diabetes into the mix.&lt;/p&gt;
&lt;h3&gt;Parameterized Subclassing&lt;/h3&gt;
&lt;p&gt;You might recognize the following example, since it is part of the &lt;a href="http://cachefly.oreilly.com/catalogs/Mastering_the_Dynamic_Toolkit.pdf"&gt;sample chapter&lt;/a&gt; of &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; .  More than just a shameless plug though, I think this particular example shows off an interesting technique for dynamically building up subclasses in a low level system.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with some vanilla code and see how we can clean it up, then we&amp;#8217;ll finally take a look under the hood.  What follows is a &lt;tt&gt;Fatty::Formatter&lt;/tt&gt;, which abstracts the task of producing output in a number of different formats.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class MyReport &amp;lt; Fatty::Formatter 
  
    module Helpers 
      def full_name 
        "#{params[:first_name]} #{params[:last_name]}" 
      end 
    end 
    
    class Txt &amp;lt; Fatty::Format 
      include MyReport::Helpers 
       def render 
        "Hello #{full_name} from plain text" 
       end 
    end 
    
    # use a custom Fatty::Format subclass for extra features 
    class PDF &amp;lt; Prawn::FattyFormat 
      include MyReport::Helpers 
      def render 
        doc.text "Hello #{full_name} from PDF" 
        doc.render 
      end 
    end 
    
    formats.update(:txt =&amp;gt; Txt, :pdf =&amp;gt; PDF) 
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;MyReport&lt;/tt&gt; class in the previous code sample is little more than a glorified &amp;#8220;Hello World&amp;#8221; example that outputs text and &lt;span class="caps"&gt;PDF&lt;/span&gt;.   It is pretty easy to follow and doesn&amp;#8217;t really do anything fancy.  However, we can certainly clean it up and make it look better:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class MyReport &amp;lt; Fatty::Formatter 
    
    helpers do 
      def full_name 
        "#{params[:first_name]} #{params[:last_name]}" 
      end 
    end 
    
    format :txt do 
      def render 
        "Hello #{full_name} from plain text" 
      end 
    end 
    
    format :pdf, :base =&amp;gt; Prawn::FattyFormat do 
      def render 
        doc.text "Hello #{full_name} from PDF" 
        doc.render 
      end 
    end 
    
  end
&lt;/pre&gt;
&lt;p&gt;I think you&amp;#8217;ll agree that this second sample induces the kind of familiar sugar shock that Ruby coders know and love.  It accomplishes the same goals and actually wraps the lower level code rather than replacing it.  But is there some sort of dark magic behind this?  Let&amp;#8217;s peek behind the curtain:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def format(name, options={}, &amp;amp;block) 
    formats[name] = Class.new(options[:base] || Fatty::Format, &amp;amp;block) 
  end
&lt;/pre&gt;
&lt;p&gt;As you can see, it is nothing more than a hash of &lt;tt&gt;formats&lt;/tt&gt; maintained at the class level, combined with a call to &lt;tt&gt;Class.new&lt;/tt&gt; to generate the subclass.  No smoke and mirrors, just the same old Ruby tricks we&amp;#8217;ve been using throughout this article.  The curious may wonder how &lt;tt&gt;helpers()&lt;/tt&gt; works here, and though it&amp;#8217;s slightly tangential, you&amp;#8217;ll see it is similarly simple.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def helpers(helper_module=nil, &amp;amp;block) 
    @helpers = helper_module || Module.new(&amp;amp;block) 
  end 
&lt;/pre&gt;
&lt;p&gt;Though I won&amp;#8217;t get into it here, fun tricks can be done with anonymous modules as well.  Can you think of any that are particularly interesting?  If so, let me know in the comments.&lt;/p&gt;
&lt;p&gt;Although I only showed a part of the picture, you might want to check out the rest of &lt;a href="http://github.com/sandal/fatty/blob/392d65ee9b4be167cfe568f0669b64694ef2bbff/lib/fatty.rb"&gt;Fatty&amp;#8217;s source&lt;/a&gt;.  I call it a &amp;#8216;67 line replacement for &lt;a href="http://rubyreports.org"&gt;Ruport&lt;/a&gt;&amp;#8217;, which is a major exaggeration, but it is really surprising how much you can get out of a few dynamic Ruby tricks when you combine them together properly.  A lot of these ideas were actually inspired by the &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt; web framework, so that&amp;#8217;s another project to add to your code reading list if you&amp;#8217;re looking to learn new tricks.&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;#8217;m getting off topic now, and it&amp;#8217;s about time to wrap up anyway.  I&amp;#8217;ll go on one more tiny tangent, and then send you on your way.&lt;/p&gt;
&lt;h3&gt;Shortcutting with Struct&lt;/h3&gt;
&lt;p&gt;With all this talk about using anonymous sub-classes, I can&amp;#8217;t help but recap one of the &lt;a href="http://blog.grayproductions.net/articles/all_about_struct"&gt;oldest tricks in the book&lt;/a&gt;.  The method &lt;tt&gt;Struct.new&lt;/tt&gt; can be handy for shortcutting class creation.  Using it, the very first example in this post could be simplified down to:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Point &amp;lt; Struct.new(:x, :y)
  def distance(point)
    Math.hypot(point.x - x, point.y - y)
  end
end
&lt;/pre&gt;
&lt;p&gt;The constructor and accessors are provided for free by &lt;tt&gt;Struct&lt;/tt&gt; here.  Of course, the real reason I mentioned this was to get you thinking.  If &lt;tt&gt;Struct.new&lt;/tt&gt; can work this way, and we know that &lt;tt&gt;Class.new&lt;/tt&gt; can accept a block definition that provides a closure, what other cool uses of parameterized subclasses can we cook up?&lt;/p&gt;
&lt;h3&gt;Please Share Your Thoughts&lt;/h3&gt;
&lt;p&gt;I wrote this article in hopes that it&amp;#8217;ll be a jumping off point for discussion on more cool tricks I haven&amp;#8217;t seen before, or failing that, ones that other readers haven&amp;#8217;t seen before.  While there certainly is a lot of nasty, scary looking &amp;#8220;meta-programming&amp;#8221; out there that makes people feel like this stuff is hard and esoteric, there are many techniques that lead to simple, elegant, and beautiful dynamic code.  Please let me know what you think of these techniques, and definitely share one of your own if you&amp;#8217;d like.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 30 Apr 2009 17:55:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/anonymous_class_hacks.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/anonymous_class_hacks.html</guid></item><item><title>Rails Modularity for Lazy Bastards</title><description>&lt;p&gt;When we develop standalone systems or work on libraries and frameworks, modularity seems to come naturally.  When something seems to gain a life of its own, we pull it off into its own package or subsystem to keep things clean.  This is a natural extension of the sorts of design decisions we make at the object level in our software, and helps us work on complicated problems, often working alongside other hackers, without losing our wits.&lt;/p&gt;
&lt;p&gt;It seems a bit surprising that these helpful guiding principals can often evaporate when we bring our software to the web.  Sure, we may make use of plugins and gems for foundational support, but if you take a good look at a Rails application that has more than 50 models or so, you&amp;#8217;ll be hard pressed to find a unified purpose behind all that logic.&lt;/p&gt;
&lt;p&gt;However, if you try to break things down into core sets of functionality, you may find that certain vertical slices can be made that allow you to break out bits of functionality into their own separate focus areas. For example, you may discover that part of your application is actually a mini &lt;span class="caps"&gt;CRM&lt;/span&gt; system.  Or maybe you&amp;#8217;ve snuck in a small reporting system without noticing it consciously.   The list goes on, but the underlying idea here is that the larger a system gets, the harder it is to define its core purpose.&lt;/p&gt;
&lt;p&gt;While splitting out these subsystems may seem like the obvious choice in a standalone application, there seems to be a certain amount of &lt;span class="caps"&gt;FUD&lt;/span&gt; about this strategy when it comes to the web.  This probably originates from a time before &lt;span class="caps"&gt;REST&lt;/span&gt;, in which interaction between web applications was overly complex,making the costs of fragmentation higher than the benefits of a modular architecture.  These days, we live in better times and work with better frameworks, and should reap the benefits that come along with it.&lt;/p&gt;
&lt;p&gt;But actions speak louder than words, so let&amp;#8217;s take a look at some of the underlying tech and how to use it.  Building on the &lt;span class="caps"&gt;CRM&lt;/span&gt; scenario, I&amp;#8217;ll start by showing how to access a Customer model from another application using ActiveResource.&lt;/p&gt;
&lt;h3&gt;Sharing Model Data via ActiveResource&lt;/h3&gt;
&lt;p&gt;Suppose that we&amp;#8217;ve got a &lt;span class="caps"&gt;CRM&lt;/span&gt; system that has a Customer model that has a schema that looks something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  create_table :customers do |t|
    t.string :first_name
    t.string :last_name
    t.string :email
    t.string :daytime_phone
    t.string :evening_phone
    t.timestamps
  end
&lt;/pre&gt;
&lt;p&gt;With this, we can do all the ordinary &lt;span class="caps"&gt;CRUD&lt;/span&gt; operations within our application, so I won&amp;#8217;t bore you with the details.  What we&amp;#8217;re interested in is how to accomplish these same goals from an external application.  So within our &lt;span class="caps"&gt;CRM&lt;/span&gt; system, this essentially boils down to simply providing a RESTful interface to our Customer resource.  After adding &lt;tt&gt;map.resources :customers&lt;/tt&gt; to our &lt;em&gt;config/routes.rb&lt;/em&gt; file, we code up a &lt;tt&gt;CustomersController&lt;/tt&gt; that looks something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class CustomersController &amp;lt; ApplicationController
  
    def index
      @customers = Customer.find(:all)
      respond_to do |format|
        format.xml { render :xml =&amp;gt; @customers }
        format.html
      end
    end
 
    def show
      customer = Customer.find(params[:id])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; customer.to_xml }
        format.html
      end
    end
 
    def create
      customer = Customer.create(params[:customer])
      respond_to do |format|
        format.html { redirect_to entry }
        format.xml { render :xml =&amp;gt; customer, :status   =&amp;gt; :created, 
                                              :location =&amp;gt; customer }
      end
    end
 
    def update
      customer = Customer.update(params[:id], params[:customer])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; customer.to_xml }
        format.html
      end
    end
 
    def destroy
      Customer.destroy(params[:id])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; "", :status =&amp;gt; 200 }
        format.html
      end
    end
 
  end
&lt;/pre&gt;
&lt;p&gt;This may look familiar even if you haven&amp;#8217;t worked with ActiveResource previously, as it&amp;#8217;s basically the same boiler plate you&amp;#8217;ll find in a lot of Rails documentation.  In the &lt;tt&gt;respond_to&lt;/tt&gt; block, &lt;tt&gt;format.xml&lt;/tt&gt; is what matters here, as it is what connects our resource to the services which consume it.  The good news is we won&amp;#8217;t have to actually work with the &lt;span class="caps"&gt;XML&lt;/span&gt; data, as you&amp;#8217;ll see in a moment.&lt;/p&gt;
&lt;p&gt;While there are a few things left to do to make this code usable in a real application, we can already test basic interactions with a secondary application.  Using any other rails app we&amp;#8217;d like, we can add an &lt;tt&gt;ActiveResource&lt;/tt&gt; model by creating a file called &lt;em&gt;app/models/customer.rb&lt;/em&gt; and setting it up like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; ActiveResource::Base
    self.site = "http://localhost:3000/"
  end
&lt;/pre&gt;
&lt;p&gt;Now here comes the interesting part.  If you fire up &lt;tt&gt;script/console&lt;/tt&gt; on the client side application that is interfacing with the &lt;span class="caps"&gt;CRM&lt;/span&gt; system, you can see the same familiar &lt;span class="caps"&gt;CRUD&lt;/span&gt; operations, but taking place from a completely separate application:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt; Customer.create(:first_name =&amp;gt; "Gregory", :last_name =&amp;gt; "Brown")
  =&amp;gt; #&amp;lt;Customer:0x20d2120 @prefix_options={}, @attributes={"evening_phone"=&amp;gt;nil, "updated_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "daytime_phone"=&amp;gt;nil, "id"=&amp;gt;1, "first_name"=&amp;gt;"Gregory", "last_name"=&amp;gt;"Brown", "created_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "email"=&amp;gt;nil}&amp;gt;
 
  &amp;gt;&amp;gt; Customer.find(:all)
  =&amp;gt; [#&amp;lt;Customer:0x20a939c @prefix_options={}, @attributes={"evening_phone"=&amp;gt;nil, "updated_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "daytime_phone"=&amp;gt;nil, "id"=&amp;gt;1, "first_name"=&amp;gt;"Gregory", "last_name"=&amp;gt;"Brown", "created_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "email"=&amp;gt;nil}&amp;gt;]
 
  &amp;gt;&amp;gt; Customer.find(1).first_name
  =&amp;gt; "Gregory"
 
  &amp;gt;&amp;gt; Customer.delete(1)
  =&amp;gt; #&amp;lt;Net::HTTPOK 200 OK readbody=true&amp;gt;
 
  &amp;gt;&amp;gt; Customer.find(:all)
  =&amp;gt; []
&lt;/pre&gt;
&lt;p&gt;While the interface and behavior isn&amp;#8217;t downright identical to &lt;tt&gt;ActiveRecord&lt;/tt&gt;, it bears a striking resemblance and allows you to retain much of the functionality that is needed for basic data manipulation.&lt;/p&gt;
&lt;p&gt;Now that we can see the basic functionality in action, let&amp;#8217;s go back and fix a few key issues.  We definitely want to add some sort of authentication to this system, as it is currently allowing any third party application to modify and destroy records.  We also will most likely want a more flexible option for locating services than just hard coding a server address in each model file.  Once these two things are in place, we&amp;#8217;ll have the beginnings of a decentralized Rails based application.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;API&lt;/span&gt; Keys with &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication&lt;/h3&gt;
&lt;p&gt;I want to preface this section by saying I&amp;#8217;m typically not the one responsible for any sort of security hardening in the applications I work on.   That means that I&amp;#8217;m by no means an expert in how to make your applications safe from the malignant forces of the interweb.   That having been said, what follows is a simple technique that seems to work for me when it comes to slapping a simple authentication model in place.&lt;/p&gt;
&lt;p&gt;First, in the app that is providing the service, in this case, our fictional &lt;span class="caps"&gt;CRM&lt;/span&gt; system, you&amp;#8217;ll want something like this in your &lt;tt&gt;ApplicationController&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def basic_http_auth
    authenticated = false
    authenticate_with_http_basic do |login, password|
      if login == "api" &amp;amp;&amp;amp; password == API_KEY
        authenticated = true
      end
    end
 
    raise "Authentication failed" unless authenticated
  end
&lt;/pre&gt;
&lt;p&gt;Here, &lt;tt&gt;API_KEY&lt;/tt&gt; is some shared secret that is known by both your service providing application, and any client that wishes to use your service.  In this blog post, I&amp;#8217;ll be using the string &lt;tt&gt;&amp;#8220;kittens&amp;#8221;&lt;/tt&gt;, but you&amp;#8217;ll obviously want to pick something longer, and with significantly more entropy.&lt;/p&gt;
&lt;p&gt;After dropping a &lt;tt&gt;before_filter&lt;/tt&gt; in your &lt;tt&gt;CustomersController&lt;/tt&gt; that points to &lt;tt&gt;basic_http_auth&lt;/tt&gt;, you&amp;#8217;ll need to update your ActiveResource model definition.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; ActiveResource::Base
    self.site = "http://localhost:3000/"
    self.user = "api"
    self.password = "kittens"
  end
&lt;/pre&gt;
&lt;p&gt;If you forget to do this, you won&amp;#8217;t be able to retrieve or modify any of the customer data.  This means that any application that does not know the shared secret may not use the resource.  Although this is hardly a fancy solution, it gets the job done.   Now, let&amp;#8217;s take a look at how to make integration even easier and get rid of some of these hard coded values at the per-model level.&lt;/p&gt;
&lt;h3&gt;Simplifying Integration&lt;/h3&gt;
&lt;p&gt;So far, the work has been pretty simple, but it&amp;#8217;s important to keep in mind that if we really want to break up our applications into small, manageable subsystems, we might need to deal with a lot of remote resources.&lt;/p&gt;
&lt;p&gt;Pulled directly from some commercial work I&amp;#8217;ve been doing with Brad Ediger of Madriska Media Group (and of &lt;a href="http://oreilly.com/catalog/9780596510329/"&gt;Advanced Rails&lt;/a&gt; fame), what follows is a helper file that provides two useful features for working with remote resources via ActiveResource:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'yaml'
  require 'activeresource'
 
  class ServiceLocator
 
    API_KEY = "kittens"
 
    def self.services
      return @services if @services
      config_file = File.join(RAILS_ROOT, %w[config services.yml])
      config = YAML.load_file(config_file)
      @services = config[RAILS_ENV]
    end
 
    def self.[](name)
      services[name.to_s]
    end
  end
 
  def Service(name)
    Class.new(ActiveResource::Base) do
      self.site = "http://#{ServiceLocator[name]}"
      self.user = "api"
      self.password = ServiceLocator::API_KEY
    end
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;ServiceLocator&lt;/tt&gt; part was Brad&amp;#8217;s idea, and it represents a simple way to map the URLs of different services to a label based on what environment you are currently running in.  A basic &lt;em&gt;config/services.yml&lt;/em&gt; file might look something like this:&lt;/p&gt;
&lt;pre name="code"&gt;
  development:
    crm: localhost:3000
    reports: localhost:3001

  production:
    crm: crm.example.com
    reports: reports.example.com
&lt;/pre&gt;
&lt;p&gt;This is nice, because it allows us to configure the locations of our various services all in one place.  The interface is very simple and straightforward:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt; ServiceLocator[:crm]
  =&amp;gt; "localhost:3000"
&lt;/pre&gt;
&lt;p&gt;However, upon seeing this feature, I decided to take it a step farther.  Though it might sacrifice a bit of purity, the &lt;tt&gt;Service()&lt;/tt&gt; method is actually a parameterized class constructor that builds up a subclass filling out the &lt;span class="caps"&gt;API&lt;/span&gt; key and service address for you. What that means is that you can replace your initial &lt;tt&gt;Customer&lt;/tt&gt; definition with this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; Service(:crm)
    # my custom methods here.
  end
&lt;/pre&gt;
&lt;p&gt;Since Rails handles the mapping of resource names to class names for you, you can easily support as many remote classes from a single service as you&amp;#8217;d like this way.   When I read this aloud in my head, I tend to think of &lt;tt&gt;SomeClass &amp;lt; Service(:some_service)&lt;/tt&gt; as &amp;#8220;SomeClass is a resource provided by some_service&amp;#8221;.   Feel free to forego the magic here if this concerns you, but I personally find it pleasing to the eyes.&lt;/p&gt;
&lt;h3&gt;Just Starting a Conversation&lt;/h3&gt;
&lt;p&gt;I didn&amp;#8217;t go into great detail about how to use the various technologies I&amp;#8217;ve touched on here, but I&amp;#8217;ve hopefully provided a glimpse into what is possible to those who are uninitiated, as well as provided some food for thought to those who already have some experience in building decentralized Rails apps.&lt;/p&gt;
&lt;p&gt;To provide some extra insight into the approach I&amp;#8217;ve been using on my latest project, we basically keep everything in one big git repository, with separate folders for each application.  At the root, there is a &lt;em&gt;shared/&lt;/em&gt; folder in which we keep some shared library files, including some support infrastructure for things like a simple &lt;span class="caps"&gt;SSO&lt;/span&gt; mechanism and a database backed cross-application logging system.   We also vendor one copy of Rails there and simply symlink &lt;em&gt;vendor/rails&lt;/em&gt; in our individual apps, except for when we need a specific version for a particular service.&lt;/p&gt;
&lt;p&gt;The overarching idea is that there is a foundational support library that our individual apps sit on top of, and that they communicate with each other only through the service interfaces we expose.  We&amp;#8217;ve obviously got more complicated needs, and thus finer grained controls than what I&amp;#8217;ve covered in this article, but the basic ActiveResource functionality seems to be serving us well.&lt;/p&gt;
&lt;p&gt;What I&amp;#8217;d like to know is what other folks have been doing to help manage the complexity of their larger Rails apps.  Do you think the rough sketch of ideas I&amp;#8217;ve laid out here sounds promising?  Do you foresee potential pitfalls that I haven&amp;#8217;t considered?  Leave a comment and let me know.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 16 Apr 2009 04:31:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/rails_modularity_1.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/rails_modularity_1.html</guid></item><item><title>Welcome to the RBP blog</title><description>&lt;p&gt;Hello, and welcome to the Ruby Best Practices blog.  I am happy to announce this new collaborative writing project, along with the great team that&amp;#8217;ll be running it.  A couple weeks ago I put out a call for volunteers to help me provide a new community resource for discovering and discussing best practices in Ruby, and now, we&amp;#8217;re ready to get rolling.&lt;/p&gt;
&lt;p&gt;In addition to myself: &lt;a href="/about/jamesbritt.html"&gt;James Britt&lt;/a&gt;, &lt;a href="/about/wyhaines.html"&gt;Kirk Haines&lt;/a&gt;, &lt;a href="/about/rklemme.html"&gt;Robert Klemme&lt;/a&gt;, &lt;a href="/about/jm.html"&gt;Jeremy McAnally&lt;/a&gt;, &lt;a href="/about/seanohalpin.html"&gt;Sean O&amp;#8217;Halpin&lt;/a&gt;, &lt;a href="/about/judofyr.html"&gt;Magnus Holm&lt;/a&gt; and &lt;a href="/about/laktek.html"&gt;Lakshan Perera&lt;/a&gt; round out the team.  I am absolutely thrilled to have such a diverse and talented group to work with, and I can&amp;#8217;t wait to see the content that we&amp;#8217;ll produce together.&lt;/p&gt;
&lt;p&gt;The general theme we&amp;#8217;ve agreed upon for this blog is that each post should exhibit Ruby code that we can be proud of.  We want to expose best practices through practical examples, so you will surely see a lot of open source code being discussed here.  We want to give you less of &amp;#8220;Here&amp;#8217;s six great Rails plugins&amp;#8221; and more of &amp;#8220;Examples of Connascense in ActiveRecord&amp;#8221;, or &amp;#8220;Common Pitfalls in &lt;span class="caps"&gt;DSL&lt;/span&gt; Design, and How to Avoid Them&amp;#8221;.  Not every single post will be focused directly on best practices and idioms, but all will contain them.&lt;/p&gt;
&lt;p&gt;This will be a code and high-level design heavy blog.  We don&amp;#8217;t plan to bore you with war stories or skimp on the technical value of our content to promote our latest cute but useless hack.  That having been said, we plan to have fun while we write, and the occasional diversion will happen as a result.  However, it&amp;#8217;s safe to say that our content will be geared more towards the motivated developer looking to improve her craft rather than the general &amp;#8220;plzgivemethecodes&amp;#8221; crowd.  If that sounds like your kind of thing, I think you&amp;#8217;ll really enjoy this blog.&lt;/p&gt;
&lt;p&gt;The blog engine we&amp;#8217;ve decided to use is &lt;a href="http://github.com/sandal/korma"&gt;Korma&lt;/a&gt; which I&amp;#8217;m sure you&amp;#8217;ll hear more about in the near future.  It was designed specifically to run this blog, is git based, and gives us a lot of cool features that we wanted to make sure to have in place before launch.  Because we want to provide both the authors and the readers freedom to choose which content they are interested in, it is possible to subscribe to individual author feeds on this blog.  This means that if you like 6 of us, the two you don&amp;#8217;t like won&amp;#8217;t bother you.   Of course, we hope you like us all.&lt;/p&gt;
&lt;p&gt;Over time, we&amp;#8217;ll eventually begin accepting outside contributions to this blog, likely through something as simple as a fork and pull request on github.  This means if you have an idea for an article that you&amp;#8217;d like to see here, we may be accepting new content from third party contributors soon.  However, before we can do that, we need to wait for the dust to settle, so look for an announcement in a few weeks.&lt;/p&gt;
&lt;p&gt;It may take us a little while to work out the kinks in our blogging software.  We want to keep things simple, but there still might be a few bugs here or there.  If you run into problems using this blog, please email gregory.t.brown at gmail.com and let me know.&lt;/p&gt;
&lt;p&gt;I think that pretty much wraps up the welcome letter.  New posts should be cycling in within the next couple days, and we hope to remain active moving forward.  Thanks for checking out this new blog, and happy hacking!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Apr 2009 17:02:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/welcome.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/welcome.html</guid></item></channel></rss>