<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Todd Huss &#187; Ruby</title>
	<atom:link href="http://gabrito.com/post/category/technical/ruby/feed" rel="self" type="application/rss+xml" />
	<link>http://gabrito.com</link>
	<description>Anecdotes on Technology Leadership, Ruby, Java, Scala, Cloud Computing, Open-Source, SEO, and Design</description>
	<lastBuildDate>Thu, 08 Dec 2011 00:21:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Acceptance Testing non Ruby web applications with Cucumber</title>
		<link>http://gabrito.com/post/acceptance-testing-non-ruby-apps-with-cucumber</link>
		<comments>http://gabrito.com/post/acceptance-testing-non-ruby-apps-with-cucumber#comments</comments>
		<pubDate>Tue, 26 Oct 2010 21:49:18 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Quality Assurance]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://gabrito.com/?p=318</guid>
		<description><![CDATA[If you&#8217;re looking for the sample Standalone Cucumber Test Suite to get you started testing non Ruby based applications with Cucumber, here&#8217;s the source: http://github.com/thuss/standalone-cucumber. Sometimes you inherit a non Ruby based web app written in PHP, Perl, Java, C#, &#8230; <a href="http://gabrito.com/post/acceptance-testing-non-ruby-apps-with-cucumber">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://gabrito.com/wp-content/uploads/2010/10/cucumber-logo.png"><img src="http://gabrito.com/wp-content/uploads/2010/10/cucumber-logo.png" alt="" title="cucumber-logo" width="300" height="128" class="alignleft size-full wp-image-321" /></a>If you&#8217;re looking for the sample <a href="http://github.com/thuss/standalone-cucumber">Standalone Cucumber Test Suite</a> to get you started testing non Ruby based applications with Cucumber, here&#8217;s the source: <a href="http://github.com/thuss/standalone-cucumber">http://github.com/thuss/standalone-cucumber</a>.</p>
<p>Sometimes you inherit a non Ruby based web app written in PHP, Perl, Java, C#, or Python and you want to create an automated functional/acceptance test suite to minimize the amount of manual QA you need to do.<span id="more-318"></span> <a href="http://seleniumhq.org/">Selenium</a> is a great tool for doing just that and at <a href="http://www.commonsensemedia.org">Common Sense Media</a> I created the <a href="http://github.com/thuss/selenium-continuous-integration-runner">Selenium Continuous Integration Runner</a> to make it easy to run <a href="http://seleniumhq.org/docs/04_selenese_commands.html">Selenese</a> based tests from your <a href="http://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration</a> Server such as Hudson, Cruise Control, or Teamcity. That said, Selenese based tests leave something to be desired in terms of readability and maintainability. </p>
<p>The <a href="http://www.ruby-lang.org/en/">Ruby</a> camp is often at the forefront of great testing frameworks with <a href="http://github.com/aslakhellesoy">Aslak Hellesøy</a> often leading the charge with innovations like <a href="http://rspec.info/">RSpec</a> and <a href="http://cukes.info/">Cucumber</a>. I&#8217;d read and played around with Cucumber on Rails based apps and was loving the concept of english language specs that are actually executable as well. But when my friend and former colleague Chris Kimm mentioned that the testing group at his company was using it to test their Java application, I started to get excited as that was the problem I was about to try and tackle at <a href="http://www.volunteermatch.org">VolunteerMatch</a>.</p>
<p>However, getting the project structure in place required a little help from the <a href="http://groups.google.com/group/cukes">Cucumber mailing list</a> and in the hopes of saving others the time, I&#8217;ve published the <a href="http://github.com/thuss/standalone-cucumber">Standalone Cucumber Test Suite</a> to  Github. It&#8217;s simply a Cucumber project designed to test a non Ruby web application with a sample search.feature that uses Google search as the basis for the test. It uses <a href="http://github.com/jnicklas/capybara">Capybara</a> with the <a href="http://seleniumhq.org/docs/09_webdriver.html">Selenium Webdriver</a> on the backend but you can also switch it to use <a href="http://github.com/langalex/culerity">Culerity</a> or <a href="http://github.com/brynary/webrat">Webrat</a> if you don&#8217;t want it actually firing up a real browser to run the tests.  Fork it or download it to start testing your existing website with Cucumber!</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/acceptance-testing-non-ruby-apps-with-cucumber/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Code readability through conciseness</title>
		<link>http://gabrito.com/post/code-readability-through-conciseness</link>
		<comments>http://gabrito.com/post/code-readability-through-conciseness#comments</comments>
		<pubDate>Tue, 10 Aug 2010 22:06:51 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://gabrito.com/?p=286</guid>
		<description><![CDATA[One of the things I love about newer languages like Ruby and Scala (and to a degree Python and Groovy) are the language features that allow you to dial conciseness up or down for readability. Take for instance the typical &#8230; <a href="http://gabrito.com/post/code-readability-through-conciseness">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://gabrito.com/wp-content/uploads/2010/08/lambda.jpeg" alt="" title="lambda" width="72" height="80" class="alignleft size-full wp-image-287" />One of the things I love about newer languages like  Ruby and Scala (and to a degree Python and Groovy) are the language features that allow you to dial conciseness up or down for readability. Take for instance the typical one liner for summing numbers in languages that support anonymous functions (which can be a bit cryptic in terms of readability):</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Ruby<br />
sum = [1,2,3,4].inject(0) {|result, value| result + value}<br />
Scala<br />
val sum = Array(1,2,3,4).foldLeft(0) ((result, value) =&gt; result + value)<br />
Groovy<br />
sum = [1,2,3,4].inject(0) { result, value -&gt; result + value }<br />
Python<br />
sum = reduce(lambda result, value: result + value, [1,2,3,4])</div></div>
<p>One of the jobs of a good programmer<span id="more-286"></span> is to make their code readable and in this case by naming the variable sum it&#8217;s obvious what&#8217;s going on to the right so if you can simplify the anonymous function or use syntactic sugar to reduce the amount of code there&#8217;s a good chance you can improve the readability as follows:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Ruby<br />
sum = [1,2,3,4].inject(:+)<br />
Scala can either reduce the anonymous function<br />
val sum = Array(1,2,3,4).reduceLeft(_+_)<br />
or in Scala 2.8 they added the sum method<br />
val sum = Array(1,2,3,4).sum<br />
Groovy can't reduce the anonymous function but has a sum method<br />
sum = [1,2,3,4].sum<br />
Python can't reduce the anonymous function but has a sum function<br />
sum = sum([1,2,3,4])</div></div>
<p>Then even if the programmer reading the code is coming from another language and doesn&#8217;t know :+ or _+_ you&#8217;ll still have improved readability because they certainly understand how a sum is computed and can move past the line of code instead of having to read 3-4 lines of a for loop for something as simple as a summing operation. I love the balance of being very concise with the simple stuff so that I can be more verbose with the complex stuff, whereas in Java even the simple stuff is often extremely verbose.</p>
<p>There is of course the extreme of making your code too concise. Look no further than <a target="_blank" href="http://en.wikipedia.org/wiki/Write-only_language">write-only languages</a> like Perl to see where too much conciseness and obfuscation can lead to unmaintainable code.</p>
<p>This example is only trivial and somewhat contrived but I find that newer languages like Ruby and Scala give you significantly better tools to elegantly dial up or down the conciseness than Java or C# resulting in <em>less code + more readable code = easily maintainable code</em>.</p>
<p>As an example, I used just about every conciseness trick in the book I knew of when composing <a target="_blank" href="http://github.com/thuss/rpcfn-3-shortest_path">my submission</a> for the <a target="_blank" href="http://rubylearning.com/blog/2009/10/30/rpcfn-short-circuit-3/">3rd Ruby Challenge&#8217;s Shortest Path Algorithm</a> and I only discarded the ones that I thought obfuscated the intent. I like to think the reason my submission won was precisely because it was concise while still being readable. Writing that same algorithm with the same level of readability in Scala would be easy but in Java it would have tripled the lines of code hurting readability somewhat.</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/code-readability-through-conciseness/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Standalone Migrations: Using Rails migrations in non Rails projects</title>
		<link>http://gabrito.com/post/standalone-migrations-using-rails-migrations-in-non-rails-projects</link>
		<comments>http://gabrito.com/post/standalone-migrations-using-rails-migrations-in-non-rails-projects#comments</comments>
		<pubDate>Tue, 23 Dec 2008 01:15:47 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://gabrito.com/?p=194</guid>
		<description><![CDATA[Update 8/7/2010: Standalone migrations is now a gem (sudo gem install standalone_migrations) so disregard the outdated installation instructions below Update 7/8/2009: With the latest batch of contributed patches standalone migrations now works just like Rails migrations Update 12/26/2008: I switched &#8230; <a href="http://gabrito.com/post/standalone-migrations-using-rails-migrations-in-non-rails-projects">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/thuss/standalone-migrations/tree/master"><img src="http://gabrito.com/wp-content/uploads/2008/12/github.png" alt="Standalone Migrations" title="Standalone Migrations" width="157" height="60" class="alignleft" /></a><strong>Update 8/7/2010</strong>: Standalone migrations is now a gem (sudo gem install standalone_migrations) so disregard the outdated installation instructions below</p>
<p><strong>Update 7/8/2009</strong>: With the latest batch of contributed patches standalone migrations now works just like Rails migrations<br />
<strong>Update 12/26/2008</strong>: I switched standalone migrations to use a Rakefile instead of a Ruby script.</p>
<p>In my work managing websites I end up working in Ruby, Java, and PHP. In everything but Rails managing the schema requires rolling your own solution. As a result I&#8217;ve started using Rails migrations in non-Rails projects to manage the schema. It&#8217;s not much code but I figured others might benefit from it so I created a little Github project called <a target="_blank" href="http://github.com/thuss/standalone-migrations/tree/master">standalone migrations</a>. </p>
<p>It&#8217;s based on Lincoln Stoll&#8217;s blog post titled <a target="_blank" href="http://lstoll.net/2008/04/stand-alone-activerecord-migrations/">Stand-alone ActiveRecord migrations</a> and David Welton&#8217;s blog post titled <a target="_blank" href="http://journal.dedasys.com/2007/01/28/using-migrations-outside-of-rails">Using Migrations Outside of Rails</a>.</p>
<p>Assuming you have Ruby and Gem installed on your machine, here&#8217;s how to use it:</p>
<pre>
gem install -y activerecord rake mysql
wget http://github.com/thuss/standalone-migrations/zipball/master (or fetch it using <a target="_blank" href="http://git.or.cz/">git</a>)
unzip it, and mv to something like my_non_rails_project/db
cd my_non_rails_project/db/ (or wherever you put it)
cp config/database_sample.yml config/database.yml
vi config/database.yml
./new_migration some_user_story
vi migrations/*_some_user_story.rb
rake db:migrate (this applies your newly created migration)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/standalone-migrations-using-rails-migrations-in-non-rails-projects/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Search Engine Friendly URLs with Ruby on Rails</title>
		<link>http://gabrito.com/post/search-engine-friendly-urls-in-rails</link>
		<comments>http://gabrito.com/post/search-engine-friendly-urls-in-rails#comments</comments>
		<pubDate>Mon, 05 Feb 2007 04:58:53 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Search Engine Optimization]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/search-engine-friendly-urls-in-rails</guid>
		<description><![CDATA[Update 2/5/07: I&#8217;ve since discovered five plugins that address this very problem with slightly different approaches (the latter two store a permalink in the table, good for mutable titles): acts_as_sluggable acts_as_urlnameable acts_as_slugable acts_as_friendly_param permalink_fu Obie&#8217;s recent post on search engine &#8230; <a href="http://gabrito.com/post/search-engine-friendly-urls-in-rails">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2/5/07</strong>: I&#8217;ve since discovered five plugins that address this very problem with slightly different approaches (the latter two store a permalink in the table, good for mutable titles):</p>
<ul>
<li><a href="http://tore.darell.no/pages/5-acts-as-sluggable">acts_as_sluggable</a></li>
<li><a href="http://gabriel.gironda.org/articles/2006/03/09/acts_as_urlnameable-released">acts_as_urlnameable</a></li>
<li><a href="http://multi-up.ca/code/">acts_as_slugable</a></li>
<li><a href="http://www.chrisfarms.com/2007/2/11/seo-friendly-urls-in-rails">acts_as_friendly_param</a></li>
<li><a href="http://mephistoblog.com/2007/1/14/improved-url-escaping-for-permalinks">permalink_fu</a>
</ul>
<p><a href="http://www.jroller.com/page/obie?entry=seo_optimization_of_urls_in">Obie&#8217;s recent post on search engine friendly URL&#8217;s in Ruby on Rails 1.2 and greater</a> couldn&#8217;t have been more timely. I was about to tackle search engine friendly URL&#8217;s on my little local <a href="http://gearandboats.com/">san francisco bay area boating classifieds</a> site and after reading his blog post, 15 minutes later it was done. Here&#8217;s the old URL structure:<br />
<span id="more-172"></span><br />
<a href="http://gearandboats.com/forums/1/topics/51">http://gearandboats.com/forums/1/topics/51</a></p>
<p>and the new (longer for humans but much better for SEO):</p>
<p><a href="http://gearandboats.com/forums/1-boats/topics/51-fantasia-35-mark-ii-cruiser">http://gearandboats.com/forums/1-boats/topics/51-fantasia-35-mark-ii-cruiser</a></p>
<p>The most important thing is that the URL&#8217;s are backwards compatible because everything after the ID is ignored which is key for pages that are already in the search engines!</p>
<p><!--adsense--></p>
<p>To achieve this I combined <a href="http://www.jroller.com/page/obie?entry=seo_optimization_of_urls_in">Obie&#8217;s approach</a> with <a href="http://mephistoblog.com/2007/1/14/improved-url-escaping-for-permalinks">Ricks Permalink_fu plugin</a> (for converting text to permalinks):</p>
<pre>script/plugin install http://svn.techno-weenie.net/projects/plugins/permalink_fu</pre>
<p>Then in my topic.rb model object I do:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def to_param<br />
&amp;nbsp;&amp;nbsp;&quot;#{id}-#{PermalinkFu.escape(title)}&quot;<br />
end</div></div>
<p>and I double checked to make sure that the views always call link_to passing the model object rather than the ID (so that the to_param method has access to the id and the title). Fortunately <a href="http://beast.caboo.se/">beast.caboo.se</a> (which is what I based my site on) make heavy use of named routes:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;%= link_to h(topic.title), topic_path(@forum, topic) %&gt;</div></div>
<p>After that I was pretty much done but I had some really long URL&#8217;s so I truncated the title to the first 5 words by changing</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">PermalinkFu.escape(title)</div></div>
<p>to</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">PermalinkFu.escape(title.split[0..4].join(' '))</div></div>
<p>.</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/search-engine-friendly-urls-in-rails/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails Dreamhost plugin</title>
		<link>http://gabrito.com/post/ruby-on-rails-dreamhost-plugin</link>
		<comments>http://gabrito.com/post/ruby-on-rails-dreamhost-plugin#comments</comments>
		<pubDate>Sat, 03 Feb 2007 01:03:50 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/ruby-on-rails-dreamhost-plugin</guid>
		<description><![CDATA[Update 2/11/07: Just to clarify, this plugin won&#8217;t keep your Rails site running on Dreamhost if the sum of all your running processes exceeds 200MB (which is when their process monitor kills your processes). Run ps aux and sum the &#8230; <a href="http://gabrito.com/post/ruby-on-rails-dreamhost-plugin">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2/11/07</strong>: Just to clarify, this plugin won&#8217;t keep your Rails site running on Dreamhost if the sum of all your running processes exceeds 200MB (which is when their process monitor kills your processes). Run ps aux and sum the VSZ column and then divide by 1024. If you&#8217;re pushing the limit and are only running one Rails site you may want to look at another provider. If you&#8217;re running multiple Rails sites, run each site under a different user (one account can create many users).</p>
<p>Per <a href="http://subtlegradient.com/">Thomas Aylott&#8217;s</a> suggestion on my previous post <a href="http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2">Keeping Rails Running at Dreamhost Part 2</a> I&#8217;ve decided to release my <a href="http://gabrito.com/svn/plugins/dreamhost">Dreamhost signal handling code as a Rails plugin</a>. I&#8217;m using it on a <a href="http://gearandboats.com">Rails 1.2.1</a> site and a <a href="http://windandtides.com">Rails 1.1.6</a> site.<br />
<span id="more-171"></span><br />
<!--adsense--></p>
<p>Here&#8217;s the deal:</p>
<p>1. Get your Rails site running on Dreamhost (<a href="http://wiki.dreamhost.com/index.php/Ruby_on_Rails">the wiki should you get you there</a>).<br />
2. Once you&#8217;ve got it working, if you experience occasional 500 errors try my signal handling plugin. I still had 500 errors with the <a href="http://wiki.dreamhost.com/index.php/Ruby_on_Rails">frao_handler</a> approach described on the wiki, but if my plugin doesn&#8217;t work for you it can&#8217;t hurt to try it.</p>
<p>Here&#8217;s how to install the plugin:</p>
<pre>script/plugin install http://gabrito.com/svn/plugins/dreamhost</pre>
<p>With the plugin installed, the dispatch.fcgi will defer exiting when Dreamhost sends your dispatch.fcgi process a TERM signal if it is in the middle of handling a request, otherwise it behaves normally. This has reduced the 500 error rate on my two rails based sites to zero, your mileage may vary though. If you still have problems please don&#8217;t comment here and say it doesn&#8217;t work, instead figure out the problem and email a patch to thuss [at] gabrito [o] com!</p>
<p>The subversion repo for the plugin is at <a href="http://gabrito.com/svn/plugins/dreamhost">http://gabrito.com/svn/plugins/dreamhost</a>. If you have other Dreamhost related fixes that make sense for this plugin send them to me and I&#8217;ll incorporate them.</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/ruby-on-rails-dreamhost-plugin/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Keeping Rails running at Dreamhost Part 2</title>
		<link>http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2</link>
		<comments>http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2#comments</comments>
		<pubDate>Thu, 25 Jan 2007 06:22:11 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2</guid>
		<description><![CDATA[Update 2/2/07: Per Thomas&#8217; comment I&#8217;ve released the code below as the dreamhost rails plugin. Update 1/25/07: People have reported difficulties copy and pasting the dispatch.fcgi source code from this blog post so here is a dispatch.fcgi to download. Make &#8230; <a href="http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2/2/07</strong>: Per Thomas&#8217; comment I&#8217;ve released the code below as the <a href="http://gabrito.com/post/ruby-on-rails-dreamhost-plugin">dreamhost rails plugin</a>.<br />
<strong>Update 1/25/07</strong>: People have reported difficulties copy and pasting the dispatch.fcgi source code from this blog post so here is a <a href="http://gabrito.com/files/dispatch.fcgi">dispatch.fcgi</a> to download. Make sure you make it executable!</p>
<p>My first attempt to keep my <a href="http://www.rubyonrails.org/">Ruby on Rails</a> sites running at <a href="http://www.dreamhost.com/r.cgi?241603">Dreamhost</a> involved <a href="http://wiki.dreamhost.com/index.php/Ruby_on_Rails">modifying dispatch.fcgi to implement the frao_handler approach as described on the wiki</a>. This left me with a 3% 500 error rate. Ughh!<br />
<span id="more-170"></span><br />
My second attempt involved <a href="http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost">gracefully restarting dispatch.fcgi&#8217;s every hour or two to avoid the wrath of the Dreamhost process monitor</a>. This reduced the 500 error rate down to 0.2% which was still too high!</p>
<p>I&#8217;ve finally gotten my 500 error rate down to 0 by making some minor changes to the signal handling code of dispatch.fcgi. If the dispatch.fcgi process is in the midst of handling a request I defer letting it be killed until the request is complete. I did this by installing a custom TERM signal handler that protects the dispatch.fcgi process while a request is being processed. This solution works for my Rails 1.1 and Rails 1.2 (previously Edge) based sites. Here&#8217;s my complete dispatch.fcgi:</p>
<p><!--adsense--></p>
<pre><span class="comment">#!/usr/bin/ruby1.8</span>

<span class="ident">require</span> <span class="constant">File</span><span class="punct">.</span><span class="ident">dirname</span><span class="punct">(</span><span class="constant">__FILE__</span><span class="punct">)</span> <span class="punct">+</span> <span class="punct">"</span><span class="string">/../config/environment</span><span class="punct">"</span>
<span class="ident">require</span> <span class="punct">'</span><span class="string">fcgi_handler</span><span class="punct">'</span>

<span class="keyword">class </span><span class="class">RailsFCGIHandler</span>
 <span class="ident">private</span>
   <span class="keyword">def </span><span class="method">busy_exit_handler</span><span class="punct">(</span><span class="ident">signal</span><span class="punct">)</span>
     <span class="ident">dispatcher_log</span> <span class="symbol">:info</span><span class="punct">,</span> <span class="punct">"</span><span class="string">busy: asked to terminate during request signal <span class="expr">#{signal}</span>, deferring!</span><span class="punct">"</span>
     <span class="attribute">@when_ready</span> <span class="punct">=</span> <span class="symbol">:exit</span>
   <span class="keyword">end</span>

   <span class="comment"># Dreamhost sends the term signal and if we're handling a request defer it</span>
   <span class="keyword">def </span><span class="method">term_process_request</span><span class="punct">(</span><span class="ident">cgi</span><span class="punct">)</span>
     <span class="ident">install_signal_handler</span><span class="punct">('</span><span class="string">TERM</span><span class="punct">',</span><span class="ident">method</span><span class="punct">(</span><span class="symbol">:busy_exit_handler</span><span class="punct">).</span><span class="ident">to_proc</span><span class="punct">)</span>
     <span class="constant">Dispatcher</span><span class="punct">.</span><span class="ident">dispatch</span><span class="punct">(</span><span class="ident">cgi</span><span class="punct">)</span>
   <span class="keyword">rescue</span> <span class="constant">Exception</span> <span class="punct">=></span> <span class="ident">e</span>  <span class="comment"># errors from CGI dispatch</span>
     <span class="keyword">raise</span> <span class="keyword">if</span> <span class="constant">SignalException</span> <span class="punct">===</span> <span class="ident">e</span>
     <span class="ident">dispatcher_error</span><span class="punct">(</span><span class="ident">e</span><span class="punct">)</span>
   <span class="keyword">ensure</span>
     <span class="ident">install_signal_handler</span><span class="punct">('</span><span class="string">TERM</span><span class="punct">',</span> <span class="ident">method</span><span class="punct">(</span><span class="symbol">:exit_now_handler</span><span class="punct">).</span><span class="ident">to_proc</span><span class="punct">)</span>
   <span class="keyword">end</span>
   <span class="ident">alias_method</span> <span class="symbol">:process_request</span><span class="punct">,</span> <span class="symbol">:term_process_request</span>
<span class="keyword">end</span>

<span class="constant">RailsFCGIHandler</span><span class="punct">.</span><span class="ident">process!</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Switching from Edge Rails to 1.2 stable with Piston</title>
		<link>http://gabrito.com/post/switching-from-edge-rails-to-12-stable-with-piston</link>
		<comments>http://gabrito.com/post/switching-from-edge-rails-to-12-stable-with-piston#comments</comments>
		<pubDate>Wed, 24 Jan 2007 16:08:41 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Source Control]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/switching-from-edge-rails-to-12-stable-with-piston</guid>
		<description><![CDATA[Update 1/25/07: Francois pointed out that now as of Piston 1.3.0 you can now do this all with the following command: piston switch http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-1 vendor/rails For starters, if you&#8217;re still using svn:externals to manage your vendor/rails directory it&#8217;s time to &#8230; <a href="http://gabrito.com/post/switching-from-edge-rails-to-12-stable-with-piston">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Update 1/25/07</strong>: Francois pointed out that now as of Piston 1.3.0 you can now do this all with the following command: </p>
<pre>piston switch http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-1 vendor/rails</pre>
<p>For starters, if you&#8217;re still using svn:externals to manage your vendor/rails directory it&#8217;s time to switch to using <a href="http://piston.rubyforge.org">Piston</a>. svn:externals is so Q4!<br />
<span id="more-169"></span><br />
However, if you&#8217;re already running Piston, now that <a href="http://www.rubyonrails.org/">Rails 1.2</a> is out you may want to switch from running Edge (the trunk or head branch) to the stable 1.2 release for your production applications. Here&#8217;s how to make the switch with Subversion and Piston:</p>
<p><!--adsense--></p>
<pre>cd your_app
# Remove the old Piston checkout
svn delete vendor/rails
svn commit -m "Deleted edge" vendor/rails
svn update
# Checkout 1.2.1 (or newer)
piston import http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-1 vendor/rails
svn commit -m "Rails 1.2.1" vendor/rails</pre>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/switching-from-edge-rails-to-12-stable-with-piston/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An interview with the authors of JRuby</title>
		<link>http://gabrito.com/post/an-interview-with-the-authors-of-jruby</link>
		<comments>http://gabrito.com/post/an-interview-with-the-authors-of-jruby#comments</comments>
		<pubDate>Tue, 23 Jan 2007 05:23:17 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/an-interview-with-the-authors-of-jruby</guid>
		<description><![CDATA[The Java Posse hosted a great podcast interview with the authors of JRuby: Charles Nutter and Thomas Enebo. Additionally you get to hear what Tor Norbye is up to with his work on NetBeans Ruby integration and it looks like &#8230; <a href="http://gabrito.com/post/an-interview-with-the-authors-of-jruby">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Java Posse hosted a great <a href="http://javaposse.com/index.php?post_id=171709">podcast interview with the authors of JRuby</a>: <a href="http://headius.blogspot.com/">Charles Nutter</a> and <a href="http://www.bloglines.com/blog/ThomasEEnebo">Thomas Enebo</a>. Additionally you get to hear what Tor Norbye is up to with his work on <a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week1">NetBeans Ruby integration</a> and it looks like there&#8217;s some nice code assist features in the works! Really good code assist is the thing I miss most when doing Ruby (in RadRails) as opposed to  Java (in IDEA).</p>
<p>It&#8217;s exciting to see the convergence of my two favorite languages coming along!</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/an-interview-with-the-authors-of-jruby/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keeping Ruby on Rails running at Dreamhost</title>
		<link>http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost</link>
		<comments>http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost#comments</comments>
		<pubDate>Wed, 10 Jan 2007 01:41:55 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost</guid>
		<description><![CDATA[Update 1/12/07: This solution has reduced my 500 error rate down to less than 0.2% but it&#8217;s still not perfect. I continue to plug away at this&#8230; Update 1/24/07: I&#8217;ve finally solved my Dreamhost 500 error problems with a different &#8230; <a href="http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Update 1/12/07</strong>: This solution has reduced my 500 error rate down to less than 0.2% but it&#8217;s still not perfect. I continue to plug away at this&#8230;</p>
<p><strong>Update 1/24/07</strong>: I&#8217;ve finally solved my Dreamhost 500 error problems with a different solution described in <a href="http://gabrito.com/post/keeping-rails-running-at-dreamhost-part-2">Keeping Rails running at Dreamhost part 2<br />
</a><br />
This weekend I moved two of my newer <a href="http://www.rubyonrails.org/">Ruby on Rails</a> based sites (<a href="http://windandtides.com">http://windandtides.com</a> and <a href="http://gearandboats.com">http://gearandboats.com</a>) over to <a href="http://www.dreamhost.com/r.cgi?241603">Dreamhost</a>. You simply can&#8217;t beat their prices for hosting a small site (if you prepay for 2 years and use coupon code <strong>GABRITO</strong> to save $50 the total is $140.80) and I&#8217;ve found their customer service to be pretty responsive too.<br />
<span id="more-167"></span><br />
I followed their <a href="http://wiki.dreamhost.com/index.php/Ruby_on_Rails">Wiki based Ruby on Rails instructions</a> and had the sites up and running with <a href="http://manuals.rubyonrails.com/read/book/17">Capistrano</a> in no time. However, I soon discovered that their process monitor likes to kill off long running processes (effectively taking my sites offline without warning) and the only indication of what&#8217;s wrong is this error in the apache error.log:</p>
<p><!--adsense--></p>
<pre>
FastCGI: comm with (dynamic) server "/path/to/dispatch.fcgi" aborted: (first read)
  idle timeout (60 sec), referer: http://gearandboats.com
FastCGI: incomplete headers (0 bytes) received from server "/path/to/dispatch.fcgi",
  referer: http://gearandboats.com
</pre>
<p>To fix this I wrote a short ruby script <a href="http://gabrito.com/files/fcgimaint.rb">fcgimaint.rb</a> that I run once per hour via cron to restart my dispatch.fcgi processes (first with a USR1 and then a kill -9 if the USR1 didn&#8217;t work). This has the added benefit of cleaning up accumulated FastCGI processes and starting with a fresh memory footprint in case of a memory leak:</p>
<p>Crontab entry: 33  *  *  *  *  /home/myuser/bin/fcgimaint.rb</p>
<pre><span class="comment">#!/usr/bin/ruby</span>
<span class="keyword">def </span><span class="method">dispatchers</span><span class="punct">()</span>
  <span class="ident">ps</span> <span class="punct">=</span> `<span class="ident">ps</span> <span class="ident">ux`</span><span class="punct">.</span><span class="ident">grep</span><span class="punct">(/</span><span class="regex">dispatch<span class="escape">\.</span>fcgi</span><span class="punct">/)</span>
  <span class="ident">ps</span><span class="punct">.</span><span class="ident">map</span> <span class="punct">{|</span><span class="ident">p</span><span class="punct">|</span> <span class="punct">{'</span><span class="string">pid</span><span class="punct">'</span> <span class="punct">=></span> <span class="ident">p</span><span class="punct">.</span><span class="ident">split</span><span class="punct">[</span><span class="number">1</span><span class="punct">],</span> <span class="punct">'</span><span class="string">start</span><span class="punct">'</span> <span class="punct">=></span> <span class="ident">p</span><span class="punct">.</span><span class="ident">split</span><span class="punct">[</span><span class="number">8</span><span class="punct">]}}</span>
<span class="keyword">end</span>
<span class="ident">dispatchers</span><span class="punct">.</span><span class="ident">each</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">d</span><span class="punct">|</span> `<span class="ident">kill</span> <span class="punct">-</span><span class="constant">USR1</span> <span class="comment">#{d['pid']}` }</span>
<span class="ident">sleep</span> <span class="number">30</span>
<span class="comment"># Kill dispatchers that didn't restart nicely</span>
<span class="ident">dispatchers</span><span class="punct">.</span><span class="ident">each</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">d</span><span class="punct">|</span>
  <span class="keyword">if</span> <span class="punct">(</span><span class="constant">Time</span><span class="punct">.</span><span class="ident">now</span><span class="punct">.</span><span class="ident">hour</span> <span class="punct">!=</span> <span class="ident">d</span><span class="punct">['</span><span class="string">start</span><span class="punct">'][</span><span class="number">0</span><span class="punct">..</span><span class="number">1</span><span class="punct">])</span>
    `<span class="ident">kill</span> <span class="punct">-</span><span class="constant">KILL</span> <span class="comment">#{d['pid']}`</span>
  <span class="keyword">end</span>
<span class="keyword">end</span></pre>
<p>One other tool I found useful (especially during this process when the sites were going down periodically) was using <a href="http://nubyonrails.topfunky.com/articles/2006/03/29/surviving-rails-1-1-with-server-monitoring">Geoffrey Grosenbach&#8217;s modifications to dwatch to monitor my sites</a> and email my cell phone if there was a problem.<br />
<strong><br />
Caveat</strong>: if your site does more than 10,000 page views per day then a shared hosting plan is not the answer, you should be looking at dedicated or VPS hosting.</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/keeping-ruby-on-rails-running-at-dreamhost/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Rails Way delivers the goods</title>
		<link>http://gabrito.com/post/the-rails-way-delivers-the-goods</link>
		<comments>http://gabrito.com/post/the-rails-way-delivers-the-goods#comments</comments>
		<pubDate>Mon, 18 Dec 2006 23:52:30 +0000</pubDate>
		<dc:creator>Todd Huss</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://gabrito.com/post/the-rails-way-delivers-the-goods</guid>
		<description><![CDATA[I had a piece of data import code in Wind and Tides that I just knew could be cleaner and more elegant. Last week I submitted it to Jamis and Michael who write the Rails Way blog and their refactoring &#8230; <a href="http://gabrito.com/post/the-rails-way-delivers-the-goods">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I had a piece of data import code in <a href="http://windandtides.com">Wind and Tides</a> that I just knew could be cleaner and more elegant. Last week I submitted it to <a href="http://www.therailsway.com/">Jamis and Michael who write the Rails Way blog</a> and <a href="http://www.therailsway.com/2006/12/18/importing-files">their refactoring of it</a> exceeded my expectations and taught me a thing or two in the process. Their blog is definitely worth a read if you&#8217;re trying to take your rails coding to the next level!</p>
]]></content:encoded>
			<wfw:commentRss>http://gabrito.com/post/the-rails-way-delivers-the-goods/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

