<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Brandon Dimcheff</title>
 
 <link href="http://brandon.dimcheff.com/" />
 <updated>2011-06-30T11:44:08-04:00</updated>
 <id>http://brandon.dimcheff.com/</id>
 <author>
   <name>Brandon Dimcheff</name>
   <email>brandon-NOSPAM at dimcheff.com</email>
 </author>
 
 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/bdimcheff" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="bdimcheff" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Hacking Chrome with Git</title>
   <link href="http://brandon.dimcheff.com/2010/04/24/hacking-chrome.html" />
   <updated>2010-04-24T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2010/04/24/hacking-chrome</id>
   <content type="html">&lt;h3 id='motivations'&gt;Motivations&lt;/h3&gt;

&lt;p&gt;I spent some time hacking around in Chrome the other day because I have been extremely frustrated with the behavior of the downloads bar in the Mac version of Chrome. When the user initiates a download, it appends the downloads bar to the bottom of your current window, causing your window to grow by the height of the download bar.&lt;/p&gt;

&lt;p&gt;This behavior really bothers me, since I have my window set up with about 10px of padding around all sides so I can easily see my IM window and other things that I have docked to the top/side of my desktop. When Chrome grows the window, I have to manually shrink it and then scoot the window away from the title bar again. Then, when I close the downloads tab, I need to make the window bigger so there isn&amp;#8217;t an enormous gap below the browser window.&lt;/p&gt;

&lt;p&gt;I submitted a &lt;a href='http://code.google.com/p/chromium/issues/detail?id=42207'&gt;bug report&lt;/a&gt; about this issue, but a member of the Chrome team explains that they consider this to be the correct behavior:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is by design, as we do not want to change the size of the web content. We do attempt to restore the original window size when you close the download shelf, although that logic seems to break at times (see Issue 39266).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If that&amp;#8217;s their position, then fine, though it does contradict other behavior of Chrome&amp;#8217;s. Chrome will, for instance, not enlarge the window when they display the &amp;#8220;do you want Chrome to remember your password&amp;#8221; alert bar and other similar things. It simply pushes the content down a small amount and then pulls it back up when you close the alert. This is far preferable to me over messing with the size of my window.&lt;/p&gt;

&lt;h3 id='the_fix'&gt;The Fix&lt;/h3&gt;

&lt;p&gt;Well, Chrome is open source, so I decided that if they won&amp;#8217;t fix it, I would. At least for my build, anyways. Turns out that it&amp;#8217;s a one-line patch to a single controller file. Here they check to see if the view that&amp;#8217;s initiating a redraw is the download shelf or the bookmark bar. If it is, they add the height to the view to the window. In this case, I just removed the condition for the download shelf and voila!&lt;/p&gt;
&lt;script src='https://gist.github.com/375990.js?file=keep-downloads-bar-from-making-the-window-bigger.patch'&gt;
&lt;/script&gt;
&lt;h3 id='how_i_built_chrome'&gt;How I built Chrome&lt;/h3&gt;

&lt;p&gt;Hopefully I can save you some time if you&amp;#8217;d like to perform similar surgery to your copy of Chrome. It took me a few tries to get everything right, due to some incorrect documentation and the enormous size of the Chrome checkout. Naturally I want to use git, since it&amp;#8217;ll make my patch sets so much easier to maintain. These instructions show you how to build a specific release version with your patches using git. This assumes you&amp;#8217;re building 5.0.375.17. Substitute a different version if you&amp;#8217;d like.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow the &lt;a href='http://code.google.com/p/chromium/wiki/UsingGit'&gt;Chrome Git instructions&lt;/a&gt; steps 1-3. You&amp;#8217;ll need to install depot tools as indicated in step 2.&lt;/li&gt;

&lt;li&gt;Instead of using the URL specified in step 4, use http://src.chromium.org/svn/releases/5.0.375.17, or another version of your choice.&lt;/li&gt;

&lt;li&gt;cd into ./src&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git config --add svn-remote.375.url http://src.chromium.org/svn/branches/375/src&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git config --add svn-remote.375.fetch :refs/remotes/375&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git svn fetch 375&lt;/code&gt; (this fetches branch 375 into your local git repo)&lt;/li&gt;

&lt;li&gt;Look in http://src.chromium.org/svn/releases/5.0.375.17/DEPS and find in the &lt;code&gt;deps&lt;/code&gt; dict where there is &lt;code&gt;src&lt;/code&gt; alone. In this case, the value is &lt;code&gt;/branches/375/src@45275&lt;/code&gt;. This means that version 375.17 is svn commit 45275. Remember that number.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git checkout refs/remotes/375&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git log&lt;/code&gt; and search for 45275. Once you find the commit, note the git sha hash. In this case, it is 1bb2782587c269be10f842a468e2d26b38003daa.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git checkout -b 375.17 1bb2782587c269be10f842a468e2d26b38003daa&lt;/code&gt; (make a checkout of the exact version of the release)&lt;/li&gt;

&lt;li&gt;Do steps 5-6 of the Chrome git instructions.&lt;/li&gt;

&lt;li&gt;Apply your patches&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You now have a specific version of Chrome and all its dependencies checked out and ready to build. You can now follow the &lt;a href='http://code.google.com/p/chromium/wiki/MacBuildInstructions'&gt;Mac OS X build instructions&lt;/a&gt;, or just open &lt;code&gt;src/chrome/chrome.xcodeproj&lt;/code&gt; and choose &amp;#8220;chrome&amp;#8221; from the build menu in the upper left. Choose &amp;#8220;Release&amp;#8221; if you want to build Chrome for actual use. Note that this took over an hour on my fancy new i7 MacBook Pro with 4GB of RAM. It also used enough resources that my computer was nearly unusable for part of the compile.&lt;/p&gt;

&lt;h3 id='chrome_build_process'&gt;Chrome Build Process&lt;/h3&gt;

&lt;p&gt;A few notes about the Chrome build process: The git repo stores only the code for the browser itself. General libraries, both Google internal and external, are fetched by using the &lt;code&gt;gclient sync&lt;/code&gt; command. This is somewhat similar to git submodules, in that it allows Google to pin specific revisions of dependencies to a release. The DEPS file stores all the revisions of the external repositories that are necessary to duplicate a build. The tricky part was to make sure that the git checkout and the dependencies both corresponded to the same release version.&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t yet had to switch my build to use a different release. As soon as that happens, I will update this page to give instructions on how to do so.&lt;/p&gt;

&lt;h3 id='download'&gt;Download&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;d like, you can &lt;a href='/chromium-5.0.375.17-dlfix.app.zip'&gt;download&lt;/a&gt; a copy of the current dev channel of Chromium with my fix applied. Or you can follow the instructions above and patch it yourself.&lt;/p&gt;

&lt;h3 id='the_future'&gt;The Future&lt;/h3&gt;

&lt;p&gt;The Chrome guys are working on &lt;a href='http://code.google.com/p/chromium/issues/detail?id=41467'&gt;eliminating the http:// scheme&lt;/a&gt; from standard HTTP urls. It turns out that this caused a lot of bugs when they released it into the dev channel so they reverted the change, but they have said that they will eventually revive this &amp;#8220;feature&amp;#8221;. I found it really annoying and my custom chrome build will likely do away with http hiding once it becomes part of Chrome. I&amp;#8217;m happy to work with someone who&amp;#8217;s also annoyed by this to set up an automatic build to release a new dev channel build with custom patches to fix some of these &amp;#8220;features&amp;#8221;&amp;#8230; Let me know.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Ruby Brew at Great Lakes Ruby Bash</title>
   <link href="http://brandon.dimcheff.com/2010/04/17/ruby-brew-at-great-lakes-ruby-bash.html" />
   <updated>2010-04-17T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2010/04/17/ruby-brew-at-great-lakes-ruby-bash</id>
   <content type="html">&lt;span style='margin:0 10px; float:right'&gt;&lt;img src='/images/ruby_brew.jpg' height='160' alt='ruby brew' width='240' /&gt;&lt;/span&gt;
