<?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"
	>

<channel>
	<title>DigitalHobbit</title>
	<atom:link href="http://www.digitalhobbit.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.digitalhobbit.com</link>
	<description>Thoughts from the hobbit hole</description>
	<pubDate>Thu, 28 Aug 2008 06:17:02 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<item>
		<title>Rails And JSON Containing Unicode Characters</title>
		<link>http://www.digitalhobbit.com/archives/2008/08/27/rails-and-json-containing-unicode-characters/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/08/27/rails-and-json-containing-unicode-characters/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 06:17:00 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=302</guid>
		<description><![CDATA[As I mentioned in a previous blog post, Rails 2.1 natively supports incoming JSON requests. Unfortunately, it still struggles with JSON data containing non-ASCII characters.

According to the JSON spec, JSON fully supports UTF-8 encoded text, so with a few exceptions it generally should not be necessary to escape non-ASCII characters with \u Unicode escape sequences. [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned in a previous blog post, <a href="http://www.digitalhobbit.com/archives/2008/05/25/rails-21-and-incoming-json-requests/">Rails 2.1 natively supports incoming JSON requests</a>. Unfortunately, it still struggles with JSON data containing non-ASCII characters.</p>

<p>According to the <a href="http://json.org/">JSON spec</a>, JSON fully supports UTF-8 encoded text, so with a few exceptions it generally should not be necessary to escape non-ASCII characters with \u Unicode escape sequences. However, many JSON libraries appear to escape all non-ASCII text in this fashion. This in itself should not be a problem, but <code>ActiveSupport::JSON</code> currently does not properly parse JSON containing \u escapes, resulting in strings with literal \u escape sequences rather than the desired UTF-8 encoded characters. This is especially confusing since <code>ActiveSupport:JSON</code> itself encodes all non-ASCII characters as \u escapes, so one might think that the reverse transformation yields the original data. But this behavior is likely explained by an odd implementation choice for its decoder: Rather than using the <code>json</code> (or <code>json-pure</code>) library, it converts the JSON data to YAML and then uses the YAML library to decode the data into Ruby objects.</p>

<p>Monkey-patching to the rescue! I decided to replace <code>ActiveSupport::JSON::decode</code> with an implementation that uses the <code>json</code> library. The easiest way is to stick the following code into a file named something like <code>activesupport_json_unicode_patch.rb</code> inside the <code>config/initializers/</code> directory, where Rails will automatically pick it up.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'json'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> ActiveSupport
  <span style="color:#9966CC; font-weight:bold;">module</span> JSON
    <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">decode</span><span style="color:#006600; font-weight:bold;">&#40;</span>json<span style="color:#006600; font-weight:bold;">&#41;</span>
      ::JSON.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>json<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>You can verify the fix by adding a test case (I added a file named <code>activesupport_json_test.rb</code> to the <code>test/unit/</code> directory):</p>


<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'/../test_helper'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> ActiveSupportJsonTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_json_encoding
    unicode_escaped_json = <span style="color:#996600;">'{&quot;foo&quot;:&quot;G<span style="color:#000099;">\u</span>00fcnter&quot;,&quot;bar&quot;:&quot;El<span style="color:#000099;">\u</span>00e8ne&quot;}'</span>
    hash = <span style="color:#6666ff; font-weight:bold;">ActiveSupport::JSON</span>.<span style="color:#9900CC;">decode</span><span style="color:#006600; font-weight:bold;">&#40;</span>unicode_escaped_json<span style="color:#006600; font-weight:bold;">&#41;</span>
    assert_equal<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">'foo'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Günter'</span>, <span style="color:#996600;">'bar'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Elène'</span><span style="color:#006600; font-weight:bold;">&#125;</span>, hash<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>This test should fail without the patch and pass after adding it.</p>

<p>In addition to fixing the JSON / Unicode problem, this patch should also provide a nice speed boost, as we&#8217;re replacing the somewhat roundabout YAML based JSON decode method with a native one (particularly if you&#8217;re using the native <code>json</code> implementation rather than <code>json-pure</code>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/08/27/rails-and-json-containing-unicode-characters/feed/</wfw:commentRss>
		</item>
		<item>
		<title>It&#8217;s been a while&#8230;</title>
		<link>http://www.digitalhobbit.com/archives/2008/08/27/its-been-a-while/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/08/27/its-been-a-while/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 07:28:20 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Technology]]></category>

		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=298</guid>
		<description><![CDATA[I realized that it&#8217;s been quite a while since my last update. Unfortunately it seems like the amount of interesting stuff I have to write about is inversely proportional to the spare time I have available for writing&#8230;  

Anyway, I figure I&#8217;ll try to get back into the habit of publishing smaller posts, but [...]]]></description>
			<content:encoded><![CDATA[<p>I realized that it&#8217;s been quite a while since my last update. Unfortunately it seems like the amount of interesting stuff I have to write about is inversely proportional to the spare time I have available for writing&#8230; <img src='http://www.digitalhobbit.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

<p>Anyway, I figure I&#8217;ll try to get back into the habit of publishing smaller posts, but hopefully more regularly. Let&#8217;s see how it goes&#8230;</p>

<p>Ever since I went back into startup life four months ago, I&#8217;ve had the chance to play with a lot of exciting technologies, so there&#8217;s plenty of stuff to write about. Below are just some quick notes and mini-reviews, but I&#8217;ll be writing more about the various topics in the future.</p>

<ul>
<li><a href="http://merbivore.com">Merb</a>

<ul>
<li>This is quickly becoming my web framework of choice. It is well-thought-out, highly modular, and ideally suited for both small webservices as well as large scale websites.</li>
<li>The default application layout is very similar to Rails, making it easy for Rails developers to get up to speed on Merb. However, it also supports highly compact app layouts that are ideal for smaller webservices.</li>
<li>I&#8217;m sure I&#8217;ll write more about Merb later.</li>
</ul></li>
<li><a href="http://datamapper.org">DataMapper</a>

<ul>
<li>An awesome ORM framework, and one of several supported by Merb. Like Merb it is still pre-1.0 and therefore still evolving a lot, but it is already quite solid and very powerful.</li>
<li>More on this later&#8230;</li>
</ul></li>
<li><a href="http://rspec.info/">RSpec</a>

<ul>
<li>For my new projects, I have been using RSpec exclusively, and after a small learning curve it has really grown on me. Granted, I&#8217;m probably not taking advantage of all its features (for example I haven&#8217;t actually written my own matchers yet), but with a bit of discipline (and a heavy dose of mocking and stubbing), specs written in RSpec are probably an order of magnitude clearer and more readable than with Test::Unit.</li>
<li>I took the opportunity to get rid of test fixtures as well (and good riddance!)</li>
</ul></li>
<li><a href="http://www.ruby-lang.org/en/">Ruby</a> in general + <a href="http://rubyonrails.com/">Rails</a>

<ul>
<li>Right now I am working with a mix of Merb projects, Rails projects, and standalone Ruby apps.</li>
<li>I&#8217;ve had the opportunity to build a Ruby based framework for SMS based mobile apps, consisting of a processing pipeline with several independent services that communicate via asynchronous message queues, with some DSLs and meta-programming thrown in for good measure. This has allowed me to become much more familiar with Ruby than I was back when I just played with some Rails apps.</li>
<li>There&#8217;s definitely a right language for every task, but I have to admit that I find it harder and harder to imagine ever going back to Java&#8230;</li>
</ul></li>
<li><a href="http://aws.amazon.com">Amazon Web Services</a> (EC2, SQS, and S3)

<ul>
<li>Using Amazon AWS as a deployment platform is a whole new experience for me, and I am very impressed with the various services. They were already solid when I started working with them, but in the past few months Amazon managed to launch several major features (such as static IP addresses and persistent storage) that significantly lower the barrier of entry.</li>
<li>EC2 is particularly well-suited for the type of loosely coupled architecture we are developing, and I envision eventually being able to dynamically start and stop instances to adjust both to general growth over time, as well as fluctuations throughout the day (as mobile apps tend to exhibit certain usage patterns.)</li>
<li>SQS is a convenient way to tie the different components together (albeit with some limitations, such as an 8KB maximum message size), and of course S3 is available for any storage needs.</li>
<li>I will definitely blog in more detail about various AWS strategies and recipes.</li>
</ul></li>
<li><a href="http://git.or.cz/">Git</a>

<ul>
<li>We&#8217;ve been using Git (and <a href="http://github.com">GitHub</a>) for all new applications. We&#8217;re definitely not exploiting it to its full potential so far (given that we&#8217;re only a few developers that mostly work on different products, we haven&#8217;t had much of a need to leverage Git&#8217;s distributed nature), but I am definitely growing quite fond of it.</li>
<li>It is extremely fast, I love being able to commit code and browse the revision history even without a network connection, topic branches are convenient and powerful, and more.</li>
<li>Tool support is definitely still a weak point, but for the most part I&#8217;ve been happy using Git on the command line. </li>
</ul></li>
<li>Lots of sysadmin / deployment stuff

<ul>
<li>System administration is definitely not my forte, but I get by (at least on Linux; Joyent&#8217;s Solaris servers still manage to throw me off occasionally&#8230;).</li>
<li>I have had a chance to get more exposure to deploying Rails apps (including Mongrel, Monit, Passenger, etc.), as well as building a deployment framework for AWS from scratch.</li>
<li>Deploying applications to such a cloud based architecture is quite different from a typical Rails or LAMP stack, but I&#8217;m quite happy with the initial version of the deployment framework I&#8217;ve built. I&#8217;m essentially using S3 to store versioned app packages (which correspond directly to a Git tag) as well as third party gems, and a configuration file (also in S3) for each environment (such as production or staging) defines which version should be deployed on it. Each service regularly polls S3 for configuration changes and updates itself if appropriate. We use a single machine image and configure each instance via user data upon startup, which allows the instance to pull down the appropriate files from S3 and start running the service it is intended for. A small set of Rake tasks manage deploying releases and promoting them from one environment to another one.</li>
<li>There are still some challenges ahead, though, such as a proper logging system (I&#8217;m planning to migrate our apps to log to a central <a href="http://en.wikipedia.org/wiki/Syslog">syslog</a> server.)</li>
</ul></li>
<li>Various web based services, including <a href="https://www.google.com/a/">Google Apps</a>, <a href="http://github.com">GitHub</a>, <a href="http://lighthouseapp.com/">Lighthouse</a>, <a href="http://scoutapp.com/">Scout</a>, and <a href="http://ylastic.com">Ylastic</a>

<ul>
<li>All of these are great utilities.</li>
<li>Google Apps is a must-have; any startup should use it at least for email and calendaring, as well as collaborating on documents or spreadsheets. We also use Google Sites as our Intranet / Wiki.</li>
<li>I have briefly <a href="http://www.digitalhobbit.com/archives/2008/06/24/network-monitoring-with-scout/">blogged about Scout before</a> and will likely blog about various Scout plugins in the future.</li>
<li>GitHub is an amazing application, not only for hosting our own source code, but also for following the various open source projects we depend on (such as Rails, Merb, and DataMapper.)</li>
<li>We haven&#8217;t had a chance to really dive into Lighthouse yet, so the jury is still out on it. I do believe that its refreshingly simple, tag based approach should work pretty well, though.</li>
<li>Last not least, Ylastic has been invaluable and a great way to manage our EC2 instances, images, debug SQS based apps, browse S3, and more. I&#8217;ll probably write up a more thorough review soon.</li>
</ul></li>
<li>Honorary mention: <a href="http://www.pandora.com/">Pandora</a> and <a href="http://www.rogueamoeba.com/airfoil/">Airfoil</a>

<ul>
<li>For keeping us supplied with music and allowing us to stream it to our Airport Express. <img src='http://www.digitalhobbit.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul></li>
</ul>

<p>That&#8217;s it for now. Hopefully it won&#8217;t be two months before my next post&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/08/27/its-been-a-while/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Network Monitoring With Scout</title>
		<link>http://www.digitalhobbit.com/archives/2008/06/24/network-monitoring-with-scout/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/06/24/network-monitoring-with-scout/#comments</comments>
		<pubDate>Wed, 25 Jun 2008 06:39:20 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=297</guid>
		<description><![CDATA[I&#8217;ve been meaning to set up a network monitoring tool at work for a while. We have a couple of different applications using various technologies (currently mainly Ruby on Rails and PHP), running on various VPS servers. While we are using Monit to keep an eye on our Rails apps and restart them if necessary, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been meaning to set up a network monitoring tool at work for a while. We have a couple of different applications using various technologies (currently mainly Ruby on Rails and PHP), running on various VPS servers. While we are using <a href="http://www.tildeslash.com/monit/">Monit</a> to keep an eye on our Rails apps and restart them if necessary, as well as a couple of custom webpages to track vital and growth stats of our apps, we currently don&#8217;t use any monitoring or (perhaps more importantly) alerting tools beyond that. After one of our PHP / MySQL apps stopped responding (due to the fact that we ran out of disk space, as we later discovered), I figured it was about time to put some more sophisticated network monitoring in place.</p>

<p>The de-facto standard application seems to be <a href="http://www.nagios.org/">Nagios</a>, which is quite powerful and configurable, but has an extremely steep learning curve. It also does not offer a friendly UI for configuring services and relies on static configuration files instead. There is also a newer crop of network monitoring apps that I was hoping might be a bit less daunting to get up to speed on, such as <a href="http://www.zenoss.com/">Zenoss</a> (here is a <a href="http://www.infoworld.com/infoworld/article/07/09/10/37FE-boss-enterprise-monitoring_1.html">brief overview of open source network monitoring apps</a>). I downloaded a few of these, but ultimately realized that I would not be able to get my head wrapped around any of these apps purely using intuition, and that I would actually have to invest a fair amount of time to master at least the basics. I&#8217;m simply not enough of an operations expert&#8230; It is clear that all of these apps are extremely powerful, and probably great for larger deployments, but I really just needed a simple tool to check some operating system level vital stats or ping some URLs, for a handful of machines.</p>

<p>That&#8217;s when I remembered <a href="http://scoutapp.com/">Scout</a>, a hosted network monitoring service that launched fairly recently and that sounded very interesting when I first came across it. Their <a href="https://scoutapp.com/subscriptions">subscription plans</a> are pretty reasonable (the $29/month plan for 4 servers should suffice for us at this stage), particularly given that we would have had to pay for an additional VPS slice or EC2 instance to host Nagios or some other deployed solution anyway. Best of all, Scout offers a free plan, and even though this only supports a single server, this is a good way to evaluate how well it works for our purposes.</p>

<p>Scout uses an interesting approach at monitoring servers. Rather than using SNMP or an agent that is continuously running on each server, Scout uses a lightweight client (installed via a Ruby gem) that needs to be run periodically (10 minutes being the minimal reporting interval), generally via a cron job. Once the client app is installed on each server to be monitored, the servers don&#8217;t need to be touched for future configuration changes. Instead, everything is configured on the <a href="http://scoutapp.com">Scout website</a>, and pulled down by the client the next time it checks in. The entire configuration consists of a number of plugins that can be installed for each client. Out of the box, Scout supports around 20 plugins that range from basic monitoring tasks for server load or disk space to more specific plugins for Ruby on Rails, Mongrel, or MySQL.</p>

<p>Even better, Scout offers a <a href="https://scoutapp.com/plugin_urls/static/creating_a_plugin">very simple Plugin API</a> for integrating your own plugins. Plugins are written in Ruby and mainly consist of a single method that either returns a bunch of stats as a hash, which is exposed by Scout both in tabular report and graph form, or triggers an alert in case of a problem. Since plugins have the full Ruby stack at their disposal, it is easy to write a plugin that shells out to a Unix command, performs an HTTP request, hits a database, or anything else you can think of.</p>

<p>One minor downside is that (as far as I can tell), there is no way to simply upload a plugin. Instead, Scout relies on a pull mechanism, which means that we would need to expose any proprietary plugins via a publicly accessible URL. This might be an issue if the plugin itself contains sensitive information, although settings (such as passwords or paths) can be decoupled from the code and configured via the web interface. While not ideal, putting the plugin code in a publicly accessible but not automatically discoverable location and only making it available for the duration of the initial download or future updates should minimize this risk and turn it into a minor inconvenience.</p>

<p>Based on my initial impression, Scout looks very promising. The reporting functionality is fairly basic, and particularly the graphs could perhaps use a bit more polish, but everything is very easy to use. Scout is clearly geared towards developers rather than sysadmins, so perhaps that is why it appeals to me. If your monitoring needs are relatively straightforward and you don&#8217;t need all the functionality that a deployed solution like Nagios offers, Scout is definitely worth a look, at least for relatively small deployments. I am not sure how well it scales beyond 16 servers (both in terms of administration and pricing), so it is possible that a deployed application might make more sense at that point.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/06/24/network-monitoring-with-scout/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Phusion Passenger Now Rack Compatible?</title>
		<link>http://www.digitalhobbit.com/archives/2008/06/01/phusion-passenger-now-rack-compatible/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/06/01/phusion-passenger-now-rack-compatible/#comments</comments>
		<pubDate>Sun, 01 Jun 2008 23:24:09 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=296</guid>
		<description><![CDATA[According to this blog post and several mentions on Twitter, Phusion announced today&#8217;s release of Passenger (aka mod&#95;rails) 2.0 at RailsConf. Apparently, Passenger 2.0 will be Rack compliant and thus support not only Rails, but any Rack compatible web framework, including Merb and Sinatra. Interestingly, Passenger will not even be limited to Ruby any more [...]]]></description>
			<content:encoded><![CDATA[<p>According to <a href="http://www.railsjedi.com/posts/52-The-Holy-Grail-for-Rails-Deployment">this blog post</a> and several <a href="http://summize.com/search?q=passenger+2.0">mentions on Twitter</a>, Phusion announced today&#8217;s release of Passenger (aka mod&#95;rails) 2.0 at RailsConf. Apparently, Passenger 2.0 will be Rack compliant and thus support not only Rails, but any Rack compatible web framework, including <a href="http://merbivore.com/">Merb</a> and <a href="http://sinatrarb.com/">Sinatra</a>. Interestingly, Passenger will not even be limited to Ruby any more and extend their support to WSGI, the Python web adapter framework that inspired Rack in the first place. For example, this will allow Passenger 2.0 to run the popular Django web framework. In light of these changes, Passenger will drop the name mod&#95;rails.</p>

<p>I think these are fantastic news! As I mentioned in <a href="http://www.digitalhobbit.com/archives/2008/05/14/phusion-passenger-aka-mod&#95;rails-on-dreamhost/">my previous post on Phusion Passenger</a>, it makes deploying Rails apps trivially easy, and I am planning to use it as the default deployment platform for my Rails apps. I have also been flirting with Merb lately, and knowing that I am going to be able to deploy it just as easily as Rails makes a big difference to me.</p>

<p>Support for Rack is the logical next step for Passenger, so I am not all that surprised about the direction they are going. I am however a bit surprised about the timing. After all, version 1.0 was only released fairly recently and prominently branded as mod&#95;rails. The [http://www.modrails.com/documentation.html](online documentation) even states (although I assume that this will be updated within the next few days):</p>

<blockquote>
  <p>Does it support other Ruby frameworks (Merb, Camping, etc.)?</p>
  
  <p>No.</p>
  
  <p>What?! Why??</p>
  
  <p>Because this is an evil plot created by evil overlords, with the goal of world domination destroying all other Ruby frameworks. 
  …</p>
  
  <p>Actually…</p>
  
  <p>There is the following saying: Jack of all trades, master of none. Our intention is to be masters, not Jacks. The primary goal of version 1.0 was to create an easy-to-use, low-maintenance, stable and fast Ruby on Rails deployment system for Apache. And we&#8217;ve put a lot of effort into reaching that goal. Implementing support for other Ruby frameworks would have deviated us from that goal and would have increased development time significantly.</p>
  
  <p>That said, nothing prevents future versions from supporting other Ruby frameworks, or from becoming a generic Ruby web application deployment platform. Please discuss it with us if you&#8217;re interested in steering development towards that direction.</p>
</blockquote>

<p>My guess is that there was a lot of demand for Rack support from users (even Rails now supports Rack), and after looking into it, they realized it was easier to integrate this than they initially expected. Either way, this is great news, and I look forward to trying out Passenger 2.0 with Merb and DataMapper, or even Sinatra for smaller apps.</p>

<p><strong>Update:</strong> 2.0 RC1 has been released, and you can find more details in <a href="http://blog.phusion.nl/2008/06/09/phusion-passenger-20-rc-1-and-ruby-enterprise-edition-released/#comment-82">the release announcement on the Phusion blog</a>. In addition to Rack and WSGI support, 2.0 sounds like a more solid and stable release overall, with a significantly smaller memory footprint, faster startup time, fair load balancing, upload buffering, and some convenient <a href="http://www.modrails.com/documentation/Users%20guide%202.0.html#_analysis_and_system_maintenance_tools">analysis tools</a>. There&#8217;s also a native Ubuntu package now, in case you want to avoid compiling from source.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/06/01/phusion-passenger-now-rack-compatible/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails 2.1 and Incoming JSON Requests</title>
		<link>http://www.digitalhobbit.com/archives/2008/05/25/rails-21-and-incoming-json-requests/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/05/25/rails-21-and-incoming-json-requests/#comments</comments>
		<pubDate>Mon, 26 May 2008 06:54:57 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=295</guid>
		<description><![CDATA[Earlier this week, we tried to figure out the cleanest and easiest way to get our Rails app to accept incoming JSON requests. Up until recently, developers were able to use various Rails plugins for this purpose, such as the json_request plugin.

Luckily, it turns out that full support for JSON was added to Rails in [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week, we tried to figure out the cleanest and easiest way to get our Rails app to accept incoming JSON requests. Up until recently, developers were able to use various Rails plugins for this purpose, such as the <a href="http://blog.labnotes.org/2007/12/11/json_request-handling-json-request-in-rails-20/">json_request plugin</a>.</p>

<p>Luckily, it turns out that full support for JSON was <a href="http://github.com/rails/rails/commit/4d594cffcfc93b37fad4e423ec8593299e50133c">added to Rails in April</a>, making it a first class citizen along with XML and regular URL-encoded form fields. This functionality will be officially released in Rails 2.1, but in addition to Edge Rails, it is already included in Rails 2.0.991, which is available from the <a href="http://gems.rubyonrails.org">Ruby on Rails Gem Repository</a>. You can install this pre-release via:</p>


<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> gem update rails <span style="color: #660033;">--source</span> http:<span style="color: #000000; font-weight: bold;">//</span>gems.rubyonrails.org</pre></div></div>


<p>Using this functionality is really simple. Let&#8217;s say we have created the following scaffolded Rails app with a Book resource, perhaps to manage your library:</p>


<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">rails library
<span style="color: #7a0874; font-weight: bold;">cd</span> library
script<span style="color: #000000; font-weight: bold;">/</span>generate scaffold book title:string author:string isbn:string price:decimal
rake db:migrate</pre></div></div>


<p>As you know, you can now access the books controller in the browser via <code>http://localhost:3000/books</code>, and use the &#8220;New Book&#8221; link to create a new book via the scaffolded form that Rails provides. But you can also create books via JSON (or XML, for that matter). In fact, we will try XML first, which has been natively supported in Rails for a while:</p>


<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">curl <span style="color: #660033;">-H</span> <span style="color: #ff0000;">&quot;Content-Type:text/xml&quot;</span> <span style="color: #660033;">-H</span> <span style="color: #ff0000;">&quot;Accept:text/xml&quot;</span> \
  <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;&lt;book&gt;&lt;title&gt;Posted via XML&lt;/title&gt;&lt;author&gt;Ex Emel&lt;/author&gt;&lt;isbn&gt;1234567890&lt;/isbn&gt;&lt;price&gt;34.99&lt;/price&gt;&lt;/book&gt;&quot;</span> \
  http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">3000</span><span style="color: #000000; font-weight: bold;">/</span>books</pre></div></div>


<p>Note that I am setting both the Content-Type and Accept header to &#8220;text/xml&#8221;, indicating that the incoming request consists of XML and that we would like to receive an XML-formatted response as well. The response looks like this:</p>


<div class="wp_syntax"><div class="code"><pre class="xml xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;book<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Ex Emel<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;created-at</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;datetime&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>2008-05-26T05:58:38Z<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/created-at<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;integer&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;isbn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1234567890<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/isbn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;price</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;decimal&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>34.99<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/price<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Posted via XML 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;updated-at</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;datetime&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>2008-05-26T05:58:38Z<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/updated-at<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/book<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Now let&#8217;s try the same thing in JSON:</p>


<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">curl <span style="color: #660033;">-H</span> <span style="color: #ff0000;">&quot;Content-Type:application/json&quot;</span> <span style="color: #660033;">-H</span> <span style="color: #ff0000;">&quot;Accept:application/json&quot;</span> \
  <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;{<span style="color: #000099; font-weight: bold;">\&quot;</span>book<span style="color: #000099; font-weight: bold;">\&quot;</span>:{<span style="color: #000099; font-weight: bold;">\&quot;</span>title<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>Posted via JSON<span style="color: #000099; font-weight: bold;">\&quot;</span>, <span style="color: #000099; font-weight: bold;">\&quot;</span>author<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>Jason Bourne<span style="color: #000099; font-weight: bold;">\&quot;</span>, <span style="color: #000099; font-weight: bold;">\&quot;</span>isbn<span style="color: #000099; font-weight: bold;">\&quot;</span>:1234567890, <span style="color: #000099; font-weight: bold;">\&quot;</span>price<span style="color: #000099; font-weight: bold;">\&quot;</span>:49.95}}&quot;</span> \
  http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">3000</span><span style="color: #000000; font-weight: bold;">/</span>books</pre></div></div>


<p>As you can verify in the browser, this request was successful and had the desired effect. However, unlike the XML case, there was no response this time. This is because our controller does not know how to render JSON results yet. Looking at the <code>create</code> method in the <code>BooksController</code>, we notice that the <code>responds_to</code> block contains entries for HTML and XML, but not for JSON. Simply copy the XML lines and replace all occurrences of <code>xml</code> with <code>json</code>. The updated method should look like this:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> create
  <span style="color:#0066ff; font-weight:bold;">@book</span> = Book.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:book</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  respond_to <span style="color:#9966CC; font-weight:bold;">do</span> |format|
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">save</span>
      flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'Book was successfully created.'</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#006600; font-weight:bold;">&#123;</span> redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span>@book<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:created</span>, <span style="color:#ff3333; font-weight:bold;">:location</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">json</span> <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:json</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:created</span>, <span style="color:#ff3333; font-weight:bold;">:location</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;new&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">errors</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:unprocessable_entity</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">json</span> <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:json</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">errors</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:unprocessable_entity</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>If you run the same curl command again, you should now get the following response:</p>


<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">{&quot;book&quot;: {&quot;isbn&quot;: 1234567890, &quot;updated_at&quot;: &quot;2008-05-26T06:11:33Z&quot;,
&quot;title&quot;: &quot;Posted via JSON&quot;, &quot;price&quot;: 49.95, &quot;author&quot;: &quot;Jason Bourne&quot;,
&quot;id&quot;: 4, &quot;created_at&quot;: &quot;2008-05-26T06:11:33Z&quot;}}</pre></div></div>


<p>One important thing to note is that both the incoming and outgoing JSON contain an outermost element called <code>book</code>. This is in fact required for resource based JSON requests to work. The same is true for XML, but since XML requires an enclosing element (unlike JSON, which can be &#8220;naked&#8221;), it is perhaps less obvious in this case. The outermost JSON element should always have the same name as the resource it corresponds to.</p>

<p>A few notes on testing JSON requests:</p>

<p>We initially banged our heads against the wall trying to figure out how to convince our functional test to pass JSON-formatted parameters in the <code>post</code> method, including various hacks to override different settings on the <code>@request</code> object. Admittedly it had been a while since I had seriously used Rails the last time, but it later dawned on me that we were going about this the wrong way. Functional tests (in Rails, anyways&#8230; let&#8217;s not talk about its confusing and non-standard test terminology) bypass most of the actual HTTP request handling and are not meant to test this aspect of an application. They essentially pick up at the point where the controller has received its (already parsed) parameters in the <code>params</code> hash, regardless of whether these originated from an XML, JSON, or URL-encoded form request.</p>

<p>Since JSON support is implemented by Rails (and thus covered by its own unit tests), it probably does not make sense to focus too much on testing this general functionality in the individual application. But if you do want to test JSON requests, you can use integration tests for this purpose. The <code>post</code> method in integration tests is more low level and simulates the actual HTTP request, along with the parameter parsing.</p>

<p>So in our library example, we might use an integration test case such as the one below to specifically test creating a book via JSON:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> test_create_via_json
  assert_difference<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Book.count'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    post <span style="color:#996600;">'/books/create'</span>,
      <span style="color:#996600;">'{&quot;book&quot;:{&quot;title&quot;:&quot;Posted via JSON&quot;, &quot;author&quot;:&quot;Jason Bourne&quot;, &quot;isbn&quot;:1234567890, &quot;price&quot;:49.95}}'</span>,
      <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">'Content-Type'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'application/json'</span>, <span style="color:#996600;">'Accept'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'application/json'</span><span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Native JSON support in Rails is definitely a useful feature. In fact, I was fairly surprised that this wasn&#8217;t already implemented until recently. But now that it&#8217;s here, it should come in very handy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/05/25/rails-21-and-incoming-json-requests/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Phusion Passenger (aka mod_rails) on DreamHost</title>
		<link>http://www.digitalhobbit.com/archives/2008/05/14/phusion-passenger-aka-mod_rails-on-dreamhost/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/05/14/phusion-passenger-aka-mod_rails-on-dreamhost/#comments</comments>
		<pubDate>Thu, 15 May 2008 06:09:26 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=294</guid>
		<description><![CDATA[A couple weeks ago, Phusion Passenger (aka mod&#95;rails) was released. I recently tested this at work, on an EC2 instance, and my initial experience was so smooth that I am already planning to use it to deploy our various Rails applications. The benchmarks I&#8217;ve seen put its performance on approximately the same level as a [...]]]></description>
			<content:encoded><![CDATA[<p>A couple weeks ago, <a href="http://www.modrails.com/">Phusion Passenger (aka mod&#95;rails)</a> was released. I recently tested this at work, on an EC2 instance, and my initial experience was so smooth that I am already planning to use it to deploy our various Rails applications. The benchmarks I&#8217;ve seen put its performance on approximately the same level as a Mongrel cluster, but its ease of use is an order of magnitude better. All you need to do is install an Apache mod and set up a virtual host config that points to your Rails app&#8217;s <code>public</code> directory. You don&#8217;t even need to tell it that the directory you&#8217;re pointing to represents a Rails app &#8212; mod&#95;rails is smart enough to figure this out by itself (although there are a few Rails specific options you can use to control the base URI or the Rails environment). No more juggling Mongrel PIDs, complicated proxy configs, or anything of that sort. Simply create a <code>tmp/restart.txt</code> file to have Apache reload the Rails app after you deploy a new version. Tom Copeland posted a <a href="http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-and-c.html">very simple Capistrano script for mod&#95;rails</a>, which essentially does just that and stubs out the usual Rails Capistrano tasks that are no longer necessary in this setup.</p>

<p>Yesterday, <a href="http://blog.dreamhost.com/2008/05/13/passenger-for-ruby-on-rails/">DreamHost announced their support for mod&#95;rails</a>. I had played with Rails on DreamHost several years ago (back when FCGI was still the generally accepted way to run Rails apps), but ultimately gave up on this because of the frustrating experience (performance, stability, and ease of deployment wise). Since then, VPS hosting services (such as <a href="http://www.slicehost.com/">SliceHost</a>) have become the prevalent solution for hosting Rails apps. But with DreamHost officially supporting mod&#95;rails, I figured I&#8217;d give this a spin to see how well it works in practice.</p>

<p>I am happy to say, it seems to work just as advertised! In order to test Rails on DreamHost, I downloaded the popular <a href="http://mephistoblog.com/">Mephisto Blog Application</a>, unzipped it into a directory on my DreamHost account, and configured the database settings (I didn&#8217;t even bother with MySQL and opted for Sqlite3 for the purpose of this test). I then went into my domain&#8217;s settings on the DreamHost Web Panel, checked the &#8220;Ruby on Rails Passenger (mod&#95;rails)&#8221; checkbox, and pointed to my Mephisto directory&#8217;s <code>public</code> subdirectory as the web directory for my domain (this is important, as the web directory defaults to <code>yourdomain.com</code>, without the <code>/public</code> that mod&#95;rails expects).</p>

<p>A minute or two later, my changes had been applied and I was greeted by the Mephisto blog when I hit my domain in the browser. I configured my blog&#8217;s settings and entered some dummy articles, and found the performance to be very snappy &#8212; no different from PHP apps that I am hosting at DreamHost (such as this WordPress blog).</p>

<p>I think this is pretty exciting. Sure, there are many other cost-effective options to deploy Rails apps these days (such as the unique and highly promising <a href="http://heroku.com/">Heroku</a> or a cheap $20 VPS slice on SliceHost), but for a personal blog or another small, reasonably low-traffic website (such as the 12 or so random Rails apps all of us are concurrently working on and too cheap to spring for VPS hosting, since most of them will never go anywhere), having the option to easily deploy these on a shared hosting account is great.</p>

<p>Now I am hoping that mod&#95;rails will be extended beyond just Rails to support any <a href="http://rack.rubyforge.org/">Rack</a> compliant Ruby web framework, such as <a href="http://merbivore.com/">Merb</a> or <a href="http://sinatra.rubyforge.org/">Sinatra</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/05/14/phusion-passenger-aka-mod_rails-on-dreamhost/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Twitter / Ruby on Rails FUD</title>
		<link>http://www.digitalhobbit.com/archives/2008/05/01/twitter-ruby-on-rails-fud/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/05/01/twitter-ruby-on-rails-fud/#comments</comments>
		<pubDate>Fri, 02 May 2008 04:57:37 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Technology]]></category>

		<category><![CDATA[Websites]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=293</guid>
		<description><![CDATA[Earlier today, TechCrunch&#8217;s poorly researched claim that Twitter is abandoning Ruby on Rails in favor of PHP or Java generated a lot of buzz in the Twitter and Ruby communities (the claim was later refuted by Twitter developer Evan Williams).

Of course, the article&#8217;s comments attracted the usual, ignorant TechCrunch trolls. Most took the opportunity to [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier today, <a href="http://www.techcrunch.com/2008/05/01/twitter-said-to-be-abandoning-ruby-on-rails/">TechCrunch&#8217;s poorly researched claim that Twitter is abandoning Ruby on Rails</a> in favor of PHP or Java generated a lot of buzz in the Twitter and Ruby communities (the claim was later <a href="http://twitter.com/ev/statuses/801530348">refuted by Twitter developer Evan Williams</a>).</p>

<p>Of course, the <a href="http://www.techcrunch.com/2008/05/01/twitter-said-to-be-abandoning-ruby-on-rails/#comments">article&#8217;s comments</a> attracted the usual, ignorant TechCrunch trolls. Most took the opportunity to pitch their framework of choice (such as PHP, Java, .NET, or Django), which they claimed would of course magically solve all of Twitter&#8217;s scalability issues.</p>

<p>I have to say I am appalled at this level of ignorance. People just don&#8217;t seem to realize that Twitter is a complex messaging application and that the front-end is only a relatively small aspect of it. Even if one particular front-end technology happens to be faster than another one (and admittedly Rails, as much as I like it, is not the fastest technology out there), this fact is bound to be negligible compared to the real challenges in scaling the back-end, starting with the database (trust me, like many developers I&#8217;ve learned this the hard way <img src='http://www.digitalhobbit.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Even for a typical web application (which Twitter is not), there are many performance improvements than can be implemented at that level (such as leveraging database replicas to separate writes from reads, or utilizing Memcached to cache queries and other data), all of which can be applied equally well to any front-end framework.</p>

<p>I&#8217;m not saying that it does not make sense to consider other technologies (there might very well be a breaking point at which it makes sense to evaluate Java or even rewriting parts of the system in C/C++), but in my opinion this should be considered a cost-savings measure when the application reaches a scale at which the cost of hardware far outweighs any savings due to increased developer productivity (think Google), and not a magic bullet for solving fundamental scalability issues (performance != scalability!)</p>

<p>One of the real difficulties in scaling Twitter lies in the fact that all Twitter hits are completely personalized and need to return fresh data, making it difficult to fully leverage caching. Also, since Twitter is a social application and the returned data is generated by each user&#8217;s social graph, there is no straightforward way to shard the database by user, as one might be able to do in a typical e-commerce or enterprise application (or pretty much any non-social app&#8230;). Without knowing more about Twitter&#8217;s internal architecture and their actual profiling results, it would be foolish of me to make any concrete recommendations &#8212; particularly silly ones like <em>&#8220;Use technology XYZ, it will magically solve all your problems!&#8221;</em> Too bad many of the developers out there don&#8217;t seem to realize this&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/05/01/twitter-ruby-on-rails-fud/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gelato with DHH</title>
		<link>http://www.digitalhobbit.com/archives/2008/04/20/gelato-with-dhh/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/04/20/gelato-with-dhh/#comments</comments>
		<pubDate>Sun, 20 Apr 2008 07:49:30 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Events]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=292</guid>
		<description><![CDATA[I just got back from an ice cream social with Ruby on Rails creator David Heinemeier Hansson (aka DHH). I had come across his blog post about this casual event last week and figured I&#8217;d make my way over there, particularly since the location (Michael&#8217;s Gelato &#38; Cafe) in downtown Palo Alto is only 5 [...]]]></description>
			<content:encoded><![CDATA[<p>I just got back from an ice cream social with Ruby on Rails creator <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a> (aka DHH). I had come across his <a href="http://www.loudthinking.com/posts/25-going-to-california">blog post about this casual event</a> last week and figured I&#8217;d make my way over there, particularly since the location (<a href="http://www.michaelsgelatoandcafe.com/">Michael&#8217;s Gelato &amp; Cafe</a>) in downtown Palo Alto is only 5 minutes from my house.</p>

<p>There were probably about 20 other people (mainly Rails developers) at the event, and since the space was pretty small and we didn&#8217;t have a dedicated room, it was initially difficult to actually speak with David. But towards the end of the evening the group started getting smaller, which made it easier to participate in the conversation.</p>

<p>In terms of what David had to say, I did not catch too many noteworthy items that are not already known in Ruby on Rails circles. But a few things seem to be key to understanding both the history and the future of Rails:</p>

<ol>
<li><p>David created Rails to solve his specific problems. It wasn&#8217;t meant to directly solve every possible problem out there, and if there are useful features missing from it that simply means that he (or presumably the rest of the core team, now that it has become a larger community project) has not needed that particular functionality, not that it would not be useful.</p></li>
<li><p>Rails is (as we all know) a very opinionated framework. It makes a lot of reasonable assumptions about various things (such as the names of &#8220;id&#8221; columns), which enables developers to accomplish a lot with very little code. However, all of these opinions are purely about the internals of the system and therefore relevant for developers, but never affect the end user in any way. David is strongly against including any features in Rails that would result in any default application flows or otherwise affect the actual behavior of the application. That&#8217;s why Rails still does not (and probably will never) include a built-in authentication system.</p></li>
</ol>

<p>Otherwise, he seems pretty indifferent about a lot of the details about how people are working with Rails. For example, Ruby and Ruby on Rails&#8217; performance was good enough for him several years ago, so this area has never been too much of a concern of his. He also doesn&#8217;t feel strongly about using Test::Unit vs. RSpec. In his opinion, Test::Unit is good enough, and actually easier to understand for someone who does not have much experience with testing, whereas RSpec probably has more of a learning curve (and he did not seem to excited about the particular syntax). He felt that the most important thing that BDD and RSpec brought to the table is the &#8220;should&#8221; keyword, and that changing Rails to allow this in test method names made a big enough difference in readability and helped enforce the convention of using a single assertion for each test case. (I actually was not aware that you can use &#8220;should&#8221; in Rails test names; I&#8217;ll have to look into this.)</p>

<p>I probably missed a bunch of other nuggets of wisdom because the room was a bit noisy and crowded, but I&#8217;m sure that all of these have been posted on various blogs and mentioned in various keynote speeches before.</p>

<p>Anyway, it was nice to meet David in person. He seems like a great guy, and I definitely appreciate that he took the time to meet with a small fraction of his user base tonight. It&#8217;s refreshing to work with technologies that are owned and driven by real-world people like this, rather than large corporations that have lost touch with their user base.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/04/20/gelato-with-dhh/feed/</wfw:commentRss>
		</item>
		<item>
		<title>On Leaving Google</title>
		<link>http://www.digitalhobbit.com/archives/2008/04/13/on-leaving-google/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/04/13/on-leaving-google/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 08:16:23 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Career]]></category>

		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/?p=291</guid>
		<description><![CDATA[As some of you may know, I have decided to leave Google and go back into the startup world. Friday was my last day at Google, and even though I normally don&#8217;t blog much about my job, I figured I was due for an update.

First off, Google is an amazing company. Especially for a company [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you may know, I have decided to leave Google and go back into the startup world. Friday was my last day at Google, and even though I normally don&#8217;t blog much about my job, I figured I was due for an update.</p>

<p>First off, Google is an amazing company. Especially for a company of this size (and impact), it is highly impressive that they have managed to maintain this kind of work environment, company culture, and integrity. On the most basic level, there are all the perks, from great health benefits to free food (there are about 15 cafeterias on the Mountain View campus alone, many of which offer breakfast, lunch, and dinner), micro-kitchens with free snacks (including fresh fruit or fresh cut carrots and celery), on-campus gyms and a beach volleyball field, and more. Another great thing are the many tech talks (usually there are at least a couple every day), which feature both internal and external speakers. There are also many opportunities for training. In the one year that I have worked at Google, I had the opportunity to take a one-day class on Agile Estimating and Planning, as well as an excellent four-day workshop on Design Patterns and Refactoring, and numerous Google and product specific classes. Then there are the various off-sites and team building events, which probably take up another good week each year. Not many companies send their employees to Disneyland for three days&#8230; And of course there&#8217;s Google itself, with its various products that have become so ubiquitous and synonymous with the web that life would be difficult to imagine without them. Anybody remember the web before Google Search came along? Let me give you a hint: it sucked! But even newer products like Gmail, Google Reader, or Calendar have caught on quickly and become established as best-of-breed applications, and I definitely felt proud to work at the company that has built all of these applications. And speaking of work, the actual work environment is also nice in many ways: Every engineer gets either two 24&#8243; or one 30&#8243; monitor, as well as a company laptop (either MacBook Pro or Thinkpad). Depending on which project you work on, you might get to work with innovative internal tools and frameworks (such as BigTable), and I have definitely developed an entirely different perspective on scale, which humbles any project I&#8217;ve worked on before. Then there&#8217;s the community. In general, Googlers are a great bunch, and very smart. There are internal mailing lists on pretty much any subject, and you can pretty much guarantee that you will be able to get a solid answer to whatever question you might have (work or non-work related). In fact, this reminded me quite a bit of Usenet, back when it was still popular and usable, and not totally overrun with idiots. Of course, keeping up with all of this can become quite a time sink as well&#8230; Google is highly engineering-driven, and engineers enjoy a lot of trust and power, which is a very different and refreshing experience from working at a more product-driven company.</p>

<p>So if everything is so great at Google, why am I stupid enough to leave? And part of me does indeed feel a bit guilty about not being able to fully appreciate and enjoy working at Google &#8212; after all, there are many people out there in the world that have dreary and monotonous minimum-wage jobs, without any benefits or perks to speak of. But in the end, I have realized that I am just much more of a startup person than a big-company person. Perks and everything are great, but this is ultimately not what motivates me. At an early stage startup, every single individual has a tremendous impact on the company (good or bad&#8230;), along with a much broader set of responsibilities (everybody has to wear many hats). Then, there&#8217;s the pioneering spirit, which is extremely energizing and contagious. These days, it seems like a lot of the true innovations are made at small startups, which have the benefit of being orders of magnitude times more agile and efficient than a large company will ever be. Sure, many ideas don&#8217;t go anywhere, but every once in a while, something new comes along that leaves a big footprint (and let&#8217;s not forget that even Google started out like this). Last not least, there is of course a significantly bigger upside to working at a startup. Of course the harsh truth is that most startups fail, but at least there is that 1 in a 10 chance of being tremendously successful (and the sense of actually being able to contribute to this chance). As a recent Google employee, I would have never gotten rich there, even if the stock had doubled or tripled in price.</p>

<p>There are a few other Google-specific problems I should mention as well. For one thing, it is unlikely to initially be able to work in an area that one is passionate about. Many of the Google products are exciting, but unfortunately I was unable to be passionate about my particular product area. That is not to say that there weren&#8217;t any interesting aspects about it, and I do have a lot of respect for the team I worked with. Overall this is less of a problem later, as it is generally encouraged to switch projects every 1-2 years, but this first year makes a big difference, particularly for experienced engineers that have a good understanding of what kind of things they enjoy working on (or perhaps more importantly, don&#8217;t enjoy working on) or what kind of environments are a good match. I feel that the hiring process should be improved to better take this into consideration, although this is admittedly a difficult logistical problem at Google&#8217;s scale. Another scale-related problem: Due to the sheer size of the code base and the vast number of Google-specific tools and frameworks, it also takes a very long time to learn how to actually become productive at Google, which can be frustrating at times.</p>

<p>But overall, I feel privileged that I had the chance to work at Google. I&#8217;m sure they will still be around for a long time, and 20 years from now I will be able to tell my grandchildren &#8220;Oh, Google, yes, I worked there once&#8230;&#8221;. I will certainly miss the Google campus, which had the vibrant feel of a University campus. I will also miss many things about the Google culture, and hopefully be able to take many of these inspirations with me into my future career.</p>

<p>Which brings me to my new job, which I am enormously excited about starting this Monday. I can&#8217;t say too much, as the company is just getting founded and still in stealth mode, but I am going to be a co-founder of a brand-new startup in the Social Networking / Mobile space, two areas I am very interested in. I have worked at small startups, but so far I&#8217;ve never had the opportunity to come in on the ground floor like this, so this should be a great adventure. My role is going to be that of Director of Engineering, but I expect to be wearing a lot of hats, ranging from architecture and implementation to being involved in the product direction, taking care of hosting and other IT stuff, and ultimately building a great team and helping define the company culture (although we will initially be a small core team). We will be working with some exciting technologies, including Ruby and a sprinkling of Ruby on Rails, which I am strongly looking forward to as well. Besides using a bit of Ruby at my previous job, I have mostly played with Ruby in my spare time, and I am glad about being able to finally use it again at my day job as well (though we will be pragmatic and use whatever tool makes most sense for the job at hand). I think I am officially done with Java at this point (but never say never&#8230; I am pretty sure I will at least use it again as a platform at some point in the future).</p>

<p>Well, this blog post turned out a bit longer than expected. But don&#8217;t worry, I am sure I will be busy enough at my startup that I won&#8217;t have a chance to bug you with any additional long posts for a while. <img src='http://www.digitalhobbit.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/04/13/on-leaving-google/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Evernote: A Promising Start</title>
		<link>http://www.digitalhobbit.com/archives/2008/03/15/evernote-a-promising-start/</link>
		<comments>http://www.digitalhobbit.com/archives/2008/03/15/evernote-a-promising-start/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 17:39:55 +0000</pubDate>
		<dc:creator>DigitalHobbit</dc:creator>
		
		<category><![CDATA[Mobile]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[Websites]]></category>

		<guid isPermaLink="false">http://www.digitalhobbit.com/archives/2008/03/15/evernote-a-promising-start/</guid>
		<description><![CDATA[After having signed up for an Evernote beta invite a while ago, I finally received one this week.

Evernote is a next generation note taking service. What sets it apart from similar applications are the numerous ways of entering as well as retrieving notes. First of all there is the Evernote Website. It is simple and [...]]]></description>
			<content:encoded><![CDATA[<p>After having signed up for an <a href="http://evernote.com/">Evernote</a> beta invite a while ago, I finally received one this week.</p>

<p>Evernote is a next generation note taking service. What sets it apart from similar applications are the numerous ways of entering as well as retrieving notes. First of all there is the <a href="http://preview.evernote.com/">Evernote Website</a>. It is simple and straightforward, and seems to be very responsive. You can create as many notebooks as you want. Each notebook acts like a folder that contains individual notes as files, and can be viewed using different perspectives (such as thumbnail view or list view), much like a native file browser application like Finder or Windows Explorer.</p>

<p>Notes can be entered and edited on the website, but there are several alternatives. For example, you can email a note to a special email address that is generated for you when you sign up. You can also use this mechanism to send notes from your mobile phone, using your provider&#8217;s SMS-Email gateway. However, I have been running into some technical issues when I attempted this from my mobile phone (I&#8217;m getting the following error message: <em>&#8220;Your MSG could not be DELIVERED because InvalidPduContent&#8221;</em>), so I need to look into this. Curiously, sending a picture via MMS worked just fine. Speaking of pictures: Evernote&#8217;s support for images is pretty amazing. It uses advanced text recognition to extract text from images, such that it becomes searchable. I have tested this with a low quality photo of a poster snapped from my mobile phone, and it worked as advertised. Very impressive!</p>

<p>You can also use a nifty bookmarklet that allows you to either submit an entire webpage to Evernote, or just the text that you have selected.</p>

<p>But perhaps most importantly, Evernote has a downloadable client app for both Windows and Mac. I have only tested the Mac client, which was released very recently. It seems to lag slightly behind its Windows counterpart in terms of features, but on the positive side it looks and feels like a proper Mac application rather than a quick port. It relies on a Sync feature to synchronize notes between the server and the client (either manually or in a configurable interval). Otherwise, the client offers pretty much the same functionality as the website. In addition, it comes with a clipping service that shows up in the menu bar (and registers some convenient keyboard shortcuts) and allows you to easily submit any copied text to the client, or even to clip a screenshot.</p>

<p>Evernote also has many ways to browse notes. It has a search box that allows you to find notes using full text search, but also using other criteria. For example, notes can be tagged (much like emails in Gmail), after which you can search for them by tag (or just click on the tag in the navigation bar). Notes can also be located via various attributes, such as creation or modification date, source (website, email, mobile, etc.), or whether or not they contain images or audio. This works from both the website or the native client. Evernote also has a mobile website, which I have not tested. This should be convenient when you need to look up a note while you&#8217;re on the road.</p>

<p>Overall, I am pretty impressed with Evernote. I have played with various note taking applications, and this comes very close to perfect in terms of features. I often have ideas that I need to capture, and right now I&#8217;m using a personal wiki for this purpose. However, I would prefer to work in a native application when possible, since this is generally more convenient. The combination of native client and website for Evernote is quite powerful, with a well-implemented synchronization mechanism. I just wish there were some wiki-like features, such as easy linking between individual notes. But the most important drawback is the lack of formatting options. The website only supports straight text entry, with no formatting at all. The Mac client supports rudimentary formatting (such as font, color, bold, italic, underline, alignment), but unfortunately this formatting appears to be lost when the note is uploaded to the website. The thumbnail view does show the properly formatted note, but the full view does not. And any edits on the website completely reset any formatting that might have been applied on the client. I don&#8217;t require any sophisticated formatting, but at the minimum I would need support bullet lists (which neither the Mac client nor the website supports), headings, and emphasis.</p>

<p>As it is right now, Evernote seems like a somewhat useful scratch pad to collect short notes, web clippings, etc. Particularly the mobile features might come in handy. With a bit of additional work, I think it could be extended to become a more comprehensive solution for organizing information, but right now I am going to continue using my wiki for this purpose.</p>

<p>If you would like to see it in action, there is a short <a href="http://www.evernote.com/video/">Evernote Screencast</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalhobbit.com/archives/2008/03/15/evernote-a-promising-start/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
