<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Rail Spikes - Home</title>
  <id>tag:railspikes.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://railspikes.com/" rel="alternate" type="text/html" />
  <updated>2009-07-01T01:44:29Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/RailSpikes" type="application/atom+xml" /><entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-07-01:2004</id>
    <published>2009-07-01T01:44:00Z</published>
    <updated>2009-07-01T01:44:29Z</updated>
    <category term="testing" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/OyM5ReRqqRY/testing-http-authentication" rel="alternate" type="text/html" />
    <title>Testing HTTP Authentication</title>
<content type="html">
            &lt;p&gt;If you ever need to test &lt;span class="caps"&gt;HTTP&lt;/span&gt; Authentication in your &lt;em&gt;functional&lt;/em&gt; tests, here is how you do it:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_http_auth&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@request&lt;/span&gt;.env[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;] = &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;HttpAuthentication&lt;/span&gt;::&lt;span class="co"&gt;Basic&lt;/span&gt;.encode_credentials(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;quentin&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:show&lt;/span&gt;, &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@foobar&lt;/span&gt;.id&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_response &lt;span class="sy"&gt;:success&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is much like &lt;a href="http://railspikes.com/2008/9/12/testing-ssl"&gt;testing &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Hat tip: Philipp Führer for &lt;a href="http://flip.netzbeben.de/2008/06/functional-test-for-http-authentication-in-rails-2/"&gt;Functional test for &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication in Rails 2&lt;/a&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/OyM5ReRqqRY" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/7/1/testing-http-authentication</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-22:1999</id>
    <published>2009-06-22T22:25:00Z</published>
    <updated>2009-06-25T06:41:10Z</updated>
    <category term="routes" />
    <category term="testing" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/of6fyG4oAyk/adding-routes-for-tests" rel="alternate" type="text/html" />
    <title>Adding Routes for Tests</title>
<content type="html">
            &lt;p&gt;I like to be extremely judicious with use of routes. Fewer routes means less memory consumption and fewer confusing magical methods.&lt;/p&gt;


	&lt;p&gt;I always delete the default route &lt;code&gt;map.connect ':controller/:action/:id'&lt;/code&gt; (you should too, otherwise all your pretty RESTful routing is easily circumvented). Since Rails now has the ability to remove unneeded RESTful routes, I’ve been removing those, too.&lt;/p&gt;


	&lt;p&gt;However, this judiciousness recently painted me into a corner. I have a controller action that I would like to test and it’s wired up like this:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :method =&amp;gt; 'delete'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;I don’t have this mapped any other way, because why should I?&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_logout_should_redirect_to_root_path&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;UserSession&lt;/span&gt;.create(&lt;span class="co"&gt;User&lt;/span&gt;.first)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  delete &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_match &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;logged out&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;, flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  assert_redirected_to root_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Unfortunately, the test fails with &lt;code&gt;ActionController::RoutingError: No route matches {:action=&amp;gt;"destroy", :controller=&amp;gt;"user_sessions"}&lt;/code&gt;! Huh?&lt;/p&gt;


	&lt;p&gt;The problem is that the &lt;code&gt;delete&lt;/code&gt; (and &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, etc.) method can’t find the route that I created.&lt;/p&gt;


	&lt;p&gt;Initially, I worked around this using &lt;code&gt;with_routing&lt;/code&gt; to define a whole new set of routes just for that test.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;with_routing &lt;span class="r"&gt;do&lt;/span&gt; |set|&lt;tt&gt;
&lt;/tt&gt;  set.draw &lt;span class="r"&gt;do&lt;/span&gt; |map|&lt;tt&gt;
&lt;/tt&gt;    map.resource &lt;span class="sy"&gt;:user_sessions&lt;/span&gt;, &lt;span class="sy"&gt;:only&lt;/span&gt; =&amp;gt; [&lt;span class="sy"&gt;:destroy&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    map.root &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;foobars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  delete &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_match &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;logged out&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;, flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  assert_redirected_to root_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;But that was annoying. And after I had more than one route exhibiting this problem, it got &lt;em&gt;really&lt;/em&gt; annoying.&lt;/p&gt;


	&lt;p&gt;Fortunately, I found Sam Ruby’s post &lt;a href="http://intertwingly.net/blog/2009/05/15/Keeping-Up-With-Rails"&gt;Keeping Up With Rails&lt;/a&gt; about the challenge of Rails’ minor, quasi-documented &lt;span class="caps"&gt;API&lt;/span&gt; changes. Sam’s post has a bit about how you can add new routes without clearing the existing routes in Rails 2.3.2, which I knew was possible. Following Sam’s link to &lt;a href="http://github.com/rails/rails/commit/40b40c487040d9c721d486e8ec8cfbc53a8cd79a"&gt;the commit&lt;/a&gt; (there’s no docs for this) showed how to do it.&lt;/p&gt;


	&lt;p&gt;Now, I’ve added this to &lt;code&gt;test_helper.rb&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ActionController::TestCase&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# add a catch-all route for the tests only.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;::&lt;span class="co"&gt;Routes&lt;/span&gt;.draw { |map| map.connect &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;:controller/:action/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The downside to this is that real problems with broken routes may get swept under the rug. You could be more restrictive with the routes you are adding just for tests to overcome that problem.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Thanks to Adam Cigánek in the comments for pointing out my error in why the route didn’t get picked up in the tests. &lt;em&gt;I had the condition hash wrong!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Instead of:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :method =&amp;gt; 'delete'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;It should be:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :conditions =&amp;gt; {:method =&amp;gt; :delete}&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;The first way I had worked correctly when testing manually, but only because without &lt;code&gt;:method&lt;/code&gt;, the route responds to all &lt;span class="caps"&gt;HTTP&lt;/span&gt; methods (still no clue why my test didn’t pick it up, though).&lt;/p&gt;


	&lt;p&gt;Interestingly enough, there’s another gotcha here. Notice that I specified &lt;code&gt;:method =&amp;gt; 'delete'&lt;/code&gt;. Even when put into the &lt;code&gt;:conditions&lt;/code&gt; hash, that doesn’t work. You &lt;span class="caps"&gt;MUST&lt;/span&gt; pass a symbol (&lt;code&gt;:delete&lt;/code&gt;) for the &lt;span class="caps"&gt;HTTP&lt;/span&gt; method.&lt;/p&gt;


	&lt;p&gt;This fixed my problem, but if I ever do need to add routes for tests, now I know how…&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/of6fyG4oAyk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/22/adding-routes-for-tests</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-17:1989</id>
    <published>2009-06-17T20:51:00Z</published>
    <updated>2009-06-17T20:54:57Z</updated>
    <category term="javascript" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/DScbpAz3dIw/javascript-gotcha-storing-objects-in-an-associative-array" rel="alternate" type="text/html" />
    <title>JavaScript gotcha: storing objects in an associative array</title>
<content type="html">
            &lt;p&gt;I just ran into a tricky gotcha in JavaScript.&lt;/p&gt;


	&lt;p&gt;I was trying to store some objects in an associative array. Based on my experience with Java, Ruby, and other languages, I expected that given code like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;var&lt;/span&gt; dictionary = {};&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;var&lt;/span&gt; obj1 = {}; &lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;var&lt;/span&gt; obj2 = {};&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;dictionary[obj1] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;dictionary[obj2] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The result of &lt;code&gt;dictionary[obj1]&lt;/code&gt; would be ‘foo’ and &lt;code&gt;dictionary[obj2]&lt;/code&gt; would be ‘bar’.&lt;/p&gt;


	&lt;p&gt;This is not the case!&lt;/p&gt;


	&lt;p&gt;The problem is that JavaScript objects are not really hash tables. They’re associative arrays, and the key can &lt;em&gt;only&lt;/em&gt; be a String. When you insert an object into a associative array, &lt;code&gt;toString()&lt;/code&gt; is called and that is used as the key. Unfortunately, the default &lt;code&gt;toString&lt;/code&gt; implementation for JavaScript objects returns “[object Object]”...which is not only very unhelpful when debugging, but doesn’t provide you with a unique key for your associative array.&lt;/p&gt;


	&lt;p&gt;You can work around this problem by overriding &lt;code&gt;toString&lt;/code&gt;. Or you can figure out another way to associate your object with a value. D’oh!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/DScbpAz3dIw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/17/javascript-gotcha-storing-objects-in-an-associative-array</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-04:1978</id>
    <published>2009-06-04T16:39:00Z</published>
    <updated>2009-06-04T16:42:50Z</updated>
    <category term="provisioning" />
    <category term="sprinkle" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/aTF68B6HJg8/sprinkle" rel="alternate" type="text/html" />
    <title>Sprinkle: the provisioning tool for people who don't have huge server clusters</title>
<content type="html">
            &lt;p&gt;I’ve recently been trying to find a good server automation tool that meets my needs. I looked at &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;Chef&lt;/a&gt; and &lt;a href="http://reductivelabs.com/trac/puppet/"&gt;Puppet&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;They are both awesome for what they do, but what I don’t like is all the infrastructure I have to maintain to run Chef or Puppet. You need a server to host your server configuration on. But I only have one server![1] Chef does have a &lt;a href="http://wiki.opscode.com/display/chef/Chef+Solo"&gt;solo version&lt;/a&gt; which can download configuration from a web server and run it. That’s cool, but I don’t want to have a web server just for putting server configuration on.&lt;/p&gt;


	&lt;p&gt;When the time commitment to set up one of these tools up greatly exceeds how long it is for me to bring up a new slice and run through the standard Apache/DB/Passenger stack, I lose interest. In the end, these are great tools for managing a cluster of machines and bringing up a new app in the cluster quickly—and keeping it up to date automatically. If you have big infrastructure needs, they make sense. If you just want to set up a single slice…ugh.&lt;/p&gt;


	&lt;p&gt;After reading a bit about how Puppet and Chef work, what I really wanted was the ability to &lt;em&gt;push&lt;/em&gt; server provisioning recipes. I want to maintain the server config in my repository and then provision a new server with a command I run on my machine. Sort of like &lt;a href="http://deprec.failmode.com/"&gt;deprec&lt;/a&gt;, but understandable.&lt;/p&gt;


	&lt;p&gt;Fortunately, I found &lt;a href="http://github.com/crafterm/sprinkle/tree/master"&gt;Sprinkle&lt;/a&gt; and &lt;a href="http://benschwarz.github.com/passenger-stack/"&gt;passenger-stack&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Sprinkle lets me quickly define which packages I want installed and push it out to a server to run (via Capistrano, Vlad, or Net::SSH). Sprinkle makes it easy to install software using apt, gem, or source. And unlike a simple shell script, Sprinkle tests whether or not the software is installed before running, and has a concept of dependencies.&lt;/p&gt;


	&lt;p&gt;Passenger-stack removes the pain of writing my own rules for what to install. It comes with the standard stuff you’d need, and you can customize it from there.&lt;/p&gt;


	&lt;p&gt;Here’s how you install all the software you need for a fresh server, after downloading &lt;a href="http://benschwarz.github.com/passenger-stack/"&gt;passenger-stack&lt;/a&gt;:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;sprinkle -c -s config/install.rb&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;The best part is that you can run that command again, and it won’t do anything. So you can add new software to your stack, then run it against your server, and only the new software will get installed.&lt;/p&gt;


	&lt;p&gt;This gives you a great way to manage natively compiled gems and ensure that if you ever need to spin up a staging server or a demo server, everything you need gets installed.&lt;/p&gt;


	&lt;p&gt;Check out this screencast by Ben Schwartz, author of passenger-stack.&lt;/p&gt;


&amp;lt;object height="360" width="640"&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2888665&amp;amp;amp;server=vimeo.com&amp;amp;amp;show_title=1&amp;amp;amp;show_byline=1&amp;amp;amp;show_portrait=0&amp;amp;amp;color=00ADEF&amp;amp;amp;fullscreen=1" height="360" width="640"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/2888665"&gt;Passenger-stack demo&lt;/a&gt; from &lt;a href="http://vimeo.com/user1015730"&gt;Ben Schwarz&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;

	&lt;p&gt;It’s not a smart as Chef and Puppet. It’s not transactional and servers don’t check for new software to install automatically. But it sure is easy. That’s why I call &lt;a href="http://github.com/crafterm/sprinkle/tree/master"&gt;Sprinkle&lt;/a&gt; “the provisioning tool for people who don’t have huge server clusters.”&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Basically. I have many servers with many different applications on them. And I have a few servers that have multiple environments, but the same software. That’s my big driver for wanting a provisioning tool.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/aTF68B6HJg8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/4/sprinkle</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-06-02:1980</id>
    <published>2009-06-02T16:06:00Z</published>
    <updated>2009-06-02T16:27:48Z</updated>
    <category term="Business" />
    <category term="Programming" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/gl7KwwlhsUE/estimating-software-a-rule-of-thumb" rel="alternate" type="text/html" />
    <title>Estimating software: a rule of thumb</title>
<content type="html">
            &lt;p&gt;Estimating software is hard, but most of us have to do it – whether we’re estimating an entire project for a client, or a new feature for a boss, or  a change to one of our own projects.&lt;/p&gt;


	&lt;p&gt;I’ve found the following rule helpful when estimating software. This comes from about four years of estimating Rails projects to consulting clients, and moving from bad – dramatically underestimating fixed-bid projects – to pretty good – usually overestimating time &amp; materials projects slightly. (And more importantly, knowing when I can’t estimate, because the scope is too vague or too large.)&lt;/p&gt;


	&lt;h2&gt;Jon’s Law of Estimates&lt;/h2&gt;


	&lt;p&gt;Software difficulty is primarily determined by &lt;em&gt;volume&lt;/em&gt;, &lt;em&gt;logic&lt;/em&gt;, and &lt;em&gt;integration&lt;/em&gt;.&lt;/p&gt;


	&lt;h2&gt;Jon’s Law of Estimates, explained&lt;/h2&gt;


	&lt;p&gt;1. &lt;strong&gt;Volume&lt;/strong&gt; is easy to understand. If you’re building software that does more, it will require more work. So if you’re estimating a project that stores recipes, and you’re estimating another project that stores recipes &lt;span class="caps"&gt;AND&lt;/span&gt; shopping lists, you can expect that the second one will take more work (if everything else is equal).&lt;/p&gt;


	&lt;p&gt;2. &lt;strong&gt;Logic&lt;/strong&gt; refers to the rules or business logic behind a feature. The more rules there are, the more work there is. Imagine that our recipe system requires that recipes from some users are manually approved by an administrator, and checks to see that each ingredient in the recipe is present in the step-by-step instructions, and only allows a user to post 3 recipes per hour, and lets users propose alternative versions of a recipe, and lets an alternative version replace the regular version if it achieves a certain rating, etc. That’s more work than a recipe system that just lets users create and rate recipes, even though the volume of features may not be any larger.&lt;/p&gt;


	&lt;p&gt;Interestingly, a technology can make some logic trivial and some logic hard. &lt;a href="http://rails.uservoice.com/pages/rails3/suggestions/99641-nested-model-forms"&gt;Nested forms&lt;/a&gt; are a great example of this. Before Rails 2.3, Rails made it trivial to do &lt;span class="caps"&gt;CRUD&lt;/span&gt; on a single table at a time, but difficult handle multiple tables. Now it is (almost) trivial to do &lt;span class="caps"&gt;CRUD&lt;/span&gt; on multiple tables at a time.&lt;/p&gt;


	&lt;p&gt;3. &lt;strong&gt;Integration&lt;/strong&gt; points are usually deserving of special consideration in an estimate. This includes talking to a web services &lt;span class="caps"&gt;API&lt;/span&gt;, another local software system, a data feed, a complex library, etc. Not only do integration points often take time to get right, but they can become sinkholes of time when the documentation is inadequate or incorrect, the other system doesn’t play nice, or you can’t easily test the integration. And your estimate depends on something out of your control: the other system.&lt;/p&gt;


	&lt;h2&gt;External factors&lt;/h2&gt;


	&lt;p&gt;These rules only apply to the difficulty of the software. Several external factors are important as well. These include, most notably, the &lt;strong&gt;client&lt;/strong&gt; and the &lt;strong&gt;team&lt;/strong&gt;. The client can make a project easy, or they can make a project difficult. Similarly, the right team might be able to blaze through a project quickly, while the wrong team may never finish at all.&lt;/p&gt;


	&lt;h2&gt;The other side of estimating&lt;/h2&gt;


	&lt;p&gt;Here’s the thing about these rules: they’re relative, not absolute. There is no rule that says “Features take 5 days, and integration points take 10”. So estimating requires comparisons. This means that if you’ve never built a Rails app before, you’ll have trouble estimating a Rails project. But once you’ve built a few, you can compare the volume, logic, and integration points of a new project to volume, logic, and integration points of the previous ones.&lt;/p&gt;


	&lt;p&gt;So estimating requires intuition and experience as well as analysis (e.g. Jon’s Law of Estimates). The key to estimating is to combine analysis and intuition, and to let each side refine the other.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/gl7KwwlhsUE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/2/estimating-software-a-rule-of-thumb</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-05-10:1972</id>
    <published>2009-05-10T20:07:00Z</published>
    <updated>2009-05-10T20:08:46Z</updated>
    <category term="twitter" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/M7sssUH-BB8/announcing-velotweets" rel="alternate" type="text/html" />
    <title>Announcing VeloTweets, Pulse of the Peloton</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://velotweets.com"&gt;&lt;img src="http://img.skitch.com/20090510-1xh56ct6uya88idy4exf2gdmu9.png" height="" width=""&gt;&lt;/a&gt; I’m pleased to announce &lt;a href="http://velotweets.com"&gt;VeloTweets&lt;/a&gt;, the pulse of the peloton, a curated collection of professional cycling Twitter activity. The idea and driving force came from &lt;a href="http://www.thingelstad.com/"&gt;Jamie Thingelstad&lt;/a&gt;. I did most of the development, and &lt;a href="http://orstaddesign.com/"&gt;Norm Orstad&lt;/a&gt; designed the site. &lt;a href="http://twitter.com/mindtron"&gt;Chris Hatch&lt;/a&gt; helped a lot on the back end, providing a list of cyclists on Twitter, filling out profiles and affiliations, and doing research.&lt;/p&gt;


	&lt;h2&gt;What’s Different about VeloTweets?&lt;/h2&gt;


	&lt;p&gt;We wanted to make VeloTweets different than the other subject matter aggregators out there. We wanted a hook that would combine the immediacy of Twitter with pro cycling in a compelling way.&lt;/p&gt;


	&lt;p&gt;Here’s what we came up with.&lt;/p&gt;


	&lt;p&gt;First, we focused on who to include. Instead of everyone who’s talking about cycling, this contains only pro cyclists (and a few others associated with the sport, like managers or team mechanics).&lt;/p&gt;


	&lt;p&gt;Second, we extended the data that is given to us by Twitter. We can enter every cyclist’s real name, nationality, and team, as well as expanded biographical data (here’s &lt;a href="http://www.velotweets.com/profiles/10"&gt;Lance Armstrong’s profile&lt;/a&gt; for instance).&lt;/p&gt;


	&lt;p&gt;Third, we collected cycling events in a &lt;a href="http://www.velotweets.com/events"&gt;calendar&lt;/a&gt; that’s displayed on the site, and added a Message of the Day that’s tuned to what’s happening in the racing world each day.&lt;/p&gt;


	&lt;p&gt;Forth, we brought in photos from the tweets (only &lt;a href="http://twitpic.com"&gt;TwitPic&lt;/a&gt; is supported right now). We store references to the photos in our DB so we can show the latest photos, along with photos that individuals have posted, and &lt;a href="http://velotweets.com/photos"&gt;all of them&lt;/a&gt;. This turns out to be really cool because where else are you going to see &lt;a href="http://twitpic.com/4rut7"&gt;photos like this one&lt;/a&gt; as they happen?&lt;/p&gt;


	&lt;p&gt;After all this we still weren’t totally satisfied with what we’d come up with, because it still looked too much like Twitter (long list of messages in reverse chronological order). Then Jamie came up with the idea of only displaying each cyclist’s most recent tweet in a grid. We really like how this works because people who tweet a lot (like Lance) don’t dominate the page. It gives you an overview of what the whole peloton is talking about without letting a few people dominate it.&lt;/p&gt;


	&lt;h2&gt;Behind the scenes&lt;/h2&gt;


	&lt;p&gt;This application uses Rails 2.3, the &lt;a href="http://github.com/thoughtbot/suspenders/tree/master"&gt;Suspenders base app&lt;/a&gt;, &lt;a href="http://github.com/hcatlin/make_resourceful/tree/master"&gt;make_resourceful&lt;/a&gt;, &lt;a href="http://github.com/rubypond/semantic_form_builder/tree/master"&gt;semantic_form_builder&lt;/a&gt; and the excellent &lt;a href="http://dev.ctor.org/http-access2"&gt;HTTPClient&lt;/a&gt; library for interacting with Twitter (give up on net/http – &lt;a href="http://olabini.com/blog/tag/httpclient/"&gt;it is full of fail&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;Twitter &lt;span class="caps"&gt;API&lt;/span&gt; access is done directly with &lt;span class="caps"&gt;JSON&lt;/span&gt;. We pull the &lt;code&gt;friends_timeline&lt;/code&gt; and insert those tweets into the database.&lt;/p&gt;


	&lt;h2&gt;Developing for Twitter&lt;/h2&gt;


	&lt;p&gt;I’ve been doing a number of Twitter-related projects lately. The first was &lt;a href="http://twistr.org"&gt;Twistr&lt;/a&gt;, which combines Twitter and Flickr LOLcat style for occasionally amusing results. Then &lt;a href="http://bjhess.com"&gt;Barry Hess&lt;/a&gt; and I built &lt;a href="http://followcost.com"&gt;Follow Cost&lt;/a&gt;, which tells you how much someone tweets &lt;em&gt;before&lt;/em&gt; you follow them. I created &lt;a href="http://fanchatter.com"&gt;a prototype for FanChatter’s next product&lt;/a&gt; based on Twitter conversation aggregation. Now comes VeloTweets and another project that’s not public yet.&lt;/p&gt;


	&lt;p&gt;I really enjoy working with the Twitter APIs. It’s fun to develop applications that utilize the platform that the Twitter folks have built.&lt;/p&gt;


	&lt;p&gt;On that front, I recently received a copy of &lt;a href="http://www.amazon.com/gp/product/0596154615?ie=UTF8&amp;amp;#38;tag=justlook-20&amp;amp;#38;linkCode=as2&amp;amp;#38;camp=1789&amp;amp;#38;creative=390957&amp;amp;#38;creativeASIN=0596154615"&gt;Twitter &lt;span class="caps"&gt;API&lt;/span&gt;: Up and Running&lt;/a&gt; (Follow Cost is mentioned on page 70!) which I will give a full review to soon. You don’t &lt;em&gt;need&lt;/em&gt; a book on the Twitter &lt;span class="caps"&gt;API&lt;/span&gt; to develop applications for it, but it does provide some ideas and a useful reference, as well as details on some interesting aspects of Twitter (for example, I did not know that direct messages disappear if they are deleted by either party.).&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/M7sssUH-BB8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/5/10/announcing-velotweets</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-04-30:1966</id>
    <published>2009-04-30T18:49:00Z</published>
    <updated>2009-04-30T18:50:06Z</updated>
    <category term="music" />
    <category term="railsconf" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/8HX2zDXhDGk/music-and-programming-interviews-with-chad-fowler-and-dave-thomas" rel="alternate" type="text/html" />
    <title>Music and programming: interviews with Chad Fowler and Dave Thomas</title>
<content type="html">
            &lt;p&gt;I’ll be speaking at &lt;a href="http://en.oreilly.com/rails2009/"&gt;RailsConf 2009&lt;/a&gt; this year on music and software development (&lt;a href="http://en.oreilly.com/rails2009/public/schedule/detail/7494"&gt;Five musical patterns for programmers&lt;/a&gt;). The basic premise is that software development and music actually have quite a bit in common. This may be surprising to some people, who see programming as a cold, rational left-brain sort of thing, like science. But we programmers know that this is not really the case at all.&lt;/p&gt;


	&lt;p&gt;So as a prelude to my talk, I decided to interview two programmer-musicians on the subject: Chad Fowler and Dave Thomas. Both compose and perform music, and both are noted programmers. Here is the interview.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Tell us a little about your background with both programming and music.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; I started my professional life as a saxophonist in Memphis. I played the Beale street clubs and all the typical Memphis professional musician stuff.  Among others, I played for a while with &lt;a href="http://en.wikipedia.org/wiki/Ann_Peebles"&gt;Ann Peebles&lt;/a&gt; and her husband &lt;a href="http://project.ioni.st/2007/11"&gt;Don Bryant&lt;/a&gt; with the rhythm section from all the old &lt;a href="http://www.hirecords.com/"&gt;Hi Records&lt;/a&gt; recordings. I did mostly R&amp;B and jazz professionally but I was probably most well known in the Memphis community for making “strange” music. Before playing music professionally, I played guitar in punk bands in high school.  I was a fan of punk, heavy metal, hip hop, pop, (new) classical and pretty much everything else.  As I immersed myself in the world of jazz, it became quickly clear that the jazz community doesn’t like punk and other less “serious” types of  music and has an almost religious negative reaction to jazz musicians who  do.&lt;/p&gt;


	&lt;p&gt;It was almost as if any deviation from the “normal” world of jazz made you a traitor. So I did the natural thing: started a group called The Jazz Traitors, which played music that 1) we loved and 2) offended the jazz community (not necessarily in that order).&lt;/p&gt;


	&lt;p&gt;I was also very interested in composing “classical” music. I studied with a composer named &lt;a href="http://kamrancince.com"&gt;Kamran Ince&lt;/a&gt;, who is still my favorite such composer.&lt;/p&gt;


	&lt;p&gt;As for programming, I’ve been interested in programming since I was a young child using my commodore 64. I wasn’t really that good at it as a kid but I played around a lot. I didn’t get serious until I picked up programming again as a hobby while I was a professional musician. After a late night gig at a bar, it was relaxing to go home and unwind to some C programming tutorials. I didn’t have a &lt;em&gt;need&lt;/em&gt; to program, nor did I have a project in mind (except that I have always loved video games and wanted to learn how they worked). But I got so into it, that I ended up getting a job in computer support because a friend filled out an application for me.&lt;/p&gt;


	&lt;p&gt;Being the gamer I am, as soon as I started in computer support, I naturally wanted to “level up”. That meant becoming a network administrator. Then a system administrator. Then a programmer, then a designer, then an architect, then a &lt;span class="caps"&gt;CTO&lt;/span&gt;, etc.  Now here I am. It’s been fun.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; There was always a lot of music in our house. My father liked to play the piano and the organ (I learned to solder as he built a Heathkit organ from a kit in the late 60s). My mother liked Broadway musicals. So we’d often experience alternating hours of Chopin and South Pacific. My brother was also musical. I wasn’t particularly, but I enjoyed noodling on the piano, and spent hours just playing with chords and progressions.&lt;/p&gt;


	&lt;p&gt;I’ve been programming since I was 15 or so.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Some developers – yourself included – have suggested a similarity between programming and music composition or performance. How exactly are music and programming similar?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; I’m not sure, but I think it might be something to do with the discovery of patterns. Both music and code consist of nested sets of variations and repetitions. There’s a rythm to executing code, in the same way there’s a rythm to music. It is never exact, but it’s there. After a while, I found I could imagine the rythm and structure of my programs as they run, in the same way you can pick apart the structure of a piece of music as you listen to it. And, jsut as with music, it takes experience to be able to feel the deeper structures and notice the more extreme variations. But being able to spot them in programs makes coding simpler and more interesting. The basic coding structures—loops, method calls, and so on—provide the framework for composing in the same way that staff and bar lines do for music. Algorithms are like the progressions, and data becomes the notes. And in the same way that good music takes all these things and then surprises you, good code does the same thing. It isn’t mechanical and repetitive: instead it uses the constraints to build something bigger and more interesting.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; It’s hard for me to put my finger on. There’s something similar in the way I think when I do each.&lt;/p&gt;


	&lt;p&gt;I think it all boils down to language, though. In all of these cases (including learning actual language), you take a bunch of tokens (notes, sounds, grunts, functions, classes) and combine them into a grammar which you use to express ideas. The way you do that is totally up to you as long as the intended ideas are communicated. With computer programs, they have to do what they’re meant to do. With music, they express or evoke emotions, paint pictures, cause anxiety or whatever.&lt;/p&gt;


	&lt;p&gt;Some computer programs evoke emotions and cause anxiety as well.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Is Ruby development more like improvised jazz or composed classical music?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; I think it’s both. And I don’t think Ruby is any different in this than other languages. Much of the discussion about the relationship between programming and music focuses on the more obvious idea of programming as composition. It makes sense, since programmers tend to sit and type their ideas into an editor and then eventually execute it. The programs can be checked, tested, refactored, etc. before the actual performance. This is how classical composition works as well.&lt;/p&gt;


	&lt;p&gt;But the less obvious angle is that in many situations, programming is like performance. In fact, even in music, improvisation  is really just real time composition. You don’t get a chance to refactor because your “code” is executed as you write it.&lt;/p&gt;


	&lt;p&gt;I’ve had this same feeling while debugging production problems, hacking new features on a tight deadline, or sometimes during the initial creation of an application. The same synapses are firing as when I was trying to play Cherokee at 200 beats per minute. Mistakes can’t be erased, so they have to be nuanced into (worst case) insignificant events or (best case) important drivers behind the work.&lt;/p&gt;


	&lt;p&gt;From a purely development-oriented perspective, &lt;span class="caps"&gt;TDD&lt;/span&gt; is more like improvisation than composition. I think that’s what I like about it. It’s motivating and creative in an exciting, time-sensitive way. You take small steps and see where they lead you. Sure, you can always revert your changes if you paint yourself into a corner but part of the fun and challenge is to not paint yourself into a corner.&lt;/p&gt;


	&lt;p&gt;One thing jazz musicians like to say is that every wrong note is just a half step away from a right note. &lt;span class="caps"&gt;TDD&lt;/span&gt; is like that. You might take a slightly wrong turn. It’s fun to see if you can course-correct without starting over.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Do developers need to be musically inclined? Does it help?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; Obviously not. Some of the best programmers I know are not musicians. I can’t tell if it helps, but I would guess that developers who are also musicians are different than developers who aren’t. I don’t think that’s because being a musician changes people, though. I think it’s because the people who are both are the kind of people who &lt;em&gt;need&lt;/em&gt; to do both.&lt;/p&gt;


	&lt;p&gt;This usually means they’re “right brain” people. This leads to a way of thinking that changes how they approach programming problems.&lt;/p&gt;


	&lt;p&gt;I think learning music (or another right brain discipline) is a good way to exercise your mind. So I wouldn’t be surprised if leaning music helps people exercise their thought processes in ways that will benefit their work as programmers (or authors, or lawyers, or doctors or whatever).&lt;/p&gt;


	&lt;p&gt;I also think, though, that if we were all musicians at heart, we wouldn’t get much done. I rely heavily on my less artsy colleagues to ground me and be sometimes more pragmatic than I am. So I don’t think we all need to be a “right brain” programmer. It would be disasterous if we were.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; Do they need to be? No. But many of the good ones I know are. I’d guess that density of musicians in software development is many times the population norm. But that means you could also ask the question “Do musicians have to know software development?”&lt;/p&gt;


	&lt;p&gt;I think the more interesting question is to ask “how can people best express what they enjoy doing?” because both music and software development are outlets for this.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; What sort of music do you listen to? Any recommendations for Ruby developers looking to expand their musical horizons?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; As I mentioned earlier, I like all kinds of music (with a few exceptions). Lately I’ve been listening to a lot of instrumental hip hop, such as DJ Qbert and Mixmaster Mike. I’ve also been getting into a genre of electronic music called “electro”, which sounds like the bleeps and bloops that are the soundtrack of my dreams (if a computer is going to generate music I always like it to sound like a computer generated it).&lt;/p&gt;


	&lt;p&gt;As for recommendations, here are a few ideas for things that most developers probably haven’t listened to:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://kamranince.com"&gt;Kamran Ince&lt;/a&gt; – He was my composition teacher and, I think, an accessible introduction to the world of “new music”, which is what we call new composed “classical” music. The term “classical” is a widely spread misnomer. It actually refers to music written in the late 18th and early 19th centuries, but most people use it to mean high brow music written for instruments like violins. So whatever you call it, Kamran Ince writes some beautiful instances of it. Specifically check out his chamber music, such as Domes and Arches.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://charliewood.us"&gt;Charlie Wood&lt;/a&gt; – I have had the pleasure of playing with Charlie on a few occasions. He is a R&amp;B singer/organist/composer from Memphis and writes some of the most intelligent songs you’ll hear. My favorite album of his is “Who I Am”.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.tzadik.com/"&gt;John Zorn&lt;/a&gt; – Zorn has been around for a long time and is a leader in the world of Avant Garde music. He’s also one of the most amazing saxophonists ever. If you’re new to this kind of thing, his Masada quartet (“radical Jewish music”) produces some great stuff that’s accessible to first time listeners. If you’re looking for something to shock your aural taste buds, try Painkiller (metal-tinged noise) or Naked City.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; I listen to just about anything that’s interesting. My playlist here is very varied, and I try to add new stuff to it farily regularly. I know people who are trained as musicians, and I tend to ask them what they’re listening to. Sometimes that leads to challenges: my ear isn’t as developed as their ears. But often it leads to whole new areas of cool stuff. So I’d recommend everyone should find a friend who knows more than you do about music and ask them to surprise and challenge you. (That advice probably applies to just about everything, thinking about it.) It’s easy to find music that stimulates your lizard brain. Get into the habit of looking for the stuff that engages at a higher level too. And, like everything, have fun with it.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/8HX2zDXhDGk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/4/30/music-and-programming-interviews-with-chad-fowler-and-dave-thomas</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-04-08:1957</id>
    <published>2009-04-08T19:10:00Z</published>
    <updated>2009-04-08T19:13:18Z</updated>
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/17crtOgctvg/how-to-anonymize-data-with-rake" rel="alternate" type="text/html" />
    <title>Anonymize sensitive data with rake</title>
<content type="html">
            &lt;p&gt;When troubleshooting a nasty bug, it’s often useful to take a look actual production or staging data, or even pull it down into your development database. But this is a huge potential privacy and security concern. Your local environment likely isn’t as secure as your production environment, and you might not want to access this sensitive data (or give it to another team member).&lt;/p&gt;


	&lt;p&gt;Similarly, you might want to replicate your production data on a staging or QA environment to see how new code will interact with real data. Also a privacy concern.&lt;/p&gt;


	&lt;p&gt;Simple solution: anonymize the data!&lt;/p&gt;


	&lt;p&gt;In my current project, I put together an &lt;a href="http://gist.github.com/91930"&gt;anonymize.rake&lt;/a&gt; task to deal with this. The most sensitive data in our app is name and phone number. Without that, private information can’t really be linked back to someone. So I pulled the 200 most common first names and 1000 most common last names (in the United States) and put them into an Anonymizer class. Call Anonymizer.random_name for a random, but realistic, name. The class also includes a simple phone number and email anonymizer.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Anonymizer&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.random_name&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;random_first_name&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;random_last_name&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.random_first_name&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;FIRSTNAMES&lt;/span&gt;[rand(&lt;span class="co"&gt;FIRSTNAMES&lt;/span&gt;.size)]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.random_last_name&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;LASTNAMES&lt;/span&gt;[rand(&lt;span class="co"&gt;LASTNAMES&lt;/span&gt;.size)]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.random_phone&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;612-555-&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;rand(&lt;span class="i"&gt;8000&lt;/span&gt;) + &lt;span class="i"&gt;1000&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;FIRSTNAMES&lt;/span&gt; = &lt;span class="s"&gt;&lt;span class="dl"&gt;%w(&lt;/span&gt;&lt;span class="k"&gt;James&lt;tt&gt;
&lt;/tt&gt;  John&lt;tt&gt;
&lt;/tt&gt;  Robert&lt;tt&gt;
&lt;/tt&gt;  Michael&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  # etc.&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The rake task is simple:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;namespace &lt;span class="sy"&gt;:db&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  namespace &lt;span class="sy"&gt;:data&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    desc &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Anonymize sensitive information&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    task &lt;span class="sy"&gt;:anonymize&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:environment&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="co"&gt;RAILS_ENV&lt;/span&gt; == &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Refusing to anonymize production data. You don't really want to do that.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Anonymizing all name and email records in the &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; database.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# User.find(:all).each do |user|&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# user.name = Anonymizer.random_name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# user.email = Anonymizer.random_email(user.name)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# puts &amp;quot;Saving #{user.name} (#{user.email})&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# user.save!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You’ll need to do the actual implementation yourself (see the sample &lt;code&gt;User.all.each {} block&lt;/code&gt;). It would be easy enough to extend this to work with social security numbers, addresses, etc. Run with:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;rake db:data:anonymize&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Code: &lt;a href="http://gist.github.com/91930"&gt;anonymize.rake&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/17crtOgctvg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/4/8/how-to-anonymize-data-with-rake</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-04-03:1946</id>
    <published>2009-04-03T14:46:00Z</published>
    <updated>2009-04-06T21:56:31Z</updated>
    <category term="Programming" />
    <category term="rails" />
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/t_6M4jmua9s/rails-test-benchmarks" rel="alternate" type="text/html" />
    <title>Benchmarking your Rails tests (updated)</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Update: stubbing a single integration point shaved 22 seconds off of my unit tests, reducing test time from 35 seconds to 13. See below.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;The first step to &lt;a href="http://railspikes.com/2009/3/10/slow-tests-are-a-bug"&gt;faster tests&lt;/a&gt; is knowing what is slow. Fortunately, this is dead simple with the &lt;a href="http://github.com/timocratic/test_benchmark/tree/master"&gt;test_benchmark plugin&lt;/a&gt; by &lt;a href="http://www.timocracy.com/"&gt;Tim Connor&lt;/a&gt;, and originally built by &lt;a href="http://nubyonrails.com/"&gt;Geoffrey Groschenbach&lt;/a&gt;. Install the plugin, and when you run your tests via Rake, you’ll see handy output showing you the slowest tests, and the slowest test classes.&lt;/p&gt;


	&lt;h2&gt;Step 1: Install the plugin.&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;script/plugin install git://github.com/timocratic/test_benchmark.git&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Step 2: Run your tests&lt;/h2&gt;


	&lt;p&gt;&lt;code&gt;rake test&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Here is a bit of output when I run the unit tests for &lt;a href="http://fanchatter.com"&gt;FanChatter&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Finished in 34.838173 seconds.

Test Benchmark Times: Suite Totals:
25.393 MailReceiverTest
4.520 PhotoTest
1.429 REXMLTest
0.961 TeamTest
0.846 MessageTest
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Pretty useful information. Almost 75% of our unit testing time is taken up in the MailReceiverTest. So if we want to speed up our tests, we need to make our &lt;span class="caps"&gt;MMS&lt;/span&gt; testing faster. Looking at that code, I see this line over and over:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;MailReceiver&lt;/span&gt;.receive(fixture_mms(&lt;span class="sy"&gt;:fixture_name&lt;/span&gt;))&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This method reads a test email message from the filesystem, and runs it through our mail parsing method. This is basically an integration test, hitting at least two integration points. So if we can remove these bottlenecks, we can reasonably expect a fairly large improvement in our unit test speed.&lt;/p&gt;


	&lt;p&gt;I think we could realistically reduce our unit testing time from 34 seconds to &amp;lt;15&gt;&lt;/p&gt;


	&lt;h2&gt;Other options&lt;/h2&gt;


	&lt;p&gt;The test_benchmark plugin fires whenever you run your tests with &lt;code&gt;rake&lt;/code&gt;. Tim recently patched the plugin to &lt;em&gt;not&lt;/em&gt; fire when run with &lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;autotest&lt;/a&gt;, which is great. Personally, though, I don’t want to see this benchmark information every time I run my tests. So I added the following line to my test.rb environment file:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;ENV['BENCHMARK'] ||= 'none'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Now, the benchmarks don’t run by default. If I want to see them, I call:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;rake test BENCHMARK=true&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;And if to see full tests, showing the time it takes to run every test in the system, just call:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;rake test BENCHMARK=full&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;That’s it. You still have to speed up your tests, and there are many ways to do that (from mocking to simply reducing the number of calls to expensive methods), but knowing what’s slow is half the battle.&lt;/p&gt;


	&lt;h2&gt;The stirring conclusion (update)&lt;/h2&gt;


	&lt;p&gt;I spent a few minutes optimizing these slow tests today. First, I tried rearranging the tests to reduce unnecessary calls to the slow method (&lt;code&gt;MailReceiver.receive(message)&lt;/code&gt;). I was able to speed MailReceiverTest from about 25 seconds to 17. Not bad, but still slow.&lt;/p&gt;


	&lt;p&gt;The real problem is that this method saves a photo. It creates a Photo record that includes a file, treated sort of like an upload, like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;photo.uploaded_data = mms.file&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is what was slow. But my unit tests don’t actually deal with the file being saved to the filesystem; they test other things, like the right records being created, confirmation emails being sent, etc.&lt;/p&gt;


	&lt;p&gt;So I decided to try bypassing this file save/upload by stubbing the &lt;code&gt;uploaded_data=&lt;/code&gt; method. I put the following at the top of my test class:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;setup&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Photo&lt;/span&gt;.any_instance.stubs(&lt;span class="sy"&gt;:uploaded_data=&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And &lt;em&gt;voila!&lt;/em&gt; &lt;code&gt;MailReciverTest&lt;/code&gt; went from 25 seconds to 17 seconds to 3 seconds.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/t_6M4jmua9s" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/4/3/rails-test-benchmarks</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-03-30:1941</id>
    <published>2009-03-30T14:00:00Z</published>
    <updated>2009-03-31T04:19:14Z</updated>
    <category term="rails" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/_owYwJ6PUgQ/10-cool-things-in-rails-23" rel="alternate" type="text/html" />
    <title>10 Cool Things in Rails 2.3</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;This was presented to the &lt;a href="http://ruby.mn"&gt;Ruby Users of Minnesota&lt;/a&gt; on March 30, 2009.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Here’s a quick look at 10 new Rails features that I think are cool. Not all of them are huge new features, but instead help solve annoying problems. I’ve also created a simple application that demonstrates most of these features. You can &lt;a href="http://bitbucket.org/look/rails23-10coolfeatures/src/"&gt;get it at BitBucket&lt;/a&gt;&lt;/p&gt;


&lt;div&gt;&lt;a href="http://www.slideshare.net/lukefrancl/10-cool-things-about-rails-23?type=powerpoint" title="10 Cool Things About Rails 2.3"&gt;10 Cool Things About Rails 2.3&lt;/a&gt;&amp;lt;object height="355" width="425"&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=10coolthingsaboutrails2-3-090329160723-phpapp01&amp;amp;#38;stripped_title=10-cool-things-about-rails-23" height="355" width="425"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;div&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/lukefrancl"&gt;lukefrancl&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;

	&lt;h2&gt;1. Rails Boots Faster in Development Mode&lt;/h2&gt;


	&lt;p&gt;This is something all Rails developers can appreciate. In development mode, Rails now lazy loads as much as possible so that the server starts up much faster.&lt;/p&gt;


	&lt;p&gt;This is so fast, instead of replying on reloading (which doesn’t pick up changes to gems, lib directory, etc) one developer wrote a script (does anyone have the link for this?) that watches for file system changes and restarts your &lt;code&gt;script/server&lt;/code&gt; process.&lt;/p&gt;


	&lt;p&gt;Using an empty Rails app, I got the following (totally non-scientific) real times for &lt;code&gt;time script/server -d&lt;/code&gt;:&lt;/p&gt;


	&lt;p&gt;Rails 2.2: 1.461s&lt;br /&gt;
Rails 2.3: 0.869s&lt;/p&gt;


	&lt;p&gt;Presumably this difference would grow as more libraries were used, because Rails 2.3 will lazy load them. However I was too lazy to build up equivalent Rails 2.2 and 2.3 applications to try that out.&lt;/p&gt;


	&lt;h2&gt;2. Rails Engines Officially Supported&lt;/h2&gt;


	&lt;p&gt;Inspired by Merb’s slices implementation, Rails added official support for Engines, which are self-contained Rails apps that you can install into another application. Engines can have their own models, controllers, and views, and add their own routes.&lt;/p&gt;


	&lt;p&gt;Previously this was possible using the Engines plugin, but Engines would often break between Rails versions. Now that they are officially supported, this should be less frequent.&lt;/p&gt;


	&lt;p&gt;There are still some features from the unofficial Engines plugin that are not part of Rails core. You can read about that &lt;a href="http://rails-engines.org/news/2009/02/02/engines-in-rails-2-3/"&gt;at the Rails Engines site&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;3. Routing Improvements&lt;/h2&gt;


	&lt;p&gt;RESTful routes now use less memory because &lt;code&gt;formatted_*&lt;/code&gt; routes are no longer generated, resulting in a 50% memory savings.&lt;/p&gt;


	&lt;p&gt;Given this route:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.resources :users&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;If you want to access the &lt;span class="caps"&gt;XML&lt;/span&gt; formatted version of a user resource, you would use:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;user_path(123, :format =&amp;gt; 'xml')&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;In Rails 2.3, &lt;code&gt;:only&lt;/code&gt; and &lt;code&gt;:except&lt;/code&gt; options to &lt;code&gt;map.resources&lt;/code&gt; are not passed down to nested routes. The previous behavior was rather confusing so I think this is a good change.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;map.resources &lt;span class="sy"&gt;:users&lt;/span&gt;, &lt;span class="sy"&gt;:only&lt;/span&gt; =&amp;gt; [&lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:new&lt;/span&gt;, &lt;span class="sy"&gt;:create&lt;/span&gt;] &lt;span class="r"&gt;do&lt;/span&gt; |user|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# now will generate all the routes for hobbies&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  user.resources &lt;span class="sy"&gt;:hobbies&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h2&gt;4. &lt;span class="caps"&gt;JSON&lt;/span&gt; Improvements&lt;/h2&gt;


	&lt;p&gt;&lt;code&gt;ActiveSupport::JSON&lt;/code&gt; has been improved.&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;to_json&lt;/code&gt; will always quote keys now, per the &lt;span class="caps"&gt;JSON&lt;/span&gt; spec.&lt;/p&gt;


	&lt;p&gt;Before:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;{123 =&amp;gt; 'abc'}.to_json&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;=&amp;gt; '{123: "abc"}'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Now:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;{123 =&amp;gt; 'abc'}.to_json&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;=&amp;gt; '{"123": "abc"}'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Escaped Unicode characters will now be unescaped.&lt;/p&gt;


	&lt;p&gt;Before:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;ActiveSupport::JSON.decode("{'hello': 'fa\\u00e7ade'}")&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;=&amp;gt; {"hello"=&amp;gt;"fa\\u00e7ade"}&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Now:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;ActiveSupport::JSON.decode("{'hello': 'fa\u00e7ade'}")&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;=&amp;gt; {"hello"=&amp;gt;"façade"}&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;See &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/1100"&gt;ticket 11000 for details&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;5. Default scopes&lt;/h2&gt;


	&lt;p&gt;Prior to Rails 2.3, if you executed a find without any options, you’d get the objects back unordered (technically, the database does not &lt;strong&gt;guarantee&lt;/strong&gt; a particular ordering, but it would typically be by primary key, ascending).&lt;/p&gt;


	&lt;p&gt;Now, you can define the default sort and filtering options for finding models. The default scope works just like a named scope, but is used by default.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  default_scope &lt;span class="sy"&gt;:order&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;`users`.name asc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The default options can always be overridden using a custom finder.&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;User.all                                      # will use default scope&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;User.all(:order =&amp;gt; 'name desc') # will use passed in order option.&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Example:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;George&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class="co"&gt;User&lt;/span&gt;.all.map { |u| &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;u.id&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; - &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;u.name&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="i"&gt;3&lt;/span&gt; - &lt;span class="co"&gt;Alice&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="i"&gt;2&lt;/span&gt; - &lt;span class="co"&gt;Bob&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="i"&gt;1&lt;/span&gt; - &lt;span class="co"&gt;George&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Note how the default order is respected.&lt;/p&gt;


	&lt;h2&gt;6. Nested Transactions&lt;/h2&gt;


	&lt;p&gt;Pass &lt;code&gt;:requires_new =&amp;gt; true&lt;/code&gt; to &lt;code&gt;ActiveRecord::Base.transaction&lt;/code&gt; and a nested transaction will be created.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;User&lt;/span&gt;.transaction &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  user1 = &lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;User&lt;/span&gt;.transaction(&lt;span class="sy"&gt;:requires_new&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    user2 = &lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;   &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is actually emulated using save points because most databases do not support nested transactions. Some databases (SQLite) don’t support either save points or nested transactions, so in that case this works
just like Rails 2.2 where the inner transaction(s) have no effect and if there are any exceptions the entire transaction is rolled back.&lt;/p&gt;


	&lt;h2&gt;7. Asset Host Objects&lt;/h2&gt;


	&lt;p&gt;Since Rails 2.1, you could configure Rails to use an &lt;code&gt;asset_host&lt;/code&gt; that was a &lt;code&gt;Proc&lt;/code&gt; with two arguments, &lt;code&gt;source&lt;/code&gt; and &lt;code&gt;request&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;For example, some browsers complain if an &lt;span class="caps"&gt;SSL&lt;/span&gt; request loads images from a non-secure source. To make sure &lt;span class="caps"&gt;SSL&lt;/span&gt; always loads from the same host, you could write this (&lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html"&gt;from the documentation&lt;/a&gt;):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;.asset_host = &lt;span class="co"&gt;Proc&lt;/span&gt;.new { |source, request|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;if&lt;/span&gt; request.ssl?&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.protocol&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.host_with_port&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.protocol&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;assets.example.com&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This works but it’s kind of messy and it’s difficult to implement complicated logic. Rails 2.3 allows you to implement the logic in an object that responds to call with one or two parameters, like the
&lt;code&gt;Proc&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;The above Proc could be implemented like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;SslAssetHost&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;call&lt;/span&gt;(source, request)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; request.ssl?&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.protocol&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.host_with_port&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;request.protocol&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;assets.example.com&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;.asset_host = &lt;span class="co"&gt;SslAssetHost&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;David Heinemeier Hansson has already created a better plugin that handles this case: &lt;a href="http://github.com/dhh/asset-hosting-with-minimum-ssl/tree/master"&gt;asset-hosting-with-minimum-ssl&lt;/a&gt;. It takes into account the peculiarities of the different browsers to use &lt;span class="caps"&gt;SSL&lt;/span&gt; as little as possible, reducing load on your server.&lt;/p&gt;


	&lt;h2&gt;8. Easily update Rails timestamp fields&lt;/h2&gt;


	&lt;p&gt;If you’ve ever wanted to update Rails’ automatic timestamp fields &lt;code&gt;created_at&lt;/code&gt; or &lt;code&gt;updated_at&lt;/code&gt; you’ve noticed how painful it can be. Rails &lt;span class="caps"&gt;REALLY&lt;/span&gt; didn’t want you to change those fields.&lt;/p&gt;


	&lt;p&gt;Not any more!&lt;/p&gt;


	&lt;p&gt;Now you can easily change &lt;code&gt;created_at&lt;/code&gt; and &lt;code&gt;updated_at&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:created_at&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;3&lt;/span&gt;.weeks.ago, &lt;span class="sy"&gt;:updated_at&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;2&lt;/span&gt;.weeks.ago)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class="c"&gt;#&amp;lt;User id: 3, name: &amp;quot;Alice&amp;quot;, created_at: &amp;quot;2009-03-08 00:06:58&amp;quot;, updated_at: &amp;quot;2009-03-15 00:06:58&amp;quot;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Remember, If you don’t want your users changing these fields, you should make them &lt;code&gt;attr_protected&lt;/code&gt;.&lt;/p&gt;


	&lt;h2&gt;9. Nested Attributes and Forms&lt;/h2&gt;


	&lt;p&gt;This greatly simplifies complex forms that deal with multiple objects.&lt;/p&gt;


	&lt;p&gt;First, nested attributes allow a parent object to delegate assignment to its child objects.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; has_many &lt;span class="sy"&gt;:hobbies&lt;/span&gt;, &lt;span class="sy"&gt;:dependent&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  accepts_nested_attributes_for &lt;span class="sy"&gt;:hobbies&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Stan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;tt&gt;
&lt;/tt&gt;            &lt;span class="sy"&gt;:hobbies_attributes&lt;/span&gt; =&amp;gt; [{&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Water skiing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;},&lt;tt&gt;
&lt;/tt&gt;                                    {&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Hiking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;}])&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Nicely, this will save the parent and its associated models together and if there are any errors, none of the objects will be saved.&lt;/p&gt;


	&lt;p&gt;Forms with complex objects are now straight-forward. To use this in your forms, use the &lt;code&gt;FormBuilder&lt;/code&gt; instance’s &lt;code&gt;fields_for&lt;/code&gt; method.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;% form_for(&lt;span class="iv"&gt;@user&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |f| &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;div&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;%= f.label &lt;span class="sy"&gt;:name&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User name:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;%= f.text_field :name %&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;h2&amp;gt;Hobbies&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;h2&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;% f.fields_for(&lt;span class="sy"&gt;:hobbies&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |hf| &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;div&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= hf.label &lt;span class="sy"&gt;:name&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Hobby name:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= hf.text_field :name %&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;% end %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= f.submit &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;% end %&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;One catch is that a form is displayed for every associated object. New objects obviously have no associations so you have to create a dummy object in your controller.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# In this contrived example, I create 3 dummy objects so I'll get&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# 3 blank form fields.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt;.hobbies.build&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt;.hobbies.build&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt;.hobbies.build&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;There are a lot of options for nested forms including deleting associated objects, so be sure to read the documentation. Ryan Daigle also has &lt;a href="http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes"&gt;a great write-up&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;10. Rails Metal &lt;code&gt;\m/&lt;/code&gt;&lt;/h2&gt;


	&lt;p&gt;You can now write very simple Rack endpoints for highly trafficked routes, like an &lt;span class="caps"&gt;API&lt;/span&gt;. These are slotted in before Rails picks up the route.&lt;/p&gt;


	&lt;p&gt;A Metal endpoint is any class that conforms to the Rack spec (i.e., it has a &lt;code&gt;call&lt;/code&gt; method that takes an environment and returns the an array of status code, headers, and content).&lt;/p&gt;


	&lt;p&gt;Put your class in &lt;code&gt;app/metal&lt;/code&gt; (not generated by default). Return a 404 response code for any requests you don’t want to handle. These will get passed on to Rails.&lt;/p&gt;


	&lt;p&gt;There’s a generator you can use to create an example Metal end point:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;script/generate metal classname&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;In my sample app, I have what I would consider the “minimally useful” Rails Metal endpoint. It responds to /users.js and returns the list of users as &lt;span class="caps"&gt;JSON&lt;/span&gt;.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersApi&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.call(env)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# if this path was /users.js, reply with the list of users&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; env[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;PATH_INFO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;] =~ &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;^&lt;/span&gt;&lt;span class="ch"&gt;\/&lt;/span&gt;&lt;span class="k"&gt;users.js&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      [&lt;span class="i"&gt;200&lt;/span&gt;, {&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;}, &lt;span class="co"&gt;User&lt;/span&gt;.all.to_json]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;# otherwise, bail out with a 404 and let Rails handle the request&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      [&lt;span class="i"&gt;404&lt;/span&gt;, {&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;text/html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;}, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you want a little bit more help, you can use any other Rack-based framework, for example Sinatra.&lt;/p&gt;


	&lt;p&gt;For more details on how Rails Metal works, check out &lt;a href="http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m"&gt;Jesse Newland’s article about it&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Thanks for reading! For more details about new features in Rails 2.3, read the excellent &lt;a href="http://guides.rubyonrails.org/2_3_release_notes.html"&gt;release notes&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/_owYwJ6PUgQ" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/3/30/10-cool-things-in-rails-23</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-03-10:1917</id>
    <published>2009-03-10T16:34:00Z</published>
    <updated>2009-03-10T16:35:09Z</updated>
    <category term="Programming" />
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/iqIPyDrZwFc/slow-tests-are-a-bug" rel="alternate" type="text/html" />
    <title>Slow tests are a bug</title>
<content type="html">
            &lt;p&gt;&lt;img src="http://images.icanhascheezburger.com/completestore/2009/3/10/128811758638599628.jpg" /&gt;I’ve been doing &lt;span class="caps"&gt;TDD&lt;/span&gt; for about three years now. Once I figured out how to do it right, it became a natural part of how I program, and I can’t really imagine doing development without it. This isn’t to say that &lt;span class="caps"&gt;TDD&lt;/span&gt; is the &lt;a href="http://railspikes.com/2009/2/9/maybe-theres-more-than-one-way"&gt;only approach&lt;/a&gt; to writing quality software or that &lt;a href="http://railspikes.com/2008/7/11/testing-is-overrated"&gt;unit testing it the only kind of testing&lt;/a&gt; that matters. But it sure is useful.&lt;/p&gt;


	&lt;p&gt;The Ruby world talks a lot about &lt;span class="caps"&gt;TDD&lt;/span&gt;, moreso than many other developer communities. We have not one, not two, but at least half a dozen testing libraries that are actively being used and developed. For most Ruby developers, the question isn’t “Do you test?” but “BDD or &lt;span class="caps"&gt;TDD&lt;/span&gt;?” or even “RSpec, Shoulda, or Bacon?” We often use at least 2-3 layers of automated testing, and sometimes use different tools for each layer. Most Ruby conferences devote at least a few talks each day to testing-related topics. We’re test fanboys and -girls, for better or for worse.&lt;/p&gt;


	&lt;p&gt;But in spite of this, we rarely talk about &lt;strong&gt;test speed&lt;/strong&gt;. Sure, there are purists who believe that &lt;a href="http://blog.jayfields.com/2006/09/rubyrails-unit-testing-in-less-than-1.html"&gt;unit tests shouldn’t touch the database&lt;/a&gt; because anything that touches the DB is actually an integration test. But few Ruby testers actually take this long and lonely road, and I personally &lt;em&gt;prefer&lt;/em&gt; tests that talk to a database, at least some of the time.&lt;/p&gt;


	&lt;p&gt;And it’s true that others have written libraries to &lt;a href="http://github.com/brynary/testjour/tree/master"&gt;distribute their tests&lt;/a&gt; across multiple machines. But that’s the exception that proves the rule – the only reason to distribute your tests is that they’re too slow to begin with.&lt;/p&gt;


	&lt;p&gt;Most Rails projects I’ve worked on have ended up at around 3,000-15,000 lines of code, with a roughly as many lines of test code, and most have test suites that take a minute or more to run. Our test suite for &lt;a href="http://tumblon.com"&gt;Tumblon&lt;/a&gt;, for instance, churns along for 2.5 minutes. This is a too slow. And slow tests are a problem for at least two reasons: they &lt;strong&gt;slow down your development&lt;/strong&gt; and &lt;strong&gt;decrease code quality&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;1. &lt;strong&gt;Slow tests slow down development.&lt;/strong&gt; If you’re practicing &lt;span class="caps"&gt;TDD&lt;/span&gt;, you want to see a test fail before you make it succeed. Two minutes is far too long for this feedback loop to be effective. Of course, you can (and should) just run the test classes that correspond to your code as you program – no need to run your entire test suite every time you write your failing tests. But even still, the test time bar should ideally be set quite low. Frequent 5-10 second delays are enough to break my concentration, and I find myself cmd-tabbing over to other programs if I have to wait more than a few seconds for a test to run. I don’t know of any hard-and-fast rules, but I know that as soon as my test suite runs  longer than 30-45 seconds, and individual test classes take longer than 2-3 seconds, I’m less happy and less productive.&lt;/p&gt;


	&lt;p&gt;2. &lt;strong&gt;Slow tests decrease code quality.&lt;/strong&gt; There are two simple reasons for this. First, if slow tests break your flow, you’re not only going to write code more slowly: you’re also going to write worse code. Second, if your tests are too slow, you’re not going to wait for them to finish before you move on to the next task. Or worse, you’re not going to run them at all.&lt;/p&gt;


	&lt;h4&gt;So, how can I speed up my tests?&lt;/h4&gt;


	&lt;p&gt;Fortunately, this problem can be addressed. There are plenty of ways to speed up tests. On a current project, we’ve managed to cut our test time substantially – a recent test refactoring cut test time from 129.45 seconds to 31.04 seconds, without removing any tests. That’s a 76% speedup. But we still have room for improvement.&lt;/p&gt;


	&lt;p&gt;Really quickly, here are at least five ways to speed up your test suite. I hope to post more on each of these over the next month or two.&lt;/p&gt;


	&lt;p&gt;1. Use a test database instead of fixtures/factories/etc.&lt;/p&gt;


	&lt;p&gt;2. Only touch the database when necessary&lt;/p&gt;


	&lt;p&gt;3. Organize your tests to avoid duplicate execution&lt;/p&gt;


	&lt;p&gt;4. Separate slow tests out into a lazier testing layer&lt;/p&gt;


	&lt;p&gt;5. &lt;a href="http://roman.flucti.com/a-test-server-for-rails-applications"&gt;Run a Rails test server&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I’d love to see the Rails community devote more of its enthusiasm for testing to the question of test speed. There’s nothing wrong with improving our test frameworks, and let’s keep doing that. But let’s also make these frameworks fast.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/iqIPyDrZwFc" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/3/10/slow-tests-are-a-bug</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-03-06:1912</id>
    <published>2009-03-06T00:26:00Z</published>
    <updated>2009-03-06T00:26:39Z</updated>
    <category term="postgresql" />
    <category term="sql" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/0cK-LtbTIqw/duplicate-key-violates-unique-constraint" rel="alternate" type="text/html" />
    <title>Dealing with 'duplicate key violates unique constraint' on the primary key</title>
<content type="html">
            &lt;p&gt;I recently had to work through a problem where inserts were failing due to duplicate primary keys.&lt;/p&gt;


	&lt;p&gt;Here’s the error (edited for clarity):&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;PGError: ERROR: duplicate key violates unique constraint "contracts_pkey": INSERT INTO "contracts" ('column_1', 'column_2', 'column_3') VALUES('abc', '123', 'xyz') RETURNING "id"&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;What is going on here? I’m not even providing the primary key &lt;code&gt;id&lt;/code&gt;—that comes from the sequence.&lt;/p&gt;


	&lt;p&gt;Hey wait a second…&lt;/p&gt;


	&lt;p&gt;What was happening is that we had a data import that didn’t use the sequence. So the integers returned by the sequence have already been used, causing a duplicate primary key.&lt;/p&gt;


	&lt;p&gt;To solve the problem, I had to reset the sequence, like this:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;select setval('contracts_id_seq', (select max(id) + 1 from contracts));&lt;/code&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/0cK-LtbTIqw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/3/6/duplicate-key-violates-unique-constraint</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-03-05:1911</id>
    <published>2009-03-05T18:49:00Z</published>
    <updated>2009-03-05T18:49:59Z</updated>
    <category term="activerecord" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/_Rj579d6F28/today-s-hard-won-lesson" rel="alternate" type="text/html" />
    <title>Today's hard-won lesson</title>
<content type="html">
            &lt;p&gt;An float subtracted from an integer results in a float. When typecast by ActiveRecord, this is converted to an integer.&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;validates_numericality_of&lt;/code&gt; with &lt;code&gt;:only_integer =&amp;gt; true&lt;/code&gt; results in a rather obscure error message if a non-integer is present (“is not a number”).&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;validates_numericality_of&lt;/code&gt; uses the attribute value before type cast for its validation.&lt;/p&gt;


	&lt;p&gt;...&lt;/p&gt;


	&lt;p&gt;That means if you calculate a value before validation, what is printed out by using the attribute method is &lt;em&gt;different&lt;/em&gt; than what &lt;code&gt;validates_numericality_of&lt;/code&gt; is using for validation. You need to &lt;em&gt;ensure&lt;/em&gt; that the value of &lt;code&gt;attr_name_before_type_cast&lt;/code&gt; is an integer!&lt;/p&gt;


	&lt;p&gt;I just spent way too much time figuring this out.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/_Rj579d6F28" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/3/5/today-s-hard-won-lesson</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-02-16:1906</id>
    <published>2009-02-16T03:27:00Z</published>
    <updated>2009-02-16T03:32:18Z</updated>
    <category term="fetcher" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/Lz6lTGLUWDQ/fetcher-moved-to-github" rel="alternate" type="text/html" />
    <title>Fetcher moved to GitHub</title>
<content type="html">
            &lt;p&gt;A quick &lt;span class="caps"&gt;FYI&lt;/span&gt; for those who have been using the Fetcher plugin that we wrote (and use on &lt;a href="http://events.fanchatter.com"&gt;FanChatter Events&lt;/a&gt;)...&lt;/p&gt;


	&lt;p&gt;I have moved the &lt;a href="http://github.com/look/fetcher/tree/master"&gt;Fetcher plugin repository&lt;/a&gt; to GitHub. You can get it at &lt;a&gt;git://github.com/look/fetcher.git&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Happy forking!&lt;/p&gt;


	&lt;p&gt;(And a shameless plug for &lt;a href="http://blog.mondragon.cc/"&gt;Mike Mondragon&lt;/a&gt; and my book: if you need more details about how to make your app speak email, look no further than &lt;a href="https://peepcode.com/products/mms2r-pdf"&gt;Receiving Email with Ruby&lt;/a&gt;!)&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/Lz6lTGLUWDQ" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/2/16/fetcher-moved-to-github</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-02-14:1903</id>
    <published>2009-02-14T19:28:00Z</published>
    <updated>2009-02-14T19:30:36Z</updated>
    <category term="autotest" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/x_F6g87smws/rescuing-autotest-from-a-conflicting-plugin" rel="alternate" type="text/html" />
    <title>Rescuing autotest from a conflicting plugin</title>
<content type="html">
            &lt;p&gt;For the longest time, I wasn’t able to run &lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;autotest&lt;/a&gt; on one of my projects. That was OK; I was intrigued by autotest, but had never really committed to it. The problem: whenever I would try to run autotest, I’d get the following error:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
loading autotest/rails_rspec
Autotest style autotest/rails_rspec doesn't seem to exist. Aborting.
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I’m running &lt;a href="http://thoughtbot.com/projects/shoulda/"&gt;Shoulda&lt;/a&gt;, not &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt;, so I had no idea why this was happening. I tried installing (and uninstalling) RSpec in various configurations, to no avail. Nothing worked.&lt;/p&gt;


	&lt;p&gt;Then I started a new project. Autotest worked just fine on it. After a few days, I got used to autotest, and a few days later, I came to really like it. It helps me get into a &lt;span class="caps"&gt;TDD&lt;/span&gt; “flow” – all tests pass; write failing tests; write code; all tests pass.&lt;/p&gt;


	&lt;p&gt;So when I came back to my previous project where autotest didn’t work, I decided to dig deeper. Eventually I found a plugin that was causing the problem: &lt;a href="http://github.com/mbleigh/acts-as-taggable-on/tree/master"&gt;acts-as-taggable-on&lt;/a&gt;. The plugin was written to allow autotesting, as explained in a &lt;a href="http://www.intridea.com/2008/6/25/using-rspec-and-autotest-while-writing-rails-plugins-2"&gt;blog post&lt;/a&gt;. Supposedly, this is supposed to be a different autotest instance from your app’s main instance, but it wasn’t working that way for me.&lt;/p&gt;


	&lt;p&gt;The fix? &lt;strong&gt;Delete lib/discover.rb&lt;/strong&gt; from the acts-as-taggable-on plugin. That’s it – autotest works now.&lt;/p&gt;


	&lt;p&gt;In the end, I maybe could have solved the problem by getting RSpec configured properly, but just running the gem locally didn’t do the trick for me, and I don’t want to add any code to my app to support autotesting of a plugin that I never want to test.&lt;/p&gt;


	&lt;p&gt;So should plugins even ship with test code? Yes, they should. Not for normal use; I never run plugin tests, assuming instead that the plugin is tested by the author. But if an open source plugin ships without tests, it’s that much harder for other developers to fork/fix/improve the plugin. But really, that’s about the only reason for plugin/gem tests. And they should never touch application tests.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/x_F6g87smws" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/2/14/rescuing-autotest-from-a-conflicting-plugin</feedburner:origLink></entry>
</feed>