&lt;p&gt;John Roos of &lt;a href='http://roosroast.com'&gt;Roos Roast&lt;/a&gt; designed an excellent blend of coffee for Great Lakes Ruby Bash. John started Roos Roast while selling cars at Dunning Subaru. I met him there when I bought my WRX, when he gave me a free pound of coffee with my car. Not long after that, he quit selling cars and started roasting coffee full-time.&lt;/p&gt;

&lt;p&gt;We have enough coffee to make 300 cups during the conference, plus we have 6 half-pound bags of coffee to raffle off for the attendees.&lt;/p&gt;

&lt;p&gt;Huge thanks to John for doing this for us. If there&amp;#8217;s enough demand, he might be convinced to roast more batches. Call him up or stop by his &lt;a href='http://roosroast.com/about/'&gt;roasting operation&lt;/a&gt; and demand some Ruby Brew!&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re not in the Ann Arbor area, you can order his coffee by phone or &lt;a href='http://roosroast.com/shop/ruby-brew/'&gt;online&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Working on this project with John was a lot of fun. I watched as he carved the Ruby Brew logo into a rubber stamp block. He also put me to work a bit. I stamped 300 of our cups, and weighed and ground our coffee for the conference.&lt;/p&gt;
&lt;object height='300' width='400'&gt; &lt;param name='flashvars' value='offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fmoofbong%2Fsets%2F72157623843059602%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fmoofbong%2Fsets%2F72157623843059602%2F&amp;set_id=72157623843059602&amp;jump_to=' /&gt; &lt;param name='movie' value='http://www.flickr.com/apps/slideshow/show.swf?v=71649' /&gt; &lt;param name='allowFullScreen' value='true' /&gt;&lt;embed src='http://www.flickr.com/apps/slideshow/show.swf?v=71649' allowFullScreen='true' type='application/x-shockwave-flash' height='300' flashvars='offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fmoofbong%2Fsets%2F72157623843059602%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fmoofbong%2Fsets%2F72157623843059602%2F&amp;set_id=72157623843059602&amp;jump_to=' width='400' /&gt;&lt;/object&gt;
&lt;p&gt;Thanks, John!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Method of the Month 1:  Ruby's sort vs. sort_by</title>
   <link href="http://brandon.dimcheff.com/2009/11/18/rubys-sort-vs-sort-by.html" />
   <updated>2009-11-18T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/11/18/rubys-sort-vs-sort-by</id>
   <content type="html">&lt;p&gt;Ruby&amp;#8217;s Array has 2 methods for sorting: &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;sort_by&lt;/code&gt;. Both methods sort your array (obviously) but they do it in slightly different ways.&lt;/p&gt;

&lt;h3 id='background'&gt;Background&lt;/h3&gt;

&lt;p&gt;This article is based on a talk I gave at the &lt;a href='http://a2rb.org'&gt;Ann Arbor Ruby Brigade&lt;/a&gt; in August. The idea for this talk was conjured up at &lt;a href='http://erubycon.com'&gt;eRubyCon&lt;/a&gt; during a discussion between &lt;a href='http://gayleforce.wordpress.com'&gt;Gayle Craig&lt;/a&gt; and me. We decided we would each give a brief talk about the differences between &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;sort_by&lt;/code&gt; at our next user group meetings. Amazingly, we both followed through.&lt;/p&gt;

&lt;h3 id='id1'&gt;&lt;code&gt;sort&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A Ruby array&amp;#8217;s &lt;code&gt;sort&lt;/code&gt; method is pretty straightforward. If called without a block, it uses each objects&amp;#8217; comparison operator (&lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;) to return a new array with all the elements sorted. If called with a block, you may specify your own comparator as shown below:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;sort&lt;/span&gt;                   &lt;span class='c1'&gt;# =&amp;gt; [1, 2, 3, 4, 7, 9]&lt;/span&gt;
&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;sort&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;  &lt;span class='c1'&gt;# =&amp;gt; [9, 7, 4, 3, 2, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that the block for &lt;code&gt;sort&lt;/code&gt; accepts two parameters. The return value of the block must be -1, 0, or 1. -1 indicates that the first item is less than the second, 0 indicates they are equal, and 1 indicates that the first item is greater than the second one.&lt;/p&gt;

&lt;h3 id='id2'&gt;&lt;code&gt;sort_by&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;sort_by&lt;/code&gt; method is slightly different. Its block only takes one parameter instead of two. Your array is then sorted by the results of each of the block calls. For example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;sort_by&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;             &lt;span class='c1'&gt;# =&amp;gt; [9, 7, 4, 3, 2, 1]&lt;/span&gt;
&lt;span class='sx'&gt;%w{ abcd ab abc abcde }&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sort_by&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;length&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;  &lt;span class='c1'&gt;# =&amp;gt; [&amp;quot;ab&amp;quot;, &amp;quot;abc&amp;quot;, &amp;quot;abcd&amp;quot;, &amp;quot;abcde&amp;quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is accomplished using something called a &lt;a href='http://en.wikipedia.org/wiki/Schwartzian_transform'&gt;Schwartzian Transform&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id='the_schwartzian_transform'&gt;The Schwartzian Transform&lt;/h4&gt;

&lt;p&gt;All a schwartzian transform does is turn each record of your array into a tuple with the first element being the item on which you wish to sort. That array of tuples is then sorted. Since the first item in the tuple gets precedence, it is effectively the same as sorting the array by the results of the &lt;code&gt;sort_by&lt;/code&gt; block. Once sorted, the first element of the tuple is removed, leaving your original array in sorted order. Below is an example implementation in pure ruby:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nn'&gt;Enumerable&lt;/span&gt;
  &lt;span class='c1'&gt;# This is essentially the implementation of sort_by&lt;/span&gt;
  &lt;span class='c1'&gt;# It&amp;#39;s written in C in MRI, so it&amp;#39;s a little faster&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;my_sort_by&lt;/span&gt;
    &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;yield&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sort&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='why_choose_one_over_the_other'&gt;Why choose one over the other?&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;re sorting a small array, it really doesn&amp;#8217;t matter which sort method you choose. Use whichever is easiest to code and understand. For larger arrays, however, the performance differences between &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;sort_by&lt;/code&gt; can be substantial.&lt;/p&gt;

&lt;p&gt;You generally want to use &lt;code&gt;sort_by&lt;/code&gt; over &lt;code&gt;sort&lt;/code&gt; whenever comparisons are relatively expensive. Note that in Ruby, method dispatch is often enough to count as an expensive comparison. Unless you&amp;#8217;re sorting things that end up as C primitives in MRI (like an Integer) you&amp;#8217;ll likely want to use &lt;code&gt;sort_by&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The performance varies so greatly because of the Schwartzian Transform. Using &lt;code&gt;sort&lt;/code&gt;, each pairwise comparison that must be performed calls the &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator. In the case of &lt;code&gt;sort_by&lt;/code&gt;, the comparison &amp;#8220;calculation&amp;#8221; is only done once at the beginning, and then the array is sorted on an Integer primitive much more quickly.&lt;/p&gt;

&lt;p&gt;I hope this was helpful to someone. It&amp;#8217;s probably more than anyone has written on the difference between these two methods.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Walk Like a Duck</title>
   <link href="http://brandon.dimcheff.com/2009/04/07/walk-like-a-duck.html" />
   <updated>2009-04-07T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2009/04/07/walk-like-a-duck</id>
   <content type="html">&lt;h3 id='introduction'&gt;Introduction&lt;/h3&gt;

&lt;p&gt;In a &lt;a href='http://en.wikipedia.org/wiki/Duck_typing'&gt;duck-typed&lt;/a&gt; language like Ruby, it&amp;#8217;s very important that you actually use duck typing. This is especially important when you&amp;#8217;re designing a library or other code that could interact with objects that you don&amp;#8217;t control. I have come across a few libraries lately that don&amp;#8217;t follow duck typing conventions and have caused unexpected behavior when I&amp;#8217;ve used them.&lt;/p&gt;

