<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Craig Ambrose</title>
    <link>http://blog.craigambrose.com</link>
    <language>en</language>
    <webMaster>craig@craigambrose.com (Craig Ambrose)</webMaster>
    <copyright>Copyright 2007-2009</copyright>
    <ttl>60</ttl>
    <pubDate>Mon, 21 Apr 2008 00:00:00 GMT</pubDate>
    <description>Agile Web Development</description>
    <item>
      <title>I sold my cow and all I got were these url helpers</title>
      <link>http://blog.craigambrose.com/past/2008/4/20/i_sold_my_cow_and/</link>
      <pubDate>Sun, 20 Apr 2008 23:19:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2008/4/20/i_sold_my_cow_and/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;In rails applications, we link to other pages in our application by generating a url which maps to a particular controller (class) and action (method) using a rule which we call a route. Back in rails 1.0, we would do something like this:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;lt;%= link_to 'Edit User', {:controller =&amp;gt; 'users', :action =&amp;gt; 'edit', :id =&amp;gt; @user} %&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This is not an article on routing for dummies, I presume you already know this stuff. However, I want to recap why we do this, in case anyone has forgotten the reason for all this.&lt;/p&gt;&lt;p&gt;To give a point of comparison, lets assume that there were no routes in rails, and that code was directed to a particular place based on the default rules of &amp;#8221;:controller/:action/:id?:other_params&amp;#8221;. A link might look like this:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;lt;%= link_to 'Edit User', "/users/edit/#{@user.to_param}" %&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;That&amp;#8217;s actually shorter than the above. Clearly brevity isn&amp;#8217;t the main goal here. So what are the goals of customisable routed?&lt;/p&gt;&lt;h3&gt;Human (and &lt;span class="caps"&gt;SEO&lt;/span&gt;) Friendly &lt;span class="caps"&gt;URLS&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;If we need further parameters, we don&amp;#8217;t want to introduce a question mark into the url. We want it to keep looking like a directory structure. If we are creating a new user inside group 5, we want a url like /groups/5/users/new, instead of /users/new?group_id=5. This goal is probably not one you have forgotten, so lets jump on to the next one.&lt;/p&gt;&lt;h3&gt;A Single Point of Change For Url Mappings&lt;/h3&gt;&lt;p&gt;It&amp;#8217;s a well known bad smell in any piece of software if changing your mind about one simple concept requires you to make changes all through the code (Martin Fowler calls this &amp;#8220;Shotgun Surgery&amp;#8221;). If our client says, &amp;#8220;can you change all references to &amp;#8216;users&amp;#8217; in the urls to saying &amp;#8216;people&amp;#8217; instead&amp;#8221;, or &amp;#8220;can you prefix all admin urls with /admin&amp;#8221; then we would expect to be able to do so without too much trouble.&lt;/p&gt;&lt;p&gt;The beautiful thing about routing in rails is that the routes control both the &lt;strong&gt;generation&lt;/strong&gt; and the &lt;strong&gt;parsing&lt;/strong&gt; of urls. Back when I wrote &lt;span class="caps"&gt;PHP&lt;/span&gt; apps, I had code to parse the urls (big ugly case statements) and in some cases I had code to generate the urls, but I never bothered to create one simple system for doing both.&lt;/p&gt;&lt;p&gt;So, with those two goals in mind, lets travel back to the present and look at resource routes in rails 2. When we create a route with map.resource, a bunch of special helper methods are also created. This allows us to replace our initial example with&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;lt;%= link_to 'Edit User', edit_user_path(@user) %&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Lets look at the pros and cons of that.&lt;/p&gt;&lt;p&gt;Firstly, it&amp;#8217;s much shorter. The hard coded string was a fair bit shorter too, so we know that brevity isn&amp;#8217;t always the main goal, but short is generally not a bad thing.&lt;/p&gt;&lt;p&gt;It&amp;#8217;s a little bit more english-like, in that it contains less symbols. However, this also means that it is less semantic. It&amp;#8217;s easy to learn how to read urls that are specified as a hash of controller, action and params. I know how to read the resource helpers too, but there are a few different rules to learn in order to parse them mentally, and I find it takes new rails programmers a little while to figure them out.&lt;/p&gt;&lt;p&gt;It&amp;#8217;s overloadable. Since it&amp;#8217;s a method, we can declare a helper of the same name and do something completely different. This can be handy, although in practice it&amp;#8217;s a bit dangerous since there are other ways to declare the route, so you&amp;#8217;re not guaranteed to intercept all calls. Also, it would then give behaviour that our programmer who has now worked so hard to figure out how the restful routing helpers work something of a surprise. The principle of least surprise is worth considering.&lt;/p&gt;&lt;p&gt;By in large, I&amp;#8217;m still kind of in favour of the new notation at this stage. When I first learnt it, I thought, &amp;#8220;wow, that looks much nicer&amp;#8221;, and that feeling is a very important argument in it&amp;#8217;s favour. We&amp;#8217;ve gotten a lot with this new functionality. I just want to mention the one feature we sold off without even noticing.&lt;/p&gt;&lt;p&gt;When generating a url we are new &lt;strong&gt;directly linking the view code to a single routing rule&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;#8220;WTF?&amp;#8221;&lt;/strong&gt;, I hear you say.&lt;/p&gt;&lt;p&gt;Haven&amp;#8217;t we already established that the rails routing system decouples url generation from the controller code that it maps to, allowing us to configure the interface between them in one place (routes.rb). Why am I now saying that I&amp;#8217;ve linked the url generation in my view to a &lt;strong&gt;single&lt;/strong&gt; route and lost my ability to vary it at will?&lt;/p&gt;&lt;p&gt;Lets say that we wanted to map all uses of the user edit action to a totally new url. It could look like anything we wanted, previously, we had the power to do so because our request to generate a url just gave the keys and values, and our action just accepted key/value parameters, and the string we used for the url in between was totally up to the routes.&lt;/p&gt;&lt;p&gt;Now we&amp;#8217;re using a method unique to this action to generate the url. By calling edit_user_path(@user), we&amp;#8217;re not actually giving up the flexibility to decide what that method does, but if we wanted to make it map to anything other than the edit action on the users controller, nested inside no other resources, then we&amp;#8217;d be violating all the conventions that we&amp;#8217;d built up in order to understand the user of these helpers.&lt;/p&gt;&lt;p&gt;So, if we want to do something like move this action to a different resource, we find that we need to go through and use a new set of helper methods for all the links. Since we need to change each link to do this, we&amp;#8217;re really not much better of that if we&amp;#8217;d used hard coded strings in the links.&lt;/p&gt;&lt;p&gt;If you wanted to rename the users resource to &amp;#8216;people&amp;#8217;, it&amp;#8217;s quite a tricky operation. I&amp;#8217;ve done it many times and without foolproof refactoring tools, you need to search and replace for strings like &lt;code&gt;user_&lt;/code&gt; and look at each method call to see if it&amp;#8217;s a url helper which should be renamed to &lt;code&gt;edit_people_path&lt;/code&gt; or similar.&lt;/p&gt;&lt;p&gt;Recently, I&amp;#8217;ve been experimenting with going back to expressing things as a hash. Also, in doing so I follow a set of conventions.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Always put spaces either side of the &lt;code&gt;=&amp;gt;&lt;/code&gt; operator.&lt;/li&gt;&lt;li&gt;Always use symbols for the keys&lt;/li&gt;&lt;li&gt;Always use single quotes as string delimiters for the values, if they are string literals.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This gives much more precise things to search and replace for. Lets say that I want to rename the users resource to people. I can search for all strings matching &lt;code&gt;:controller =&amp;gt; 'users'&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I&amp;#8217;m not necessarily saying that this approach is the best, but I think that we should all consider that the goal here is simplicity. The simplest code isn&amp;#8217;t necessary the shortest. The simplest code is the easiest to read, the easiest to learn it&amp;#8217;s full meaning, and the easiest to change. When we got all excited about named url helper methods, I&amp;#8217;m not sure it was at all clear how much we were giving up in return.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/helper">helper</category>
      <category domain="http://blog.craigambrose.com/past/tags/rails">rails</category>
      <category domain="http://blog.craigambrose.com/past/tags/url">url</category>
    </item>
    <item>
      <title>Using Model factories with RSpec</title>
      <link>http://blog.craigambrose.com/past/2008/2/23/using_model_factories_with_rspec/</link>
      <pubDate>Sat, 23 Feb 2008 22:12:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2008/2/23/using_model_factories_with_rspec/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;I had a lot of questions and concerns about RSpec when I first made the switch a few months ago. I&amp;#8217;d seen a few talks on &lt;span class="caps"&gt;BDD&lt;/span&gt; in general, and watched the peepcode screencasts on rspec, and I could see that &lt;span class="caps"&gt;BDD&lt;/span&gt; tended to encourage a fairly good style of testing. I managed to find answers for most of my questions, so here&amp;#8217;s a little list of the challenges and resolutions that I faced when I made the switch.&lt;/p&gt;&lt;p&gt;When I first started on rails, like a good little agile developer, I mocked out everything for my unit tests and ensured that I never actually hit the database and thus never required fixtures. I used the mocha library predominantly, but after a month or so of this I had gotten totally tangled up.&lt;/p&gt;&lt;p&gt;The problem was that active record objects are a bit like an iceberg where only a part of them is visible in the code, and the rest is lurking below the murky waters of your database. My tests were missing heaps of bugs caused by queries generating invalid &lt;span class="caps"&gt;SQL&lt;/span&gt;, but reliance upon properties which may or may not exist depending on the database schema, and were also far too complicated as they required lines and lines of setup code to handle all the wacky ways in which a model could interact with a database.&lt;/p&gt;&lt;p&gt;My solution eventually was to give in, and test things the way &lt;span class="caps"&gt;DHH&lt;/span&gt; does. Not particularly elegant, certainly not &amp;#8220;correct&amp;#8221; in terms of what I&amp;#8217;d been taught regarding how to test, but it did work. The upside of these tests which often integrated a number of layers together was that I got great coverage. The downside was that I&amp;#8217;d often get a raft of test failures if I broke a single line of code, and some things were just a bit too much effort to test and tended to motivate me not to bother. Also, the dependence on fixtures meant that as the test situations got more complex, I&amp;#8217;d have to add more fixtures, and in doing so break other tests.&lt;/p&gt;&lt;p&gt;When moving to RSpec, I threw all this away, and started again on mocking everything out. RSpec helped out with a few nice extra methods, like mock_model, which can sensibly provide a mock ActiveRecord object that has the bare essentials already (like the id and to_param methods). This time I did better, but I still got a little tangled up, and I found it really hard to test methods where I was querying for record. With a mock based approach, all I could test was that I&amp;#8217;d sent the query that I expected, not that it was actually valid &lt;span class="caps"&gt;SQL&lt;/span&gt; or that it would fetch any sensible results.&lt;/p&gt;&lt;p&gt;The resolution, as it turns out, lies somewhere in between.&lt;/p&gt;&lt;p&gt;I use mocking pretty heavily still, particularly when I&amp;#8217;m creating or updating records. But, I also often want to deal with real data, particularly when it&amp;#8217;s being fetched rather than created. Fixtures were a bad idea, because they created a great big data set that had to be valid for all tests. There are some plugins to provide different sets of fixtures for different scenarios, but I think that having the data used for a test in a different file is also downright confusing. Setting up for each test needs to be easy.&lt;/p&gt;&lt;p&gt;The solution for me was the use of a model factory, which is a pattern in some use amongst my colleagues at &lt;a href="http://www.cogentconsulting.com.au"&gt;Cogent.&lt;/a&gt; I&amp;#8217;d left the worlds of C# and C++ with a bit of a dislike of factories, being a pattern that, like dependency injection, seemed to add a great deal of complexity to a problem that is much more easily solved in a dynamic language. However, a simple model factory for testing is a different kettle of fish.&lt;/p&gt;&lt;p&gt;Lets say I&amp;#8217;m testing that I can&amp;#8217;t create a user if their email address already exists. If I was using fixtures, I&amp;#8217;d create a user with the email address I was going to try out, but that would affect all other tests. If I created a user directly in the test then I&amp;#8217;d need to update my test each time I changed the information needed to create a valid user. Instead, a model factory makes it look like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;describe User, "when being created" do&lt;br/&gt;  it "should require email address to be unique" do&lt;br/&gt;    model_factory.user(:email =&amp;gt; "craig@craigambrose.com")&lt;br/&gt;    user = User.create(:email =&amp;gt; "craig@craigambrose.com")&lt;br/&gt;    user.should_not be_valid&lt;br/&gt;    user.errors.on(:email).should == "must be unique" &lt;br/&gt;  end&lt;br/&gt;end&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The user method on model_factory creates and returns a valid user. It can be called as many times as I want, and it will always return a valid user. If User contains fields that must be unique, then the data I use to populate it contains integers which increment each time. The factory methods also take arrays of options which can be used instead of these default values, which I use whenever I want to set an attribute that I care about in the test. This way, if I change what is required to create a user, all I need to change is the model factory, not every single test.&lt;/p&gt;&lt;p&gt;I don&amp;#8217;t use the model factory all the time. I still make heavy use of mock_model. For each case, I try and determine which method will yield the simplest test that actually forces me to write the code that is needed, rather than just appearing to give coverage over the lines of code. Sometimes I use some mocking and some concrete objects in the same test.&lt;/p&gt;&lt;p&gt;I haven&amp;#8217;t provided the code for the model_factory itself. It&amp;#8217;s very straightforward and I&amp;#8217;ll leave it as an exercise for the reader. Drop me a line if you have a particularly clever implementation that you&amp;#8217;d like to share or are interested in seeing some of my code.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/factory">factory</category>
      <category domain="http://blog.craigambrose.com/past/tags/model">model</category>
      <category domain="http://blog.craigambrose.com/past/tags/rspec">rspec</category>
      <category domain="http://blog.craigambrose.com/past/tags/testing">testing</category>
    </item>
    <item>
      <title>Storing Images from remote URLs</title>
      <link>http://blog.craigambrose.com/past/2008/2/22/storing_images_from_remote_urls/</link>
      <pubDate>Fri, 22 Feb 2008 00:17:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2008/2/22/storing_images_from_remote_urls/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;Here&amp;#8217;s a handy little modification to attachment_fu to allow the model to have it&amp;#8217;s file data set from a remote url. I&amp;#8217;ve been doing this for a while but recently altered it to compute the mime-type from the downloaded file, rather than just basing it off the extension. This is because some web sites host files (such as images) at urls without a file extension.&lt;/p&gt;&lt;p&gt;&lt;a href="http://pastie.caboo.se/155702"&gt;http://pastie.caboo.se/155702&lt;/a&gt;&lt;/p&gt;&lt;p&gt;As this is a monkey patch for attachment_fu, I follow Chris Wanstrath&amp;#8217;s &lt;a href="http://errtheblog.com/posts/67-evil-twin-plugin"&gt;evil twin&lt;/a&gt; convention  and put it in a plugin called attachment_fu_hacks.&lt;/p&gt;&lt;p&gt;This code is also dependent on the &lt;a href="http://code.google.com/p/mimetype-fu/"&gt;mimetype-fu plugin.&lt;/a&gt; Mimetype-fu calculates the mime type of a file using the *nix &amp;#8220;file&amp;#8221; command, rather than using file extensions as the mime-types gem does. If you&amp;#8217;re using &lt;span class="caps"&gt;OSX&lt;/span&gt;, then this wont work unless you change the two occurances of &lt;code&gt;file -bir&lt;/code&gt; in mimetype_fu.rb to &lt;code&gt;file -br &amp;mdash;mime&lt;/code&gt; (which is compatible with both &lt;span class="caps"&gt;OSX&lt;/span&gt; and linux). I&amp;#8217;ve submitted that change to the author so hopefully it will be incorporated into future versions..&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/attachmentfu">attachmentfu</category>
      <category domain="http://blog.craigambrose.com/past/tags/images">images</category>
      <category domain="http://blog.craigambrose.com/past/tags/rails">rails</category>
    </item>
    <item>
      <title>respond_to.email, or how to handle incoming emails in rails RESTfully</title>
      <link>http://blog.craigambrose.com/past/2008/2/9/respond_toemail_or_how_to_handle/</link>
      <pubDate>Sat, 09 Feb 2008 04:49:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2008/2/9/respond_toemail_or_how_to_handle/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;There&amp;#8217;s a bunch of information around on how to handle incoming emails with your rails application, in particular the &lt;a href="http://wiki.rubyonrails.org/rails/pages/HowToReceiveEmailsWithActionMailer"&gt;wiki page&lt;/a&gt;,   but I have some concerns with the methods that are being suggested, and in this article I present an alternative which I&amp;#8217;ve been trying out and I really like.&lt;/p&gt;&lt;p&gt;Handling incoming email is, in essence, very simple. All you need to do is get the email, which is a big chunk of text, parse it with a ruby email class, such as TMail (which is used by ActionMailer), and perform some action. If you&amp;#8217;re only handling a few specific addresses, it might be best to fetch the email via &lt;span class="caps"&gt;POP3&lt;/span&gt;, and I&amp;#8217;ve done that before using a daemon to regularly poll the pop account.&lt;/p&gt;&lt;p&gt;&lt;span class="caps"&gt;POP3&lt;/span&gt; is not a viable solution if you want to handle all email for a certain domain. At this point, we probably want to talk about &lt;span class="caps"&gt;SMTP&lt;/span&gt;.&lt;/p&gt;&lt;h2&gt;A Very Short Guide to &lt;span class="caps"&gt;SMTP&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Simple Mail Transport Protocol&lt;/strong&gt; is pretty damn cool if you ask me. It&amp;#8217;s dead simple, basically the client can only say &amp;#8220;hello, here&amp;#8217;s an email from X to Y&amp;#8221;. Just like &lt;span class="caps"&gt;HTTP&lt;/span&gt;, it&amp;#8217;s fully push based. There&amp;#8217;s no polling, emails get pushed across the internet. Just like &lt;span class="caps"&gt;HTTP&lt;/span&gt;, it has a hole stack of response codes which are of course appropriate to trying to send an email, rather than talk to a web resource.&lt;/p&gt;&lt;h2&gt;Using Postfix Mail Filters to Call Ruby&lt;/h2&gt;&lt;p&gt;Postfix is a common open source &lt;span class="caps"&gt;SMTP&lt;/span&gt; server. Before I looked at it, it was big and scary. After a few hours of expert help, I wonder what seemed so complicated. One of the basic ways that we can use postfix to push mail to our rails app is by specifying a command like script which gets executed whenever postfix gets an email. This is the first option presented on the rails wiki, and they suggest using a script which calls the receive method of one of your ActionMailer classes.&lt;/p&gt;&lt;h2&gt;My Concern&lt;/h2&gt;&lt;p&gt;If we&amp;#8217;re going to use ActionMailer to parse an email, and then presumably fire off a bunch of ActiveRecord code to make changes to your database as a result, clearly we&amp;#8217;re loading the entire rails stack. Every time we get an email we&amp;#8217;re loading the entire rails stack. This seems like how we handled web requests back in the day when there was only mod_cgi. No shared resources between requests, a big performance hit for loading all of rails and then getting rid of it each time, and the concern that we can only handle as many incoming emails as we have &lt;span class="caps"&gt;RAM&lt;/span&gt; on our server as the rails code takes up a bunch of memory.&lt;/p&gt;&lt;h2&gt;What I Want&lt;/h2&gt;&lt;p&gt;I don&amp;#8217;t want to have to worry about the resources I need to scale my email server, I already do that with my application servers. I want to handle emails in a way that re-uses an in-memory copy of the rails classes and called be scaled in a predictable way.&lt;/p&gt;&lt;p&gt;That sounds a lot like a mongrel cluster.&lt;/p&gt;&lt;p&gt;We all have one of those already right. So why not handle incoming mail over &lt;span class="caps"&gt;HTTP&lt;/span&gt;? It&amp;#8217;s dead easy, it scales well, and the result is really Rails-ish.&lt;/p&gt;&lt;h2&gt;respond_to.email&lt;/h2&gt;&lt;p&gt;I was hoping to get a plugin out of this. It&amp;#8217;d be so handy that people would queue for miles to download it. The trouble is, it&amp;#8217;s actually not even enough code to bother, it&amp;#8217;s only about three lines of ruby and the same of postfix config. So, lets call this a pattern. I&amp;#8217;ll describe how to do it, and you can all run off and do it yourself.&lt;/p&gt;&lt;h2&gt;Step One: Install Postfix&lt;/h2&gt;&lt;p&gt;Install postfix on one of your servers. For any sizable rails site, I like to have a little &lt;span class="caps"&gt;VPS&lt;/span&gt; just for daemons, cron jobs, scripts, and the mail server, to keep it separate from all the web stuff. On ubuntu, this was as easy as &amp;#8220;sudo apt-get install postfix&amp;#8221;. For the default configuration type, I chose &amp;#8220;internet site&amp;#8221;.&lt;/p&gt;&lt;h2&gt;Step Two: Setup Your MX Record&lt;/h2&gt;&lt;p&gt;For mail to start arriving at your mail server, you need to add a MX record to your &lt;span class="caps"&gt;DNS&lt;/span&gt; which points at the url of your server. Depending on your host, you probably have a web interface to do this, and it&amp;#8217;s probably dead easy.&lt;/p&gt;&lt;h2&gt;The Magic Script!&lt;/h2&gt;&lt;p&gt;Create a file called mail_handler.rb, and pop it somewhere in your rails project. I created a /bin directory for it. Don&amp;#8217;t use a rake task, the goal here is not to load in any unecessary stuff. Here&amp;#8217;s the contents.&lt;/p&gt;&lt;code&gt;&lt;br/&gt;#!/usr/bin/ruby&lt;br/&gt;require 'net/http'&lt;br/&gt;require 'uri'Net::HTTP.post_form URI.parse('http://www.craigambrose.com/emails'), { "email" =&amp;gt; STDIN.read }&lt;br/&gt;&lt;/code&gt;&lt;p&gt;If ruby is somewhere else on your machine, change the line at the top to be correct (try &amp;#8220;which ruby&amp;#8221; on that machine to see where it is). I&amp;#8217;ve chosen to hardcode in the url that I want to post the email to so that I don&amp;#8217;t have to load any other files. If you have more deployment environments to worry about, you might want to put the target url in a yml file and parse it here. Just don&amp;#8217;t load your rails environment file, that&amp;#8217;s the whole point of this.&lt;/p&gt;&lt;h2&gt;Configuring Postfix to Call the Script&lt;/h2&gt;&lt;p&gt;In this example, the domain that I want to handle email for is &amp;#8220;craigambrose.com&amp;#8221;. Everywhere you see this, replace it with your own domain name. Most of the commands below need root access.&lt;/p&gt;&lt;p&gt;In /etc/postfix/main.cf&lt;/p&gt;&lt;code&gt;&lt;br/&gt;mydestination = localhost.localdomain, localhost, craigambrose.com&lt;br/&gt;virtual_maps = hash:/etc/postfix/virtual&lt;br/&gt;alias_maps = hash:/etc/aliases&lt;br/&gt;&lt;/code&gt;&lt;p&gt;In /etc/postfix/virtual (this is a file, you may need to create this)&lt;/p&gt;&lt;code&gt;&lt;br/&gt;@craigambrose.com  rails_mailer&lt;br/&gt;&lt;/code&gt;&lt;p&gt;The above says to redirect any address at craigambrose.com to the alias &amp;#8220;rails_mailer&amp;#8221;, which I&amp;#8217;ll create next. You could run multiple rails apps of the same server by giving them all unique aliases. On the left, you can use a regular expression to match addresses if you only want to match some of them.&lt;/p&gt;&lt;p&gt;To apply this change to virtuals, run:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;postmap /etc/postfix/virtual&lt;br/&gt;&lt;/code&gt;&lt;p&gt;In /etc/aliases&lt;/p&gt;&lt;code&gt;&lt;br/&gt;rails_mailer:   "|/var/www/apps/craigambrose/current/bin/mail_handler.rb" &lt;br/&gt;&lt;/code&gt;&lt;p&gt;That&amp;#8217;s the alias we created on the left. On the right is the path to my script, change as necessary. The pipe character before the script path means &amp;#8220;the following is a shell command, not an email address&amp;#8221;.&lt;/p&gt;&lt;p&gt;To apply this change to aliases, run:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;postalias /etc/aliases&lt;br/&gt;&lt;/code&gt;&lt;p&gt;To apply the main configuration changes to postfix, run:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;/etc/init.d/postfix reload&lt;br/&gt;&lt;/code&gt;&lt;h2&gt;Testing the Setup&lt;/h2&gt;&lt;p&gt;I should be able to send an email now to &amp;#8220;someaddress@craigambrose.com&amp;#8221;. To see it get process by postfix, we might want to watch the postfix info log:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;tail -f /var/log/mail.info&lt;br/&gt;&lt;/code&gt;&lt;p&gt;When the mail is process, you should see a line like:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;to=&amp;lt;someaddress@craigambrose.com&amp;gt;, orig_to=&amp;lt;root&amp;gt;, relay=local, delay=2, status=sent (delivered to command: /var/www/apps/craigambrose/current/mail_handler.rb)&lt;br/&gt;&lt;/code&gt;&lt;p&gt;Then, go peek at your rails app logs. You should see that the mail has been passed through by the script. Even if you haven&amp;#8217;t written an action to handle it yet, the log entry should be there.&lt;/p&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;&lt;p&gt;If you didn&amp;#8217;t see the correct line in your postfix logs, then perhaps there&amp;#8217;s a problem with your &lt;span class="caps"&gt;DNS&lt;/span&gt; Set. You could try talking to postfix directly. Mail servers listen on port 25, and you can telnet into them and speak directly. Try &amp;#8220;telnet &lt;span class="caps"&gt;YOUR&lt;/span&gt;_SERVER_IP 25&amp;#8221; And the try typing in what the client says in the &lt;a href="http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#Sample_communications"&gt;sample &lt;span class="caps"&gt;SMTP&lt;/span&gt; communication on wikipedia&lt;/a&gt; with the example address changed to the domain that you want to test. If that works, but sending email didn&amp;#8217;t, you&amp;#8217;ll need to investigate your &lt;span class="caps"&gt;DNS&lt;/span&gt; setup.&lt;/p&gt;&lt;h2&gt;Handling the Rails Action&lt;/h2&gt;&lt;p&gt;The target url I put in my mail script was http://www.craigambrose.com/emails, so the mail is going to get POSTed to that resource. With normal rails resource routes, that means that we&amp;#8217;re expecting to handle the email in the create action of the EmailsController. That seems very sensible to me. My script puts the unparsed email into params[:email].&lt;/p&gt;&lt;p&gt;To parse it with TMail, all you need to do is:&lt;/p&gt;&lt;code&gt;&lt;br/&gt;  require 'tmail'&lt;br/&gt;  email = TMail::Mail.parse(params[:email])&lt;br/&gt;&lt;/code&gt;&lt;p&gt;Alternatively you could pass it to the &amp;#8220;receive&amp;#8221; method of any ActionMailer derived class, which does the above automatically.&lt;/p&gt;&lt;p&gt;I&amp;#8217;ve had some reports that TMail is both a little slow, and also not quite up to parsing all the possible ways that an email might be encoded in the big bad world. That&amp;#8217;s a subject for another blog post.&lt;/p&gt;&lt;h2&gt;Final Performance Note&lt;/h2&gt;&lt;p&gt;When postfix is calling your script, it makes so that only a certain number of calls are occurring concurrently, the default is 20, which seems pretty good to me. If you&amp;#8217;d like to tweak this, use the following setting in main.cf (and don&amp;#8217;t forget to reload postfix afterwards).&lt;/p&gt;&lt;code&gt;&lt;br/&gt;default_destination_concurrency_limit = 30&lt;br/&gt;&lt;/code&gt;&lt;h2&gt;Acknowledgments&lt;/h2&gt;&lt;p&gt;Setting up servers is not my area of expertise. Many thanks to &lt;a href="http://www.octopus.com.au"&gt;Andrew Snow of Octopus&lt;/a&gt; for the postfix help and &lt;a href="http://notahat.com"&gt;Pete Yandell&lt;/a&gt; for sharing some of the lessons learned on his great mailing list site &lt;a href="http://9cays.com/"&gt;9cays&lt;/a&gt;&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/email">email</category>
      <category domain="http://blog.craigambrose.com/past/tags/postfix">postfix</category>
      <category domain="http://blog.craigambrose.com/past/tags/rails">rails</category>
      <category domain="http://blog.craigambrose.com/past/tags/ruby">ruby</category>
      <category domain="http://blog.craigambrose.com/past/tags/smtp">smtp</category>
    </item>
    <item>
      <title>Leaving the beaten track with RSpec</title>
      <link>http://blog.craigambrose.com/past/2007/12/5/leaving_the_beaten_track_with/</link>
      <pubDate>Wed, 05 Dec 2007 07:16:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/12/5/leaving_the_beaten_track_with/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;I&amp;#8217;ve spent today learning RSpec. To get my head around it, I decided to spec a controller action which I&amp;#8217;d already written and tested with Test::Unit. It&amp;#8217;s a pretty basic &lt;span class="caps"&gt;CRUD&lt;/span&gt; action, requiring login and ownership of the record.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s the spec and test code side by side:&lt;/p&gt;&lt;p&gt;&lt;a href="http://pastie.caboo.se/124898"&gt;http://pastie.caboo.se/124898&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I&amp;#8217;m not sure which one was easier. The RSpec version is certainly a lot longer. Having said that, the Test::Unit one uses fixtures, which aren&amp;#8217;t included in the dump.&lt;/p&gt;&lt;p&gt;In RSpec&amp;#8217;s favour, is that the specifications run much faster (as they don&amp;#8217;t use the database), and they also better decouple the controller from the model, as it&amp;#8217;s a more true &amp;#8220;unit&amp;#8221; test. Having said that, I believe that the RSpec version might actually be a little bit more fragile, as it would fail if the code under test changed to perform the same operation using different methods (such as calling ActiveRecord create, instead of new and save).&lt;/p&gt;&lt;p&gt;Also, some of the things I specified in terms of expectations are actually order dependent, which is not captured in my specs, so if I deliberately messed up the order of some of the code, I might get false positives with my specifications.&lt;/p&gt;&lt;p&gt;For the record, here&amp;#8217;s the code under test.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;  before_filter :login_required, :only =&amp;gt; [:new, :create, :edit, :update]&lt;br/&gt;  before_filter :load_user&lt;br/&gt;  before_filter :current_user_can_edit_user, :only =&amp;gt; [:new, :create, :edit, :update]&lt;br/&gt;  before_filter :load_user_base_tabs&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;  def create&lt;br/&gt;    @photo_set = PhotoSet.new(params[:photo_set])&lt;br/&gt;    @photo_set.profile = @profile&lt;br/&gt;    success = @photo_set.save    respond_to do |format|&lt;br/&gt;      format.html do&lt;br/&gt;        if success&lt;br/&gt;          redirect_to user_photo_set_path(@user, @photo_set)&lt;br/&gt;        else&lt;br/&gt;          render :action =&amp;gt; 'new'&lt;br/&gt;        end&lt;br/&gt;      end&lt;br/&gt;    end&lt;br/&gt;  end&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/rspec">rspec</category>
      <category domain="http://blog.craigambrose.com/past/tags/smackdown">smackdown</category>
      <category domain="http://blog.craigambrose.com/past/tags/testunit">testunit</category>
    </item>
    <item>
      <title>Image cropping with Mini Magick and attachment_fu</title>
      <link>http://blog.craigambrose.com/past/2007/12/3/image_cropping_with_mini_magick/</link>
      <pubDate>Mon, 03 Dec 2007 01:07:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/12/3/image_cropping_with_mini_magick/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;As I mentioned in my last post, I&amp;#8217;ve recently switched a lot of my code from RMagic to Mini Magick. The &lt;span class="caps"&gt;API&lt;/span&gt; provided by mini magick isn&amp;#8217;t quite as nice, and you have to jump through a few hoops to get it to do what you want, so I thought I&amp;#8217;d post an example.&lt;/p&gt;&lt;p&gt;Whenever clients talk about image thumbnailing, what they actually want is for the image to be cropped square, and then resized down to thumbnail size. They never, ever, want you to  provide a thumbnail that isn&amp;#8217;t square, or to scale the image out of proportion in order to stretch it into a square shape. It&amp;#8217;s always crop and scale.&lt;/p&gt;&lt;p&gt;Strangely, this isn&amp;#8217;t what attachment_fu does out of the box, with either rmagick or mini magick. Others have discussed this with regard to rmagick, but I couldn&amp;#8217;t find a good mini-magick solution that worked, so here&amp;#8217;s why I&amp;#8217;ve come up with.&lt;/p&gt;Replace the resize_image method in attachment_fu&amp;#8217;s mini_magick_processor.rb file with the following:&lt;br/&gt;&lt;code&gt;&lt;pre&gt;&lt;br/&gt;        def resize_image(img, size)&lt;br/&gt;          size = size.first if size.is_a?(Array) &amp;#38;&amp;#38; size.length == 1&lt;br/&gt;          if size.is_a?(Fixnum) || (size.is_a?(Array) &amp;#38;&amp;#38; size.first.is_a?(Fixnum))&lt;br/&gt;            if size.is_a?(Fixnum)&lt;br/&gt;              resize_and_crop(img, size)&lt;br/&gt;            else&lt;br/&gt;              size[0] == size[1] ? resize_and_crop(img, size[0]) : img.resize(size.join('x'))&lt;br/&gt;            end&lt;br/&gt;          else&lt;br/&gt;            img.resize(size.to_s)&lt;br/&gt;          end&lt;br/&gt;          self.temp_path = img&lt;br/&gt;        end&lt;/pre&gt;&lt;pre&gt;        def resize_and_crop(image, square_size)         &lt;br/&gt;          if image[:width] &amp;lt; image[:height]   &lt;br/&gt;            shave_off = ((image[:height] - image[:width])/2).round &lt;br/&gt;            image.shave("0x#{shave_off}") &lt;br/&gt;          elsif image[:width] &amp;gt; image[:height]&lt;br/&gt;            shave_off = ((image[:width] - image[:height])/2).round&lt;br/&gt;            image.shave("#{shave_off}x0")&lt;br/&gt;          end&lt;br/&gt;          image.resize("#{square_size}x#{square_size}")&lt;br/&gt;          return image&lt;br/&gt;        end&lt;br/&gt;&lt;/pre&gt;&lt;/code&gt;&lt;p&gt;The resize_image method is changed a little to ensure that resize_and_crop is called if both requested dimensions are the same. This occurs if you specify it as a single number, or as an array of two numbers that are the same.&lt;/p&gt;eg: &lt;br/&gt;&lt;code&gt;:thumb =&amp;gt; [80,80]&lt;/code&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/attachmentfu">attachmentfu</category>
      <category domain="http://blog.craigambrose.com/past/tags/images">images</category>
      <category domain="http://blog.craigambrose.com/past/tags/minimagick">minimagick</category>
    </item>
    <item>
      <title>Image management that will scale</title>
      <link>http://blog.craigambrose.com/past/2007/11/27/image_management_that_will_scale/</link>
      <pubDate>Tue, 27 Nov 2007 02:59:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/11/27/image_management_that_will_scale/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;There is a lot of conflicting information around about handling user uploaded images in rails applications. I&amp;#8217;ve done it a number of different ways, and the good news is that it&amp;#8217;s not too hard to move from one system to another. However, dealing with scaling issues is a pain and it&amp;#8217;s nice to get it right first go. So, here are some problems that I&amp;#8217;ve encountered recently, along with some solutions.&lt;/p&gt;&lt;h2&gt;Files Per Directory Limit&lt;/h2&gt;&lt;p&gt;Depending on which OS you use for hosting, you&amp;#8217;ve probably got a limit to the number of files (or directories) you can put inside a given directory. It&amp;#8217;s usually about 32,000. While this seems like a long way off, if your site accepts user content then hopefully this will eventually become a problem for you. There have been various talks and articles written about different hashing systems for file names, but it&amp;#8217;s worth mentioning that this is basically a solved problem, and you shouldn&amp;#8217;t have to tackle it yourself.&lt;/p&gt;&lt;p&gt;If you&amp;#8217;re still using file_column, as I am for a few things, then this one might bite you. The simplest solution, I think, is to migrate to attachment_fu. The file system store for attachment_fu implements file name based hashing, and the s3 and database stores don&amp;#8217;t suffer from the problem at all. Also, the way in which attachment_fu handles pluggable storage classes means that you could also slip in your own custom storage system later without having to change the way that you use attachment_fu in your models.&lt;/p&gt;&lt;p&gt;If you&amp;#8217;re thinking of making the switch, &lt;a href="http://blog.craigambrose.com/past/2007/9/9/migrating_from_file_column_to_attatchment_fu/"&gt;here&amp;#8217;s&lt;/a&gt; an article I wrote on migrating from file column to attachment_fu.&lt;/p&gt;&lt;h2&gt;RMagick Memory Leaks&lt;/h2&gt;&lt;p&gt;RMagick is really handy, and so just about every rails image handling tutorial on the internet recommends it&amp;#8217;s use. I&amp;#8217;m using it all over the place. My advice to you, is don&amp;#8217;t ever do this. It turns out that RMagick leaks memory every time it manipulates an image. I haven&amp;#8217;t measured the amount myself, but I&amp;#8217;m told it&amp;#8217;s quite a bit. Certainly I&amp;#8217;ve been having resource consumption problems with scripts using RMagick heavily. So, say goodbye to it.&lt;/p&gt;&lt;p&gt;&lt;span class="caps"&gt;DHH&lt;/span&gt; recommended just using the image magick binaries manually. That&amp;#8217;s basically a good idea, but a slightly easier way of doing that is to use the mini_magick gem. Mini magick provides a ruby &lt;span class="caps"&gt;API&lt;/span&gt;, but under the hood it just calls the image magick command line tools. Attachment_fu comes with a mini magic processor, so you can just add &amp;#8221;:processor =&amp;gt; :MiniMagick&amp;#8221; to your call to has_attachment and you&amp;#8217;re in business. Khamsouk Souvanlasy wrote &lt;a href="http://khamsouk.souvanlasy.com/2007/5/1/ajax-file-uploads-in-rails-using-attachment_fu-and-responds_to_parent/comments/292"&gt;a good tutorial&lt;/a&gt; on using mini_magick with acts_as_attachment.&lt;/p&gt;&lt;h2&gt;Cropping&lt;/h2&gt;&lt;p&gt;The one thing I noticed in using attachment_fu instead of file column is that file column resizes images and crops them nicelly, the way that you would expect. By default, attachment_fu tends to stretch them. This has been covered better by other people, so I just want to mention it because stretching is almost certainly what you want, and until Rick fixes it, I&amp;#8217;d suggest making a small change to the plugin yourself. There are a number of articles on the subject, but I think the best one is probably over at &lt;a href="http://toolmantim.com/article/2006/9/12/generating_cropped_thumbnails_with_acts_as_attachment"&gt;toolman tim&amp;#8217;s&lt;/a&gt; blog.&lt;/p&gt;&lt;p&gt;Don&amp;#8217;t just go with Tim&amp;#8217;s solution though, have a look at the comments, and you will find options for the different image processesors. I used &amp;#8220;labrat&amp;#8217;s&amp;#8221; suggested fix for mini magick (paste &lt;a href="http://pastie.caboo.se/64069"&gt;here&lt;/a&gt;)&lt;/p&gt;&lt;h2&gt;Amazon S3&lt;/h2&gt;&lt;p&gt;Amazon S3 appears to be a great solution for handling user generated images, and I&amp;#8217;m starting to use it a fair bit. One word of warning however, is that I&amp;#8217;ve already started to encounter an occasional communication error with amazon, as discussed in &lt;a href="http://www.ruby-forum.com/topic/110842"&gt;this thread&lt;/a&gt; and I don&amp;#8217;t yet know how serious it is or how easily fixed. I&amp;#8217;ll post some more on this subject when I&amp;#8217;m better informed.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/attachmentfu">attachmentfu</category>
      <category domain="http://blog.craigambrose.com/past/tags/filecolumn">filecolumn</category>
      <category domain="http://blog.craigambrose.com/past/tags/imagemagick">imagemagick</category>
      <category domain="http://blog.craigambrose.com/past/tags/images">images</category>
      <category domain="http://blog.craigambrose.com/past/tags/minimagick">minimagick</category>
      <category domain="http://blog.craigambrose.com/past/tags/rails">rails</category>
      <category domain="http://blog.craigambrose.com/past/tags/rmagick">rmagick</category>
    </item>
    <item>
      <title>Caching Makes Your Brain Explode</title>
      <link>http://blog.craigambrose.com/past/2007/11/13/caching_makes_your_brain_explode/</link>
      <pubDate>Tue, 13 Nov 2007 04:20:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/11/13/caching_makes_your_brain_explode/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;I&amp;#8217;ve been spending a lot of time recently trying to make &lt;a href="http://boxedup.com"&gt;boxedup.com&lt;/a&gt; scale. Before I started, I&amp;#8217;d watched the right screen-casts, read the right books, and I thought I knew what had to be done to speed up rails applications when the need arose.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Boy, was I wrong.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;A quick look at the three methods of caching rails pages reveals that page caching is of no use to a site which insists on displaying the current user on all pages (as most of them seem to). Next up is action caching, which does let me execute before and after filters, allowing me to handle to logged in user, but caches the entire rendered action, including the layout, so once again I can&amp;#8217;t display the currently logged in user. There are possibly some ways around this, but since action caching is really just a specialised form of fragment caching, lets talk about that.&lt;/p&gt;&lt;h2&gt;Fragment Caching&lt;/h2&gt;&lt;p&gt;Fragment caching does work. In fact, my first attempts at it benchmarked so well in my simplistic &amp;#8220;load this page 100 times in httperf&amp;#8221; tests that I dived in head first. The books on this subject, particularly the pragprog one, give the impression that this is pretty straight forward. It&amp;#8217;s not. There are some &lt;strong&gt;massive&lt;/strong&gt; gotchas that will bring even a fairly low traffic site to it&amp;#8217;s knees if you don&amp;#8217;t watch out for them.&lt;/p&gt;&lt;h2&gt;It&amp;#8217;s All About Expiry&lt;/h2&gt;&lt;p&gt;You can&amp;#8217;t consider caching without thinking about cache expiry. In rails, this is typically done with cache sweepers. For fragment caching, the sweepers call the expire fragment method. This can take a string, which matches the fragment name exactly, or it can take a regular expression.&lt;/p&gt;&lt;h3&gt;Gotcha #1, Don&amp;#8217;t Use expire_fragment With A Regex&lt;/h3&gt;&lt;p&gt;First up, this doesn&amp;#8217;t work with memcache anyway, it only works with the file system cache. There&amp;#8217;s nothing that wrong with the file system cache. Reading from it is faster than rendering a template. Expiring from it, however, is pretty slow. Expiring from it using a regex is absolutely appalling. The reason why is better explained &lt;a href="http://gurge.com/blog/2007/02/04/rails-expire_fragmentregex-considered-harmful/"&gt;in this article&lt;/a&gt; by Adam Doppelt.&lt;/p&gt;&lt;p&gt;So, if you can&amp;#8217;t expire it with a regex, that leaves you the following options for expiry:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Time based expiry. There are some plugins that add this feature to the file system store. Memcache gives it to you for free, and if you&amp;#8217;re relying on this heavily, I&amp;#8217;d use memcache.&lt;/li&gt;&lt;li&gt;Being in one of those good situations where the number of possible fragments is known, and you can expire them each explicitly. This didn&amp;#8217;t work for me in some of the critical areas that I needed to cache.&lt;/li&gt;&lt;li&gt;Storing a list (in the database) of the caches that you built up which need to be expired if a certain thing is changed.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Don&amp;#8217;t Expire, Just Render it Obsolete&lt;/h2&gt;&lt;p&gt;This article so far doesn&amp;#8217;t really capture how much pain this stuff has caused me, and I&amp;#8217;ll try and cover some other points in other articles. For now, lets jump straight to the good bit.&lt;/p&gt;&lt;p&gt;I&amp;#8217;ve read a lot of articles on caching, but this is the best, go read it:&lt;/p&gt;&lt;p&gt;&lt;a href="http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached"&gt;The Secret To Memcached &amp;#8211; by Tobias L&#252;tke&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Tobias also struggled with expiry, and his solution is to take advantage of the fact that if you&amp;#8217;re using memcache, then you can never cache too many items. The oldest ones get pushed out when you run out of of space.&lt;/p&gt;&lt;p&gt;So, here&amp;#8217;s my first bit of advice. If you&amp;#8217;re building a real site, go straight to memcache. If you&amp;#8217;re not building a site for big traffic, don&amp;#8217;t cache, just optimise any really stupid queries that are giving you trouble. If you&amp;#8217;re using memcache, be sure to run monit too.&lt;/p&gt;&lt;p&gt;So, we&amp;#8217;re running memcache, and we don&amp;#8217;t want to expire our fragments. Instead, try and find fragment keys that don&amp;#8217;t need to be expired, because they will be replaced if the data changes.&lt;/p&gt;&lt;p&gt;The one I&amp;#8217;ve just implemented was a stream of recent activity, much like facebook. Each little type of activity had a different template, and the rendering of this took up a lot of time. Fetching the data was also non-trivial. However, if I wanted to expire a cache of the activity stream, then I&amp;#8217;d need to do so anytime something occured on the site that triggered an activity for this user.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;&amp;lt;% cache ["activity_stream", @latest_activity.id, @user.id].to_s do %&amp;gt;&lt;br/&gt;   ... render the activities&lt;br/&gt;&amp;lt;% end %&amp;gt;&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&amp;#8217;s the code. The real example had a few more parameters, but you can see here that the magic is in the fact that I used @latest_activity.id as part of the key. I&amp;#8217;m still having to query that from the database, but it&amp;#8217;s pretty simple to do, and all I really need is one little integer, instead of all the activities and their associated objects. If a new activity is created for this user, then this id will have changed, and so I&amp;#8217;ll me asking for a different cache key.&lt;/p&gt;&lt;p&gt;Benchmarks for this are looking really good. I&amp;#8217;ll let you know how it goes in the wild, but I&amp;#8217;m not expecting too many problems as most of my previous troubles have been to do with expiry, and this code doesn&amp;#8217;t need any expiry. No sweepers, no regular expressions. It&amp;#8217;s simple, and it scales.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/caching">caching</category>
      <category domain="http://blog.craigambrose.com/past/tags/rails">rails</category>
    </item>
    <item>
      <title>Migrating from file_column to attatchment_fu</title>
      <link>http://blog.craigambrose.com/past/2007/9/9/migrating_from_file_column_to_attatchment_fu/</link>
      <pubDate>Sun, 09 Sep 2007 03:25:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/9/9/migrating_from_file_column_to_attatchment_fu/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;About a year ago, file_column was one of the most popular plugin for storing files, particularly images, in rails applications. These days, the most popular plugin is Rick Olsen&amp;#8217;s attachment_fu.&lt;/p&gt;&lt;p&gt;The main advantage of attachment_fu is it&amp;#8217;s ability to store the files either on the file system, in binary fields in the database, or on amazon s3. The pluggable nature of the code also makes it fairly easy to support some other storage service.&lt;/p&gt;&lt;p&gt;I&amp;#8217;ve avoided moving over because file_column actually provides more comprehensive image manipulation features, but there comes a time in the life-cycle of most applications where file system storage just doesn&amp;#8217;t cut it in a multi-server environment.&lt;/p&gt;&lt;p&gt;There are already tutorials on using attachment_fu, I&amp;#8217;m presuming that you already know how to use it. I&amp;#8217;m just going to help you make the switch. Lets start with some code, here&amp;#8217;s my migration for moving across the data:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;class CreateProfilePhotosFromFileColumn &amp;lt; ActiveRecord::Migration&lt;br/&gt;  def self.up&lt;br/&gt;    for profile in Profile.find(:all)&lt;br/&gt;      image_filename = select_value "SELECT image FROM profiles WHERE id = #{profile.id}" &lt;br/&gt;      unless image_filename.blank?&lt;br/&gt;        image_path = RAILS_ROOT + "/public/system/profile/image/#{profile.id}/#{image_filename}" &lt;br/&gt;        image_file = File.open(image_path, 'r')        photo = ProfilePhoto.new(:profile_id =&amp;gt; profile.id)&lt;br/&gt;        photo.set_from_file(image_file)&lt;br/&gt;        photo.save!&lt;br/&gt;      end&lt;br/&gt;    end&lt;br/&gt;  end  def self.down&lt;br/&gt;    execute "DELETE FROM profile_photos" &lt;br/&gt;  endend&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, I previously used file column in the field called &amp;#8220;image&amp;#8221; of my Profile model. Now, I have a new model called ProfilePhoto, which belongs_to Profile.&lt;/p&gt;&lt;p&gt;Although I&amp;#8217;m happy to loop through all profiles using regular active record finders, note that I didn&amp;#8217;t use the image method of profile. I know that after this works, I&amp;#8217;m about to remove everything to do with file column, and so to play it safe, I use assert_select to fetch the file column image name directly from the database. This is ugly, but good policy in general for producing migrations that keep working after the code changes.&lt;/p&gt;&lt;p&gt;The other trick here is the call to &amp;#8220;set_from_file&amp;#8221;. This method doesn&amp;#8217;t exist in attachment_fu, and was the first (of several) glaring omissions that I noticed in this plugin. To make this migration work, you&amp;#8217;ll need to make a few changes to attachment_fu.rb yourself.&lt;/p&gt;&lt;p&gt;The following goes inside the InstanceMethods module:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;def set_from_file(source_file)&lt;br/&gt;  source_file_extension = File.extname(source_file.path).reverse.chomp('.').reverse&lt;br/&gt;  source_file_name = File.basename(source_file.path)&lt;br/&gt;  self.content_type = self.class.mime_type_from_extension(source_file_extension)&lt;br/&gt;  self.filename = source_file_name&lt;br/&gt;  self.temp_data = source_file.read&lt;br/&gt;end&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following goes inside the ClassMethods module:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;def mime_type_from_extension(extension)&lt;br/&gt;  MIME::Types.type_for(extension).first.simplified&lt;br/&gt;end&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the following goes at the top of the file:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br/&gt;require 'mime/types'&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You&amp;#8217;ll also need to &amp;#8220;gem install mime-types&amp;#8221;, although you will already have this if you installed the amazon s3 library.&lt;/p&gt;&lt;p&gt;This code is not hugely error tolerant. It presumes that all your records with file columns contain valid image files that are going to be accepted by your attachment_fu model. It also assumes that you set up attachment_fu correctly of course.&lt;/p&gt;&lt;p&gt;If it works, I would then add further migrations to remove the old file_column field from the Profile model, and to remove the file_column files themselves from the hard disk.&lt;/p&gt;&lt;p&gt;You&amp;#8217;ll probably find the set_from_file method to be a valuable addition to attachment_fu for other purposes too. Our applications often receive their data in ways other than just &lt;span class="caps"&gt;HTTP&lt;/span&gt; post, and being able to save a file object seems like a pretty obvious addition.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/attachmentfu">attachmentfu</category>
      <category domain="http://blog.craigambrose.com/past/tags/filecolumn">filecolumn</category>
      <category domain="http://blog.craigambrose.com/past/tags/migration">migration</category>
      <category domain="http://blog.craigambrose.com/past/tags/tutorial">tutorial</category>
    </item>
    <item>
      <title>In Response to Dave Thomas' RailConf 07 Keynote</title>
      <link>http://blog.craigambrose.com/past/2007/5/25/in_response_to_dave_thomas/</link>
      <pubDate>Fri, 25 May 2007 23:37:00 GMT</pubDate>
      <guid>http://blog.craigambrose.com/past/2007/5/25/in_response_to_dave_thomas/</guid>
      <author>craig@craigambrose.com (Craig Ambrose)</author>
      <description>&lt;p&gt;Conference keynotes often introduce plenty of new ideas and challenges to a development community, but they are a bit of a one way dialogue if we don&amp;#8217;t have a think about them and share our views. In particular Dave Thomas, of the Pragmatic Programers, is not shy about trying to inspire programmers to take new directions, and I always look forward to his keynotes in particular.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.flickr.com/photos/x180/509681296/" style="float: right; text-decoration: none; margin: 10px 0 10px 20px" &gt;&lt;img src="http://farm1.static.flickr.com/222/509681296_0b12654819_m.jpg"   alt="Dave Thomas"/&gt;&lt;div style="color: #666; font-size: 80%; text-align: right; text-decoration: none"&gt;photo by James Duncan Davidson&lt;/div&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;For RailsConf 07, Dave&amp;#8217;s talk centered around the idea of &amp;#8220;cargo cults&amp;#8221;. Cargo cults were popular on Pacific island nations, who emulated the activities of the Americans during the war, to the point of building runways, control towers, and trying to summon planes with coconut headphones, in order to make the cargo come. The metaphor here is that we, as rails developers, need to stop doing things just because they have worked for others in the past, and start being truly creative.&lt;/p&gt;&lt;p&gt;While it&amp;#8217;s hard to disagree with a call to be creative, I&amp;#8217;m going to go out on a limb and say that I don&amp;#8217;t think this is a particularly good direction for the Rails community to take at present.&lt;/p&gt;&lt;p&gt;Ruby on Rails has several strengths that make it quite unique. Some of these relate to the software itself, but these are minor compared to the strengths of the Rails community. There have been plenty of other open source ecosystems with a strong community, so what makes the Rails one different to, for example, the python community?&lt;/p&gt;&lt;p&gt;My belief, if you&amp;#8217;ll excuse me for stretching David&amp;#8217;s metaphor perhaps a little too far, is that it&amp;#8217;s our cargo cults. The rails community demonstrates a particular unity of purpose. While we are all out building our own crazy web applications, the opportunities for re-use of code and design ideas is particularly high. If you ask three python programmers how to build web applications, you&amp;#8217;ll get three different answers. If you ask three ruby programmers, statistically speaking, you&amp;#8217;re liable just to hear about Rails three times.&lt;/p&gt;&lt;p&gt;This goes further than just the dominance of Rails within the Ruby community. Even within Rails, we have our cargo cults. &lt;span class="caps"&gt;REST&lt;/span&gt; is a good example, and one mentioned during David&amp;#8217;s talk. Sure, there&amp;#8217;s life beyond &lt;span class="caps"&gt;REST&lt;/span&gt;, but the benefit of picking such an approach as a community, and sticking to it (at least for the next year or two), is staggering. If I build a RESTful application, it&amp;#8217;s no big deal, but if Rails developers everywhere build them, then suddenly there&amp;#8217;s an ecosystem of useful applications that can talk to each other in such a practical and simple way that it makes Soap developers weep.&lt;/p&gt;&lt;p&gt;Not only do we have our cargo cults, but we also have our high priests. The whole &lt;span class="caps"&gt;REST&lt;/span&gt; thing happened because at RailsConf 06, &lt;span class="caps"&gt;DHH&lt;/span&gt; said that we should do it. This year, he was a little more reserved, but was still quite happy to go out on a limb and pick some particular technologies which were &lt;strong&gt;more right&lt;/strong&gt; than others. One slide of his talk listed the friends and allies of the rails community. Our friends, we are told, include OpenID and Atom. There&amp;#8217;s no reason why the Ruby on Rails framework need to be particularly associated with either of these technologies, and from a technical perspective, it probably wont be. But &lt;span class="caps"&gt;DHH&lt;/span&gt; says that they are our friends. Suddenly, OpenID support is appearing in Rails apps all over the place. This is an amazing result which you can normally only see happen within a hierarchical organisation. Here we are seeing unity of purpose within a very anarchistic open source community.&lt;/p&gt;&lt;p&gt;So I say, investigating new ideas is fine, but be aware that there is great benefit to be gained by following the path that we&amp;#8217;re all traveling on together. People with different ideas from the Rails core team tend to write plugins, and if people think that the ideas are good enough, they eventually gain traction. Just take a look at the adoption of rspec within the rails community, even though it is quite different from the default testing system.&lt;/p&gt;&lt;p&gt;You can think of this as a cargo cult if you like, or laugh and say that rails developers have swallowed too much of their own hype. However, taking a common path that represents the combination of a range of views without simply all going our separate ways is a technique that works very well in nature.&lt;/p&gt;&lt;p&gt;Amongst humans, we call this technique consensus.&lt;/p&gt;</description>
      <category domain="http://blog.craigambrose.com/past/tags/RailsConf07">RailsConf07</category>
    </item>
  </channel>
</rss>