&lt;p&gt;In this article, I&amp;#8217;m going to pick on &lt;a href='http://www.thoughtbot.com/projects/shoulda/'&gt;Shoulda&lt;/a&gt;. Thoughtbots, please do not take offense! I&amp;#8217;m a fan, and I figured you guys could take it.&lt;/p&gt;

&lt;h3 id='duck_typing'&gt;Duck Typing&lt;/h3&gt;
&lt;span style='margin:0 10px; float:right'&gt;&lt;img src='/images/duck.jpg' height='200' alt='it&amp;apos;s a duck!' width='200' /&gt;&lt;/span&gt;
&lt;p&gt;Before I get into the details, I&amp;#8217;ll say a word or two about duck typing for those who may need a refresher. The principle of duck typing basically says that if something &amp;#8220;walks like a duck and talks like a duck&amp;#8221; it probably is a duck. What this really means is that when you&amp;#8217;re interacting with other objects, you should not care &lt;em&gt;what&lt;/em&gt; they are, but rather &lt;em&gt;how they behave&lt;/em&gt;. If you have an object that responds to &lt;code&gt;#each&lt;/code&gt;, who cares if it&amp;#8217;s an Array or Set or a custom collection?&lt;/p&gt;

&lt;h3 id='implementing_duck_typing'&gt;Implementing Duck Typing&lt;/h3&gt;

&lt;p&gt;You should rarely ever use &lt;code&gt;#is_a?&lt;/code&gt; on an object. You should be using &lt;code&gt;#respond_to?&lt;/code&gt; instead. The whole point in duck typing is that you don&amp;#8217;t &lt;em&gt;care&lt;/em&gt; what kind of object you&amp;#8217;ve received. The only thing you care about is that the object does what you want it to do. Let me show you an example from Shoulda.&lt;/p&gt;

&lt;p&gt;The following code is from &lt;code&gt;lib/shoulda/assertions.rb&lt;/code&gt; in Shoulda&amp;#8217;s &lt;a href='http://github.com/thoughtbot/shoulda/blob/e02228d45a879ff92cb72b84f5fccc6a5f856a65/lib/shoulda/assertions.rb#L23'&gt;git repository&lt;/a&gt;. &lt;code&gt;assert_contains&lt;/code&gt; is a custom assertion for Shoulda that allows you to easily test a collection for the presence of a particular element.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;assert_contains&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;extra_msg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;collection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;is_a?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;msg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;inspect&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; not found in &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;to_a&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;inspect&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;extra_msg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;
  &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='no'&gt;Regexp&lt;/span&gt;
    &lt;span class='n'&gt;assert&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;detect&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=~&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt;         
    &lt;span class='n'&gt;assert&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;include?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you look at the first line of the method definition, you&amp;#8217;ll notice that they are calling &lt;code&gt;is_a?(Array)&lt;/code&gt; on the &amp;#8220;collection&amp;#8221; this is passed into the function. The code I was writing was using a Set instead of an Array. The trouble is, if you pass anything other than an array, that line will wrap whatever you passed in an array. So I ended up with an Array with a Set inside of it, which caused the rest of the assertion code to fail.&lt;/p&gt;

&lt;p&gt;The solution to this problem is very easy. If you look at my &lt;a href='http://github.com/bdimcheff/shoulda/blob/92ebbedd922e46ab2d47f37127d9bd184ae55767/lib/shoulda/assertions.rb#L23'&gt;fork&lt;/a&gt;, all I&amp;#8217;ve done is change that one line (and add some tests, of course). Now we only wrap the collection in an array if it doesn&amp;#8217;t respond to &lt;code&gt;include?&lt;/code&gt;. It&amp;#8217;ll work with an Array still. It&amp;#8217;ll work with a Set. It&amp;#8217;ll work with your custom data structure that can detect the presence of objects. That&amp;#8217;s the power of duck typing.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;assert_contains&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;extra_msg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;collection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;respond_to?&lt;/span&gt; &lt;span class='ss'&gt;:include?&lt;/span&gt;
  &lt;span class='n'&gt;msg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;inspect&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; not found in &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;to_a&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;inspect&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;extra_msg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;
  &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='no'&gt;Regexp&lt;/span&gt;
    &lt;span class='n'&gt;assert&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;detect&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=~&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt;         
    &lt;span class='n'&gt;assert&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;collection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;include?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Whenever you&amp;#8217;re checking for an actual class of an object rather than examining how it behaves, take a second to think if you can duck type it instead. It will make your code more generic, and make it easier for others to use.&lt;/p&gt;

&lt;p&gt;Again, thank you to Thoughtbot for Shoulda and I&amp;#8217;m sorry I singled you out. Shoulda is great, and just happened to be in the wrong place at the wrong time for me to start a rant about duck typing.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Automatically log in on merb-auth account creation</title>
   <link href="http://brandon.dimcheff.com/2009/03/17/automatically-log-in-on-merb-auth-account-creation.html" />
   <updated>2009-03-17T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2009/03/17/automatically-log-in-on-merb-auth-account-creation</id>
   <content type="html">&lt;p&gt;Recently I was adding new user registration to &lt;a href='http://tasteb.in'&gt;tasteb.in&lt;/a&gt; and I wanted my users to be automatically logged in as soon as they created their account. I&amp;#8217;m using merb for tasteb.in, and consequently merb-auth for authentication. It turns out it&amp;#8217;s really easy to implement, but it took me a while to get it right. All you need to do is add the following to your action that creates the new user:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;session&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s it. All you must do is set the user in the session to the newly created user. I hope this saves somebody else some time.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Fix Missing Disqus Comment Form</title>
   <link href="http://brandon.dimcheff.com/2009/03/04/fix-missing-disqus.html" />
   <updated>2009-03-04T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/03/04/fix-missing-disqus</id>
   <content type="html">&lt;p&gt;I had a bit of trouble with Disqus where it would only display a link saying &amp;#8220;Discuss this topic on Disqus&amp;#8221; instead of displaying an actual comment form. It turns out that this problem was caused by a mismatch between the URL configured in Disqus and the url where my blog was actually accessible. So if you&amp;#8217;re missing a Disqus comment form, make sure that the URL listed under Settings -&amp;gt; Website URL in Disqus is the actual URL where your site resides.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>tasteb.in is up!</title>
   <link href="http://brandon.dimcheff.com/2009/03/01/tasteb-in-is-up.html" />
   <updated>2009-03-01T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/03/01/tasteb-in-is-up</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been working on a Merb-based recipe paste site for the past couple weeks called &lt;a href='http://tasteb.in'&gt;tasteb.in&lt;/a&gt;. It&amp;#8217;s extremely simple for now. It lets you paste recipes in a very simple format and they show up on the site. You can access your recipes and all recipes on the site. And that&amp;#8217;s about it.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be going into more details about how tasteb.in is built and where I&amp;#8217;d like to take the site, but for now, just play with it if you like. Drop me a line with any problems you have, or features you would like to see.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Play in the Sandbox</title>
   <link href="http://brandon.dimcheff.com/2009/02/14/play-in-the-sandbox.html" />
   <updated>2009-02-14T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/02/14/play-in-the-sandbox</id>
   <content type="html">&lt;p&gt;I needed to test some code that reads and writes files on the filesystem. I got sick of manually setting up a scratch area for my test files and cleaning them up when I was done, so I created &lt;a href='http://github.com/bdimcheff/sandbox/tree/master'&gt;Sandbox&lt;/a&gt; to keep my tests DRY.&lt;/p&gt;

&lt;p&gt;See the Sandbox readme for more information, but the basic idea is this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# inside a test somewhere&lt;/span&gt;

&lt;span class='no'&gt;Sandbox&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;play&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='no'&gt;FileUtils&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;touch&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;  &lt;span class='c1'&gt;# build a sand castle&lt;/span&gt;

  &lt;span class='n'&gt;assert&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exists?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;  &lt;span class='c1'&gt;# test whatever you want in here&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;assert&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exists?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;  &lt;span class='c1'&gt;# path has been deleted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The project is currently only on &lt;a href='http://github.com/bdimcheff/sandbox/tree/master'&gt;github&lt;/a&gt;, but it will be on RubyForge once approved. If you want to use it now, you have to use the &lt;a href='http://gems.github.com/'&gt;github gems source&lt;/a&gt; or install it from source.&lt;/p&gt;

&lt;h2 id='future_plans'&gt;Future plans&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Optionally &lt;code&gt;Dir.chdir&lt;/code&gt; to the temporary directory for even easier usage&lt;/li&gt;

&lt;li&gt;Supply a template directory/archive to be used for the base state of the sandbox&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>How to learn Ruby</title>
   <link href="http://brandon.dimcheff.com/2009/02/05/how-to-learn-ruby.html" />
   <updated>2009-02-05T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/02/05/how-to-learn-ruby</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 4/20/2010:&lt;/strong&gt; Well Grounded Rubyist is not prerelease anymore. Corrected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 6/30/2011:&lt;/strong&gt; Fix links to _why&amp;#8217;s poignant guide, since he vanished from the earth. Add a bit about finding live people to help you.&lt;/p&gt;

&lt;p&gt;Several people have asked me for tutorials, books, and other resources to help them learn Ruby, so I&amp;#8217;ve attempted to compile a list of resources I feel are particularly valuable for beginning Rubyists. None of these resources are Rails-specific, but being a good Ruby programmer will obviously help you use Rails more effectively. If there is interest, I will compile a similar (and likely longer) list of Rails resources.&lt;/p&gt;

&lt;p&gt;Also, if I&amp;#8217;ve missed anything that helped you learn or teach Ruby, please leave a comment and I will add it to the page. I am especially interested in resources that beginning Rubyists have found useful.&lt;/p&gt;

&lt;p&gt;For these resources, I assume you already have programming experience and are attempting to pick up Ruby to widen your skillset. If you&amp;#8217;re new to programming entirely, check out Chris Pine&amp;#8217;s &lt;a href='http://pine.fm/LearnToProgram/'&gt;Learn to Program&lt;/a&gt; online tutorial.&lt;/p&gt;

&lt;h2 id='the_100_best_way_to_learn_ruby'&gt;The 100% Best Way to Learn Ruby&lt;/h2&gt;

&lt;p&gt;The best way (in my not so humble opinion) to learn Ruby is to find a Ruby expert who is willing to mentor you. Maybe this means tagging along with somebody at work, or pairing with somebody at a &lt;a href='http://startupweekend.org/'&gt;startup weekend&lt;/a&gt;. At our Ruby meetups in Ann Arbor, we occasionally do a Ruby tutorial where people take turns working on a simple problem that is projected up on a board. New rubyists have often found a permanent guide at these sorts of events. The value of having somebody close to you to be able to help is profound. Do this if you can. If you can&amp;#8217;t, or for when you&amp;#8217;re alone, this post has many other non-sentient resources that you can use.&lt;/p&gt;

&lt;h2 id='online_resources'&gt;Online Resources&lt;/h2&gt;

&lt;p&gt;The following is a list of freely available online resources that I&amp;#8217;ve found particularly helpful for new Rubyists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://github.com/edgecase/ruby_koans/tree/master'&gt;Ruby Koans&lt;/a&gt;:&lt;/strong&gt; The newest kid on the block (no pun intended) that&amp;#8217;s taking github by storm is EdgeCase&amp;#8217;s &lt;a href='http://github.com/edgecase/ruby_koans/tree/master'&gt;Ruby Koans&lt;/a&gt;. The &lt;a href='http://en.wikipedia.org/wiki/Koan'&gt;Koans&lt;/a&gt; are essentially a series of failing test cases that you need to figure out how to fix in order to move on to the next step. The best way to learn anything is by doing, and this tutorial will get you programming in no time flat. We use this one at our &amp;#8220;ruby for noobies&amp;#8221; meetings a lot.&lt;/p&gt;

&lt;p&gt;Note that the point in the exercise is &lt;strong&gt;not&lt;/strong&gt; to fix all the tests as fast as possible. In order to get the benefit of this exercise, you must read and understand what the code is showing you. Complete each Koan one by one. Run your tests after each time you change your code.&lt;/p&gt;

&lt;p&gt;I think the best way to use these Koans is to get in a small (2-3 person) group and take turns solving the problems. Discuss what you are doing with each other. Don&amp;#8217;t take anything for granted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://mislav.uniqpath.com/poignant-guide/'&gt;Why&amp;#8217;s Poignant Guide&lt;/a&gt;:&lt;/strong&gt; Why the Lucky Stiff put together an extremely silly tutorial on Ruby. While it may seem a bit campy, it really is a good tutorial. And it&amp;#8217;s a lot of fun! It&amp;#8217;s not nearly as exhaustive as the Koans, but it has more cartoon foxes and chunky bacon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://rubyquiz.com/'&gt;Ruby Quiz&lt;/a&gt;:&lt;/strong&gt; Once you get your feet wet, you might want to check out the Ruby Quiz archives. There are over 150 small programming challenges that you can try to solve using Ruby. Don&amp;#8217;t cheat and look at the answers before you try it for yourself!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://onestepback.org/articles/10things/'&gt;10 Things Every Java Programmer Should Know About Ruby&lt;/a&gt;:&lt;/strong&gt; If you&amp;#8217;re a Java programmer trying to learn ruby, you should check out Jim Weirich&amp;#8217;s 10 things presentation. He goes over many important differences between Java and Ruby, and this can really help you avoid mistakes that many Java programmers make when transitioning to Ruby.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://humblelittlerubybook.com/'&gt;The Humble Little Ruby Book&lt;/a&gt;:&lt;/strong&gt; Jeremy McAnally&amp;#8217;s free introductory online Ruby book. Covers the basics about a lot of stuff that every Ruby programmer needs to know. Also available in print.&lt;/p&gt;

&lt;h2 id='books'&gt;Books&lt;/h2&gt;

&lt;p&gt;The following books are, in my opinion, the best books for aspiring Rubists to check out. None of them are Rails specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://www.amazon.com/gp/product/1430223634/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=itsaruth-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399369&amp;amp;creativeASIN=1430223634'&gt;Beginning Ruby: From Novice to Professional&lt;/a&gt;:&lt;/strong&gt; &lt;a href='http://www.petercooper.co.uk/'&gt;Peter Cooper&lt;/a&gt;&amp;#8217;s Beginning Ruby book has received rave reviews, and is specifically targeted at beginning Rubyists. I&amp;#8217;m a bit ashamed that I didn&amp;#8217;t pick it up on the first pass at this article. Sorry Peter!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://www.amazon.com/gp/product/0974514055?ie=UTF8&amp;amp;tag=itsaruth-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0974514055'&gt;Programming Ruby: The Pragmatic Programmers&amp;#8217; Guide, Second Edition&lt;/a&gt; (aka. The Pickaxe):&lt;/strong&gt; This book has been the gold standard of Ruby books for years, and is a must have for ruby programmers. It has both a descriptive section and a reference section. The 2nd edition is from 2004, however, and does not cover Ruby 1.9 at all. The 3rd edition is available in &lt;a href='http://www.pragprog.com/titles/ruby3/programming-ruby-1-9'&gt;beta&lt;/a&gt;, and the final version will be available in March.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://www.amazon.com/gp/product/0672328844?ie=UTF8&amp;amp;tag=itsaruth-20&amp;amp;link_code=as3&amp;amp;camp=211189&amp;amp;creative=373489&amp;amp;creativeASIN=0672328844'&gt;The Ruby Way&lt;/a&gt;:&lt;/strong&gt; Hal Fulton&amp;#8217;s book is full of solutions to common problems, plus it really helps you learn many of the Ruby idioms that are used by experienced Ruby programmers. Ruby 1.8 only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://www.amazon.com/gp/product/0596516177?ie=UTF8&amp;amp;tag=itsaruth-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596516177'&gt;The Ruby Programming Language&lt;/a&gt;:&lt;/strong&gt; Written by the creator of Ruby himself, this book covers ruby 1.8 and 1.9. It&amp;#8217;s not a tutorial-style book, nor a complete reference, but more of description of the important parts of the Ruby programming language. It&amp;#8217;s a great second book (after the Pickaxe) to help you understand more details about how Ruby works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href='http://www.amazon.com/gp/product/1933988657/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=itsaruth-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399369&amp;amp;creativeASIN=1933988657'&gt;The Well Grounded Rubyist&lt;/a&gt;:&lt;/strong&gt; David Black&amp;#8217;s newest book &lt;em&gt;The Well Grounded Rubyist&lt;/em&gt; is now available in its final edition. It&amp;#8217;s in tutorial form, which is generally good for beginners. I have not had a chance to read it yet, but his last book was great and I hear this one&amp;#8217;s even better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is a work in progress. I will be updating it as new books and tutorials come out. I also don&amp;#8217;t necessarily want an exhaustive list of every ruby resource. I&amp;#8217;m looking for resources that are helpful for beginners. Too many choices may be overwhelming. Also, I haven&amp;#8217;t been a Ruby beginner in a long time, so I am particularly interested in things that recent beginners have found helpful.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Sinatra block parameters!</title>
   <link href="http://brandon.dimcheff.com/2009/02/04/sinatra-block-parameters.html" />
   <updated>2009-02-04T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/02/04/sinatra-block-parameters</id>
   <content type="html">&lt;p&gt;The latest master &lt;a href='http://www.sinatrarb.com/'&gt;Sinatra&lt;/a&gt; now supports optional block parameters. It captures any parameters in the URL and passes them into the block that defines the action:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/hello/:name&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;Hello &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;!&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;params&lt;/code&gt; hash is still available as before, so this should not break any existing applications. It will also work with regular expressions. Any captures are yielded in order:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='sr'&gt;%r{/hello/([\w]+)/([\w]+)}&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;Hello, &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; and &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;!&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Big thanks to &lt;a href='http://tomayko.com'&gt;rtomayko&lt;/a&gt; for accepting my patch, and working with me to get this solid enough to put into Sinatra!&lt;/p&gt;

&lt;p&gt;One final note: this feature behaves slightly differently in ruby 1.8 and 1.9. Ruby 1.9 is much stricter about block arity than 1.8 is. If the number of captures in the URL and the arity of the block do not match, 1.9 will raise an exception. 1.8 will likely just ignore the extra parameters and throw up a warning. If you write code that is compatible with 1.9, it will also work with 1.8, as ruby 1.9 is simply more strict.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Run specs with autotest, er, autospec!</title>
   <link href="http://brandon.dimcheff.com/2009/01/26/run-specs-with-autotest-er-autospec.html" />
   <updated>2009-01-26T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/01/26/run-specs-with-autotest-er-autospec</id>
   <content type="html">&lt;p&gt;It seems that it&amp;#8217;s not well publicized, but if you want to run your RSpec files with &lt;code&gt;autotest&lt;/code&gt; try &lt;code&gt;autospec&lt;/code&gt; instead. It looks inside the spec/ directory for files named &amp;#8220;*_spec.rb&amp;#8221; by default for specs. &lt;code&gt;autospec&lt;/code&gt; is part of the RSpec gem, and basically just sets up the proper environment and then shells out to autotest.&lt;/p&gt;

&lt;p&gt;Also, if your files in lib/ match up with specs in spec/, &lt;code&gt;autospec&lt;/code&gt; will automatically re-run your specs for changed files in lib/ on save. So if you have lib/foo/bar.rb, &lt;code&gt;autospec&lt;/code&gt; will re-run lib/foo/bar_spec.rb when you save bar.rb.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Gearing up for CodeMash</title>
   <link href="http://brandon.dimcheff.com/2009/01/06/gearing-up-for-codemash.html" />
   <updated>2009-01-06T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/01/06/gearing-up-for-codemash</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m getting all packed for CodeMash! Hope too see a lot of you there. I&amp;#8217;m a little bit disappointed by the dearth of Ruby sessions, but there are enough of us that the open sessions will be rockin&amp;#8217;. And the ever popular scotch track always helps.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://codemash.org'&gt;&lt;img src='http://codemash.org/images/badges/attendee1.png' alt='CodeMash' /&gt;&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Commit a linear git history to subversion</title>
   <link href="http://brandon.dimcheff.com/2009/01/04/commit-a-linear-git-history-to-subversion.html" />
   <updated>2009-01-04T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/01/04/commit-a-linear-git-history-to-subversion</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Deskin points out that there is a &lt;a href='http://git.kernel.org/?p=git/git.git;a=commit;h=190f53232d1e92a57843df90e889bcfea39620d3'&gt;commit&lt;/a&gt; to git that fixes this problem by adding a &lt;code&gt;--root&lt;/code&gt; option to &lt;code&gt;rebase --onto&lt;/code&gt;. So when you get a new build of git, you can probably ignore everything here.&lt;/p&gt;

&lt;p&gt;The other day I needed to commit a plain old (git-svn free) git repository to subversion. Why, you ask? I had been working on a small project at work in my own little git repository and needed to get it into our official version control. I could, of course, just commit the latest version that I had, but that would not record any of my git commit history in subversion. I needed a better option. git-svn can save each individual commit of a linear commit history to subversion, so I figured I could just apply git-svn metadata to my repository and go from there.&lt;/p&gt;

&lt;p&gt;This post is a bit long, as I explain the whole process for the solution. If you&amp;#8217;re interested in just the solution, scroll to the bottom.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m going to create a small git repository for illustrative purposes: $ git init Initialized empty Git repository in /Users/bdimchef/testgit/.git/&lt;/p&gt;

&lt;p&gt;For this howto, I&amp;#8217;m using a blank subversion repository, but you can use this method with any subversion repository that has an empty directory to put your new project.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ svnadmin create /Users/bdimchef/testsvn
$ svn mkdir file:///Users/bdimchef/testsvn/trunk
$ svn mkdir file:///Users/bdimchef/testsvn/branches
$ svn mkdir file:///Users/bdimchef/testsvn/tags&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, I added my svn metadata to my git repository and fetched the contents of svn:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git svn init -s file:///Users/bdimchef/testsvn
$ git svn fetch&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I was ready to commit:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git svn dcommit
Can&amp;#39;t call method &amp;quot;full_url&amp;quot; on an undefined value at /opt/local/libexec/git-core/git-svn line 425.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this error means (in our case) is that it can&amp;#8217;t figure out where to dcommit. If we try to rebase, it&amp;#8217;s clearer what the problem is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git svn rebase
Unable to determine upstream SVN information from working tree history&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our problem is that we have two disjoint histories in our git repository: The history that we made in git, and the history from our svn repository. Since they share no common ancestors, git svn can&amp;#8217;t figure out where to commit its changes. Take a look at &lt;code&gt;gitk&lt;/code&gt; to see what&amp;#8217;s going on here.&lt;/p&gt;

&lt;p&gt;It turns out that this problem is pretty easy to fix with &lt;code&gt;svn rebase&lt;/code&gt;. But there is one little trick that will get you if you&amp;#8217;re not careful. And before we get carried away doing too many rebases, lets just make a backup branch of master just in case.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git branch master.bak master&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets try one approach. &lt;code&gt;git rebase --onto A B C&lt;/code&gt; takes the commit range B..C and puts it onto A. In this case, we want to take all our commits and put them on to trunk:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git rebase --onto trunk master~2 master
Applying: added bar
Applying: added baz&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oops! That only applied bar and baz. It forgot about our first commit, foo. Lets go back one more.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git rebase --onto trunk master~3 master
fatal: Needed a single revision
invalid upstream master~3&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that didn&amp;#8217;t work either. The problem is that &lt;code&gt;git rebase --onto&lt;/code&gt; rebases the range beginning &lt;em&gt;after&lt;/em&gt; commit B. In this case, the commit after foo, which is bar. And there is no commit before foo, so there&amp;#8217;s no way to rebase a range starting with foo included. The simple solution to this problem is to &lt;code&gt;git cherry-pick&lt;/code&gt; foo first, then do the rebase. First we&amp;#8217;ll create a named branch for our rebase.&lt;/p&gt;

&lt;h2 id='the_solution'&gt;The Solution&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;$ git co -b svnrebase trunk                    # create a temporary branch
$ git cherry-pick master~2                     # cherry pick the first commit
$ git rebase --onto svnrebase master~2 master  # rebase the 2nd through current commit
$ git svn dcommit                              # finally commit the results to svn&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that worked! So, generally, the secret to joining two separate histories together is to cherry-pick the first commit, and then rebase the rest on top of it.&lt;/p&gt;

&lt;p&gt;Thanks to charon on #git for the cherry-pick idea.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Use Capistrano to set your production database password</title>
   <link href="http://brandon.dimcheff.com/2009/01/03/use-capistrano-to-set-your-production-database-password.html" />
   <updated>2009-01-03T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/01/03/use-capistrano-to-set-your-production-database-password</id>
   <content type="html">&lt;p&gt;This is a Capistrano recipe I use to configure my production database.yml. Before &lt;code&gt;deploy:setup&lt;/code&gt; executes, this recipe will prompt for a database password and save a new database.yml file to the shared directory on your server. After each deploy, the database.yml file will be symlinked from the shared directory. You can reconfigure your database by executing &lt;code&gt;cap db:configure&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are the goods. I&amp;#8217;m pretty sure I got this from &lt;a href='http://archive.jvoorhis.com/articles/2006/07/07/managing-database-yml-with-capistrano'&gt;Jeremy Voorhis&lt;/a&gt; a while back, and modified it to work with Capistrano 2.&lt;/p&gt;
&lt;script src='http://gist.github.com/42755.js' /&gt;</content>
 </entry>
 
 <entry>
   <title>Resolutions</title>
   <link href="http://brandon.dimcheff.com/2009/01/02/resolutions.html" />
   <updated>2009-01-02T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2009/01/02/resolutions</id>
   <content type="html">&lt;p&gt;I generally think that new year resolutions are silly, but since it&amp;#8217;s the new year and I have some goals I&amp;#8217;d like to set, I guess I might as well call them resolutions.&lt;/p&gt;

&lt;p&gt;Since goals, like technical requirements, are meaningless if you can&amp;#8217;t measure them, I&amp;#8217;ll be as specific as possible even if it means that I&amp;#8217;ll have to adjust them later. So here we go:&lt;/p&gt;

&lt;p&gt;Resolved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I will blog at least once a week. Corollary: I will blog within one day of saying to myself &amp;#8220;Hey, I should blog about this&amp;#8221;&lt;/li&gt;

&lt;li&gt;I will contribute a patch to an open source project at least once a month&lt;/li&gt;

&lt;li&gt;I will start a useful open source project by April&lt;/li&gt;

&lt;li&gt;I will write my blog from scratch by July so I can do it just the way I want&lt;/li&gt;

&lt;li&gt;I will do &lt;a href='http://photojojo.com/content/tutorials/project-365-take-a-photo-a-day/'&gt;Project 365&lt;/a&gt;. Seriously this time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and perhaps most importantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I will have my next form of gainful employment arranged by January 23rd.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog post does not count towards resolution #1, and I&amp;#8217;ve got a decent backlog of items to write about, so you&amp;#8217;ll be hearing from me soon.&lt;/p&gt;

&lt;p&gt;Happy new year!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Ruby Hoedown Videos Online</title>
   <link href="http://brandon.dimcheff.com/2008/08/22/ruby-hoedown-videos-online.html" />
   <updated>2008-08-22T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2008/08/22/ruby-hoedown-videos-online</id>
   <content type="html">&lt;p&gt;Ruby Hoedown 2008 &lt;a href='http://rubyhoedown2008.confreaks.com/'&gt;videos&lt;/a&gt; are now live. There are a lot of good talks. I highly recommend checking them out. I&amp;#8217;ve set up a &lt;a href='http://thepiratebay.org/torrent/4355220'&gt;torrent&lt;/a&gt; of all the videos for your convenience.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Make RubyMate work with MacPorts Ruby</title>
   <link href="http://brandon.dimcheff.com/2008/06/18/make-rubymate-work-with-macports-ruby.html" />
   <updated>2008-06-18T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2008/06/18/make-rubymate-work-with-macports-ruby</id>
   <content type="html">&lt;p&gt;To make TextMate&amp;#8217;s RubyMate work with MacPorts (or any other non-default ruby install) just set TM_RUBY environment variable to be the path to your custom ruby interpreter in TextMate&amp;#8217;s preferences. Custom environmental variable settings are located under &amp;#8216;Advanced&amp;#8217;-&amp;gt;&amp;#8217;Shell Variables&amp;#8217; in TM&amp;#8217;s prefs.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Fix empty sake tasks</title>
   <link href="http://brandon.dimcheff.com/2008/02/10/fix-empty-sake-tasks.html" />
   <updated>2008-02-10T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2008/02/10/fix-empty-sake-tasks</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve had a problem with my &lt;a href='http://errtheblog.com/posts/60-sake-bomb'&gt;sake&lt;/a&gt; tasks being blank for the past couple days. Since there were a couple comments on err about similar things, I&amp;#8217;ll share my fix: &lt;code&gt;gem install -v 2.0.1 ParseTree&lt;/code&gt;. That&amp;#8217;s it. Turns out my ParseTree install was messed up and to_ruby was not working on the task blocks.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Rails 2.0 is out</title>
   <link href="http://brandon.dimcheff.com/2007/12/07/rails-2-0-is-out.html" />
   <updated>2007-12-07T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2007/12/07/rails-2-0-is-out</id>
   <content type="html">&lt;p&gt;&lt;a href='http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done'&gt;Rails 2.0&lt;/a&gt; has been released. Check it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Using other MySQL Storage Engines</title>
   <link href="http://brandon.dimcheff.com/2007/12/03/using-other-mysql-storage-engines.html" />
   <updated>2007-12-03T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2007/12/03/using-other-mysql-storage-engines</id>
   <content type="html">&lt;p&gt;Try &lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;create_table&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:suppliers&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:options&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;ENGINE=InnoDB DEFAULT CHARSET=utf8&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt; if you need to make a table with a different storage engine than default on MySQL. Note that this will bind your migration to MySQL, as it simply appends whatever is in the &lt;code&gt;:options&lt;/code&gt; string to the end of the &lt;code&gt;CREATE_TABLE&lt;/code&gt; generated by the migration.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>RubyInject</title>
   <link href="http://brandon.dimcheff.com/2007/11/27/rubyinject.html" />
   <updated>2007-11-27T00:00:00-05:00</updated>
   <id>http://brandon.dimcheff.com/2007/11/27/rubyinject</id>
   <content type="html">&lt;p&gt;&lt;a href='http://rubycocoa.sourceforge.net/RubyInject'&gt;RubyInject&lt;/a&gt; is a small library from the folks who brought you RubyCocoa. It allows you to inject a ruby interpreter into a Cocoa app and tinker with all its&amp;#8217; internals.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>shoulda</title>
   <link href="http://brandon.dimcheff.com/2007/09/29/shoulda.html" />
   <updated>2007-09-29T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/29/shoulda</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m trying out &lt;a href='http://thoughtbot.com/projects/shoulda'&gt;shoulda&lt;/a&gt;, a testing framework written by the guys over at Thoughtbot.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Test behavior, not implementation!</title>
   <link href="http://brandon.dimcheff.com/2007/09/21/test-behavior-not-implementation.html" />
   <updated>2007-09-21T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/21/test-behavior-not-implementation</id>
   <content type="html">&lt;p&gt;This is a based on a comment I made on a &lt;a href='http://giantrobots.thoughtbot.com/2007/9/19/ruby-on-rails-testing-strategies'&gt;post&lt;/a&gt; on thoughtbot&amp;#8217;s blog. I suggest you read the original post for some background on what I&amp;#8217;m talking about.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re too lazy to read, here&amp;#8217;s the basic gist: You could potentially test your associations or plugins (such as acts_as_solr) by simply checking whether or not your object responds to the messages that the plugins generate when their class methods are called.&lt;/p&gt;

&lt;p&gt;The problem is, we should be trying to test &lt;em&gt;behavior&lt;/em&gt;, not simply whether or not acts_as_solr or has_many are being called. The problem with the approach described above is that it assumes too much about implementation details and doesn&amp;#8217;t actually make sure your app is doing what it&amp;#8217;s supposed to be doing.&lt;/p&gt;

&lt;p&gt;In this case, I think that find_by_solr should be called find_by_content or something, since it doesn&amp;#8217;t really matter that it&amp;#8217;s solr that&amp;#8217;s doing the lookup. All the developer using the API cares about is that when they pass a particular query into the method, the proper results are returned. And that is what our tests should test.&lt;/p&gt;

&lt;p&gt;I am not convinced that (as many test/rspec examples show) simply checking for association methods (has_many, belongs_to, etc.) or plugin methods (acts_as_solr) are sufficient, or even a good idea at all. Nor do I think that those sorts of tests qualify as BDD. For instance, I have something resembling the following in an application per someone&amp;#8217;s suggestion:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reflect_on_association&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:addresses&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should_not&lt;/span&gt; &lt;span class='n'&gt;be_nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I really don&amp;#8217;t like this, though. I don&amp;#8217;t care one bit that there&amp;#8217;s an association called &amp;#8220;addresses&amp;#8221; on my Person object. What I care about is that Person responds to addresses and that addresses returns an array of the &lt;em&gt;proper&lt;/em&gt; addresses. This is the whole point in BDD. Care about the behavior of your objects, not their implementation.&lt;/p&gt;

&lt;p&gt;To explore this further, I&amp;#8217;ll use a slightly more complicated example. Say I have the following in my Person class:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# app/models/person.rb&lt;/span&gt;
&lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:addresses&lt;/span&gt;
&lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:cool_addresses&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:foreign_key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;address_id&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:conditions&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;foo = ? AND bar = ?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;foo&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;bar&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:order&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:zipcode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the corresponding test case:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reflect_on_association&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:cool_addresses&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should_not&lt;/span&gt; &lt;span class='n'&gt;be_nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Well, guess what. This association exists. Our tests pass. But it&amp;#8217;s &lt;em&gt;wrong&lt;/em&gt;. That :foreign_key is supposed to be person_id and not address_id. Well, we can solve that! Just test to make sure the has_many receives the appropriate parameters. Something like this (made up) helper would work:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reflect_on_association&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:cool_addresses&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_foreign_key&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;person_id&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And we could go about our business, basically duplicating all the parameters supplied to has_many in our tests. But in the end, this is just going to make our tests horribly brittle and is not actually testing anything useful. It&amp;#8217;s not testing behavior &lt;em&gt;at all&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The whole point in BDD is to make our tests poke and prod our application in a certain way and have them spit back the correct output. Yes, the plugins/associations are well tested and I shouldn&amp;#8217;t be testing them again. I know that if my has_many call supplies the correct parameters, I will get the objects I expect to get. But I still need to make sure that I&amp;#8217;m calling has_many properly. It&amp;#8217;s simply not sufficient for me to know &lt;em&gt;that&lt;/em&gt; has_many is called, I need to know that &lt;em&gt;when&lt;/em&gt; it&amp;#8217;s called, the proper &amp;#8220;stuff&amp;#8221; happens. I need to make sure the association does what I expect it to do. Here&amp;#8217;s what I think my tests should do to ensure cool_addresses is working properly (no real code this time):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a few objects to the Addresses table, either using fixtures or in some kind of before callback. (Yes, fixtures suck, etc.)&lt;/li&gt;

&lt;li&gt;Make sure cool_addresses returns addresses that correspond to the &amp;#8216;foo&amp;#8217; and &amp;#8216;bar&amp;#8217; conditions above.&lt;/li&gt;

&lt;li&gt;Make sure that cool_addresses returns the addresses ordered by zipcode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that&amp;#8217;s it. Yes, it will take the tests slightly longer to run, since they&amp;#8217;re using the database (and maybe fixtures). Yes, I&amp;#8217;m partially testing ActiveRecord. But I&amp;#8217;m testing that my object &lt;em&gt;behaves&lt;/em&gt; like I want it to. That&amp;#8217;s the point in BDD, right?&lt;/p&gt;

&lt;p&gt;As an added benefit, the tests are &lt;em&gt;much&lt;/em&gt; more flexible now. Check it out:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# app/models/person.rb&lt;/span&gt;
&lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:addresses&lt;/span&gt;
&lt;span class='c1'&gt;#has_many :cool_addresses, :foreign_key =&amp;gt; &amp;quot;address_id&amp;quot;, :conditions =&amp;gt; [&amp;quot;foo = ? AND bar = ?&amp;quot;, foo, bar], :order =&amp;gt; :zipcode&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;cool_addresses&lt;/span&gt;
  &lt;span class='n'&gt;addresses&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_all&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foo&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;foo&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bar&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;bar&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sort&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='ss'&gt;:zipcode&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That passes my tests, too. And it should. But my previous example where I used association introspection would fail miserably.&lt;/p&gt;

&lt;p&gt;This is a major complaint about a lot of the test code examples I see floating around. Everybody seems to be mocking and stubbing and introspecting to their heart&amp;#8217;s content, but all they seem to be doing in the end is writing the same code twice: once in their implementation, and once in their tests. And so when they change the way their application is implemented (NOTE: I did &lt;em&gt;not&lt;/em&gt; say their application&amp;#8217;s behavior) their tests break.&lt;/p&gt;

&lt;p&gt;There are two sides to this BDD thing. First, your tests need to ensure that if you change the behavior of your code, they will fail. Second, your tests need to still work when your application still behaves the right way, even if you change every single line of code in your application. Of course, this is nearly impossible to achieve, but at least we can try.&lt;/p&gt;

&lt;p&gt;Thoughts?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>I can has patch?</title>
   <link href="http://brandon.dimcheff.com/2007/09/18/i-can-has-patch.html" />
   <updated>2007-09-18T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/18/i-can-has-patch</id>
   <content type="html">&lt;p&gt;I was poking through svn for &lt;a href='http://blog.evanweaver.com/files/doc/fauna/has_many_polymorphs/files/README.html'&gt;has_many_polymorphs&lt;/a&gt; to see if a bug that I found had been fixed. Lo and behold, it was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;r688 | evanweaver | 2007-08-29 03:49:55 -0400 (Wed, 29 Aug 2007) | 2 lines&lt;/p&gt;

&lt;p&gt;fix singularize bug in autoloader (Brandon Dimcheff)&lt;/p&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>Caboose Sample App</title>
   <link href="http://brandon.dimcheff.com/2007/09/10/caboose-sample-app.html" />
   <updated>2007-09-10T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/10/caboose-sample-app</id>
   <content type="html">&lt;p&gt;The &lt;a href='http://sample.caboo.se/'&gt;Caboose sample app&lt;/a&gt; comes with user authentication and many other useful features baked in. It&amp;#8217;s a great starting place for your new Rails app!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Railsify</title>
   <link href="http://brandon.dimcheff.com/2007/09/07/railsify.html" />
   <updated>2007-09-07T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/07/railsify</id>
   <content type="html">&lt;p&gt;A new Rails plugin repository has been launched: &lt;a href='http://railsify.com/'&gt;Railsify&lt;/a&gt;. Check it out.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Massive list of Rails development tips from Peepcode</title>
   <link href="http://brandon.dimcheff.com/2007/09/07/massive-list-of-rails-development-tips-from-peepcode.html" />
   <updated>2007-09-07T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/09/07/massive-list-of-rails-development-tips-from-peepcode</id>
   <content type="html">&lt;p&gt;The &lt;a href='http://peepcode'&gt;Peepcode&lt;/a&gt; people have published a long list of Rails development tips: &lt;a href='http://nubyonrails.com/articles/massive-list-of-rails-development-tips'&gt;Tips!&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Predefined models?  No different than any others.</title>
   <link href="http://brandon.dimcheff.com/2007/08/31/predefined-models-no-different-than-any-others.html" />
   <updated>2007-08-31T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/08/31/predefined-models-no-different-than-any-others</id>
   <content type="html">&lt;p&gt;Earlier today I was trying to figure out how to make a list of potential models to be created. For example: I have some &lt;code&gt;User&lt;/code&gt;s and some &lt;code&gt;Group&lt;/code&gt;s. I have a many-to-many &lt;code&gt;Membership&lt;/code&gt; join model with some &lt;code&gt;has_many :through&lt;/code&gt;s. The fundamental goal is to provide the user an interface to add Membership models that link a &lt;code&gt;User&lt;/code&gt; to a &lt;code&gt;Group&lt;/code&gt;. I &lt;em&gt;could&lt;/em&gt; use a bunch of checkboxes, but I&amp;#8217;d rather pull up a list of possible &lt;code&gt;Group&lt;/code&gt;s with little &amp;#8220;add&amp;#8221; links next to them.&lt;/p&gt;

&lt;p&gt;Since I&amp;#8217;m using RESTful controllers, we have a &lt;code&gt;MembershipsController&lt;/code&gt; that implements all the standard methods. We&amp;#8217;re also nesting our routes such that &lt;code&gt;MembershipsController&lt;/code&gt; nested beneath the &lt;code&gt;UsersController&lt;/code&gt;. In order to create the Membership, we need to POST to /users/1/memberships. But how do we get a list of &lt;code&gt;Membership&lt;/code&gt;s that we can quickly add?&lt;/p&gt;

&lt;p&gt;How about modifying &lt;code&gt;MembershipsController.new&lt;/code&gt;? We don&amp;#8217;t need the normal definition of &lt;code&gt;new&lt;/code&gt;, since we&amp;#8217;re never going to be manually creating a new Membership.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# controllers/memberships_controller.rb&lt;/span&gt;
&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
  &lt;span class='vi'&gt;@memberships&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Groups&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:all&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;collect&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;group&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='no'&gt;Membership&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:user_id&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user_id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:group_id&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;group&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we have a list of potential &lt;code&gt;Membership&lt;/code&gt; objects available to our view. Remember, the &lt;code&gt;Membership&lt;/code&gt;s haven&amp;#8217;t been saved yet. They&amp;#8217;re just there for convenience for holding attributes. We are doing object-oriented programming after all.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='rhtml'&gt;# views/memberships/new.html.erb
&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='vi'&gt;@memberships&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;membership&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
	&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='ss'&gt;:membership&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;membership&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;memberships_path&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
		&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;hidden_field&lt;/span&gt; &lt;span class='ss'&gt;:user_id&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
		&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;hidden_field&lt;/span&gt; &lt;span class='ss'&gt;:group_id&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
		&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='n'&gt;membership&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;group&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
	&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Basically what we have here is a big list of predefined join models wrapped up in form tags. When you click on one of them, you&amp;#8217;ll end up submitting the form that actually creates the model. Eventually, we could make this into an AJAX widget that uses &lt;code&gt;form_remote_for&lt;/code&gt; with very little effort.&lt;/p&gt;

&lt;p&gt;Nothing I have described here is particularly revolutionary. Rather than just returning a single new &lt;code&gt;Membership&lt;/code&gt; in the &lt;code&gt;new&lt;/code&gt; method, we return a list of objects. Rather than rendering one form with editable fields, we render multiple forms with predefined, hidden fields. Whichever you submit creates the corresponding object. These two very simple changes to the standard REST actions allow us to easily and elegantly create our join models.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Installing a Rails stack on Mac OS X with MacPorts</title>
   <link href="http://brandon.dimcheff.com/2007/08/28/installing-a-rails-stack-on-mac-os-x-with-macports.html" />
   <updated>2007-08-28T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/08/28/installing-a-rails-stack-on-mac-os-x-with-macports</id>
   <content type="html">&lt;p&gt;I have a clean install of OS X on which I need to install Rails. I&amp;#8217;ve done this maybe 3 or 4 times in the past year with minor variations each time which inevitably come back to bite me later. This post is an effort to document and standardize all the details to get a Rails stack going with MacPorts.&lt;/p&gt;

&lt;h2 id='installing_xcode_tools'&gt;Installing Xcode Tools&lt;/h2&gt;

&lt;p&gt;You need the latest version of &lt;a href='http://developer.apple.com/tools/xcode/'&gt;Xcode tools&lt;/a&gt; to be able to compile all the packages necessary for Ruby and Rails. They&amp;#8217;re a free download from Apple.&lt;/p&gt;

&lt;h2 id='installing_macports'&gt;Installing MacPorts&lt;/h2&gt;

&lt;p&gt;First thing&amp;#8217;s first: Install &lt;a href='http://trac.macosforge.org/projects/macports/wiki/InstallingMacPorts'&gt;MacPorts&lt;/a&gt;! Be sure to follow the directions closely. Especially the bit about setting your &lt;code&gt;PATH&lt;/code&gt; appropriately. The /opt paths must be before your standard path so when you type &lt;code&gt;ruby&lt;/code&gt;, you use the ruby interpreter from MacPorts rather than the old one that came with OS X.&lt;/p&gt;

&lt;h2 id='installing_rails_prerequisites_with_macports'&gt;Installing Rails Prerequisites with MacPorts&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install mysql5 +server
$ sudo port install ruby
$ sudo port install rb-rubygems
$ sudo port install rb-mysql
$ sudo port install rb-termios
$ sudo port install subversion +tools&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='configure_mysql'&gt;Configure MySQL&lt;/h2&gt;

&lt;p&gt;First, add &lt;code&gt;/opt/local/lib/mysql5/bin/&lt;/code&gt; to your &lt;code&gt;PATH&lt;/code&gt; as you did in the instructions to install MacPorts.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo mysql_install_db5 --user=mysql&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='install_gems'&gt;Install Gems&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;$ sudo gem install -y rake
$ sudo gem install -y rails
$ sudo gem install -y capistrano
$ sudo gem install -y mongrel
$ sudo gem install -y mongrel_cluster
$ sudo gem install -y piston&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='install_optional_packages'&gt;Install Optional Packages&lt;/h2&gt;

&lt;p&gt;The above ports and gems are the minimum you&amp;#8217;ll need to get rails running successfully. The ones below, while not required, are often useful when developing rails apps.&lt;/p&gt;

&lt;h3 id='other_databases'&gt;Other Databases&lt;/h3&gt;

&lt;p&gt;Try postgres or sqlite3 for some database variety (&lt;code&gt;port install postgresql82-server &amp;amp;&amp;amp; port install rb-postgres&lt;/code&gt; or &lt;code&gt;port install rb-sqlite3&lt;/code&gt;, respectively).&lt;/p&gt;

&lt;h3 id='testing'&gt;Testing&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://rspec.rubyforge.org/'&gt;RSpec&lt;/a&gt; - a powerful &lt;a href='http://en.wikipedia.org/wiki/Behavior_driven_development'&gt;BDD&lt;/a&gt; framework&lt;/li&gt;

&lt;li&gt;&lt;a href='http://flexmock.rubyforge.org/'&gt;Flexmock&lt;/a&gt; and/or &lt;a href='http://mocha.rubyforge.org/'&gt;Mocha&lt;/a&gt; - for mocking/stubbing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='misc'&gt;Misc&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://tzinfo.rubyforge.org/'&gt;tzinfo&lt;/a&gt; - Time Zone handling&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>First Post</title>
   <link href="http://brandon.dimcheff.com/2007/08/27/first-post.html" />
   <updated>2007-08-27T00:00:00-04:00</updated>
   <id>http://brandon.dimcheff.com/2007/08/27/first-post</id>
   <content type="html">&lt;p&gt;After 9 months of trying to get a Ruby blog launched, I finally have succeeded. And now it&amp;#8217;s late, so I&amp;#8217;m going to bed. But check back soon for juicy Ruby and Rails tidbits.&lt;/p&gt;

&lt;p&gt;No, tags don&amp;#8217;t quite work yet. It&amp;#8217;s Heminway&amp;#8217;s fault. I&amp;#8217;m fixing it and I&amp;#8217;ll release my changes.&lt;/p&gt;</content>
 </entry>
 
 
</feed>
