Rails incorrectly caches RSS feed as HTML

| |

Here’s the scenario: a site with a page which is served in two formats. http://www.example.com/sample returns HTML, and shouldn’t cache it. http://www.example.com/sample.rss returns an RSS feed, which should be cached. In Rails, we should be able to achieve this by including this code at the top of the controller:

caches_page :sample, :if => Proc.new { |c| c.request.format.rss? }

What this is saying is, if the format of the request is rss, cache it; otherwise, don’t. Because this was page cached, it would create a file public/sample.rss which would get returned in response to any requests; deleting this file equates to invalidating the cache.

The symptom we started seeing, irregularly, was that suddenly http://www.example.com/sample would return RSS. This turned out to be because the RSS feed was getting saved in public/sample.html. To solve the problem, we had to figure out how the RSS feed was getting cached as if it was HTML.

The answer turned out to be a poorly-formatted URL. If you request http://www.example.com/sample?format=rss, the response is (correctly) RSS, but the extension of the cached file is (incorrectly) .html.

In order to work around this bug, we removed the caches_page line from the top of the controller, and instead used cache_page within the response block of the action in question. cache_page accepts two parameters, the string to be cached and the key (the path, in this case) to cache it at, so we could force the cache filename.


respond_to do |format|
format.html
format.rss {
render :layout => false
cache_page(@response, "/sample.rss") }
end

The result here is that HTML is never cached (as required), and when RSS is cached, it is always cached with an .rss extension. The drawback is that the funky URL will never get a cache hit; it will always be generated from Rails (and update the cache while it’s at it). However, that’s an acceptable trade-off for not generating bogus cache files in the first place.

The kludgy part of this–aside from needing to do it in the first place–is using @response in the controller, which we’re not supposed to do. I wish there was a more elegant way of getting the content of the response for caching.

I think this is a bug somewhere in Rails’ caching code, but I haven’t yet dug in to see where or how it could be fixed.

The problem with our office

| |

We moved in to this office in November, and it was already pretty chilly. It’s warmed up enough now that we’re opening the windows a bit, and we’ve discovered this means the office smells like a kitchen. More specifically, it smells like Bueno Y Sano.

More positive press for HitFix

| |

Back in March, our friends at HitFix got some press from BusinessWeek, which listed them among “America’s Most Promising Startups.”

Template building

| |

Another area CMI works in is taking complete designs from clients and rendering valid (X)HTML and CSS from the design documents. It feels like a pretty basic service, but it frees designers (who know what looks good) from the requirement of knowing HTML, and lets them create functional and interesting designs without worrying about how they’re going to realize them in markup. From the other direction, letting design proceed in parallel with code development means the developers won’t find themselves with working code and undesigned pages, a situation which (in our experience) usually leads to launching with a rushed and poorly-thought-out design.

We’ve mentioned our work on FlyFi before; the designers, Corey McPherson Nash, recently sent out a press release highlighting their role in the project.

Another project we worked on over the winter recently went live when Running USA launched their new site. Running USA, a trade organization promoting the sport and industry of running, started down the site overhaul road nearly a year ago. We consulted with them over the summer, assisting them in identifying the major issues to be addressed by a new site, drafting the eventual RFP, and advocating implementation of particular technologies. As the project moved forward, we worked with the project managers (a company apparently so busy they don’t have a completed website yet) to turn their wireframes and comps into valid templates.

In both cases, our deliverables don’t look like much in a desktop folder: a few .html files and even fewer .css files. But being able to count on the templates to deliver (and across browsers – thanks, Litmus) isn’t measured in file counts.

“Project” project

| |

There have been some big projects happening in the office over the last few months, which we’ll tell about when they’re public (there should be several emerging over the next few weeks). A smaller one, and I hope she’ll forgive me for describing her site that way, has emerged into the public light: we’ve been doing some Wordpress tweaking for Project Happily Ever After.

PHEA, as we call it in the office (any title that long needs a TLA, even if it’s a FLA) is run by a former colleague of mine from Runner’s World, Alisa Bowman, and it’s Wordpress at the core. Beyond that core, however, PHEA uses several plugins, a custom page configuration, and a very custom theme. Wrangling all those players became our job, with the primary goal of shifting the theme from a three-column layout which left the content column too narrow for embedded video to a two-column layout. The result is easier to read and places the reading focus where it belongs: on Alisa’s columns, not on the sidebar material.

We’d love to claim credit for this, but actually Alisa is that rare and delightful client who knew exactly what she wanted; she just didn’t know how to make it happen. We demonstrated potential changes on a staging installation on one of our servers, and when they were approved, used Subversion to push theme changes out to the live site.

We have a lot of respect for Wordpress as a lightweight publishing system which is easy for non-technical users to pick up, but PHEA demonstrates that for users with a clear idea of their site’s function and the patience to try a few different options, it can also be a powerful tool for creating a rich site which is worlds apart from a cookie-cutter blog.

Moving a Rails/Mongrel site to Phusion Passenger on Ubuntu

| |

As I’ve noted before, several of our Rails projects are hosted using Phusion Passenger. We’ve been helping HitFix explore this option in recent weeks because it solves several minor deployment and restart frustrations they’ve been grappling with, and in the process I wrote up this walk-through for the installation.

This process is actually really easy and the instructions on the Passenger site and those provided during the installation process are excellent. The glitch we ran in to is that recent versions of Ubuntu and/or Apache 2.2.x use a slightly different method of loading modules and module configuration. (I haven’t run in to this method often enough to have learned whether it’s new in Apache or in Ubuntu.)

Instead of using one monolithic configuration file, sometimes offloading host configuration to included files, these Apaches instead globally include all modules found in the mods_enabled subdirectory of the Apache directory. Each module has two files, a .load file and a .conf file. The .load file contains only the LoadModule configuration directive; the .conf file contains any configuration directives.

Now, the actual files live in the mods_available subdirectory of Apache, and activating a module just means adding a symlink to the relevant files in mods_enabled, then restarting Apache. Deactivating it just means removing the symlink and restarting again.

With that in mind, here’s the Passenger process:

  • Install Passenger on the server. This should be as simple as:

sudo gem install passenger
sudo passenger-install-apache2-module

  • On one system, this second command actually told me that the Apache 2 Development Headers were missing. (Passenger needs these to compile the Apache module.) I needed to run sudo apt-get install apache2-prefork-dev to get these headers. This didn’t work on the first attempt, but running sudo apt-get update once or twice finally got me a successful install of that package. Running the passenger-install-apache2-module script then worked successfully. Note that you will need a compiler on the system in order to generate the Apache module. You would think you could take this for granted, but apparently not.

At this point, the module is built. This is where we have to adapt Phusion’s original installation instructions. Essentially, the next step is to make sure the module is loaded by Apache. Here’s how I did this:

  • Create a file at /etc/apache2/mods-available/passenger.load with the following content:

LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so

  • Create a file at /etc/apache2/mods-available/passenger.conf with the following content (I think the IfModule container may be optional, but I played safe):

<IfModule passenger_module>
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.0.6
PassengerRuby /usr/bin/ruby1.8
</IfModule>

  • Create symbolic links to both those files from /etc/apache2/mods-enabled/, i.e.

sudo ln -s /etc/apache2/mods-available/passenger.load /etc/apache2/mods-enabled/
sudo ln -s /etc/apache2/mods-available/passenger.conf /etc/apache2/mods-enabled/

We can restart Apache at this point without disturbing the existing site. Note that we can change which ruby is used (e.g. for Ruby Enterprise Edition) by altering the path at the PassengerRuby directive and restarting Apache.

To move a site to Passenger, you want to back up the file found at /etc/apache2/sites-available/yoursite, then edit it to make these changes:

  • Change the DocumentRoot to the public directory of the app, e.g. DocumentRoot /u/apps/yoursite/current/public
  • Comment out (with a #) all the lines related to the proxy, starting with the Proxy balancer definition and extending through all the ProxyPass, ProxyPassReverse and ProxyPreserveHost directives.
  • Restart Apache (/etc/init.d/apache2 restart). If something goes wrong, restore the backup you made of the configuration file and restart Apache again to restore the previous configuration.

The final trick is to update the restart task in Capistrano to handle restarting Passenger and not Mongrel. This is actually pretty easy, particularly if you’ve already overloaded the restart task in your config/deploy.rb file. Just replace the line reading run "mongrel_rails cluster::restart -C #{mongrel_config}" with one reading run "touch #{current_path}/tmp/restart.txt" and we’re good to go. The start and stop tasks probably also needs tweaking to remove the mongrel commands–probably pasting the same command in for “start” will do the trick unless we feel like putting Apache commands in.

BaselineNDA is a “pretty amazing application”

| |

Jason Mark Anderman of whichdraft.com:

I gave a presentation last week for the Association of Corporate Counsel’s Law Department Management Committee (there’s a mouthful!) entitled:

Web 2.0 for Contracts: Where to Go, What’s Free, What Costs Money

Anderman provides a list of sites he recommended in his presentation, including BaselineNDA, the application we built for Baseline Solutions Corporation. Here’s what Anderman had to say about BaselineNDA–with our emphasis added.

BaselineNDA (Pretty amazing application, with some limitations, it can read and mark up a confidentiality agreement for you)

Thanks, Jason! We think it’s pretty amazing, too, and we’re not even lawyers.

Styling anchor tags appropriately

| |

There’s a hitch in CSS styling of HTML a tags (“anchor” tags). The problem is that a tags are used for two different purposes: to establish a target, or “anchor,” for a link (e.g. <a name="anchorname">Link to this</a>), or to mark a section of text as a hyperlink (e.g. <a href="#anchorname">links to that</a>).

The first use of anchors is rare, nowadays. Every page has a default anchor, named “#“, which is set at the top of the page, and authors rarely set additional ones. They’re most frequently seen on Wikipedia pages, of all places, where subsections of the larger page are all anchored.

The problem comes in styling. What happens is that the text which is wrapped as an anchor gets styled as though it’s a hyperlink, even though without an href= attribute, it won’t work as one. This discourages a lot of webmasters from using anchors. One typical stunt is to not wrap anything at all, to create the anchor as <a name="anchorname" /> or <a name="anchorname></a> (the latter style is how Wikipedia does it). This isn’t available, however, to people using some kind of WYSIWYG editor in a CMS.

The real solution is to properly style a tags, and by “properly” I mean “not the way the default browser styles do it.” That means clearing styles from the a tag, and applying link appearance only to the :link, :hover, :active and :visited pseudo-elements.

Here’s how we did this for a recent project:

  • Style default a tags to look just like all other text:
a {
  text-decoration: inherit;
  font-style: inherit;
  color: inherit;
}
  • Now define the a:link pseudo-element to look the way you want your hyperlinks to appear. This pseudo-element is often ignored, but it’s the key to not applying link styles to your anchors. (We apply the same style to the :visited pseudo-element.)
a:link, a:visited {
 border:none;
 text-decoration:underline;
 font-style:normal;
 color:black;
}
  • Style the other pseudo-elements, because otherwise they won’t show differently from usual text (i.e. if :hover isn’t styled, links will appear to “disappear” when users mouse over them).
a:hover {
 text-decoration: none;
 color: #a3211f;
}

There’s no real trick here: all that’s involved is respecting the full definition of the a tag, and all the states allowed by its pseudo-elements.

HitFix is in Beta

| |

The site we spent the later part of December working on is now in public beta. HitFix is not the kind of site Noah and I imagined ourselves working on when we got started; it’s a site about entertainment and popular culture with commentary by industry insiders. But they needed more bodies who knew Rails as they pushed to launch, and their designer knew us from his previous job, so we got a call.

We can’t take credit for any individual aspects of the HitFix site; what we did was work as a team with HitFix’s internal Rails developer, Elliott Blatt, to make the site Beta-ready. This meant taking Photoshop demos and making fully-functional pages from them, working at all levels of the Rails stack. (We’ve been joking that our work on this site was in defiance of Brooks’s Law.)

Elliott has been a thrill to work with, having more experience with Rails than either of us, and we were surprised to find him learning from us almost as much as we were learning from him. What we’ve learned from this site is significant as well; it’s impossible to detail all the small conventions we’ve learned from Elliott, but one big example was learning HAML and its CSS sister, SASS.

It has also been an experiment in decentralized development, as some of the HitFix team is in California, Elliott is in Cambridge, and we’re in Amherst.

We’re still in active development with HitFix, but as I mentioned before, the beta is up, so if you’d like to take a look, you may find it interesting.

Name our drink

| |

The official Common Media caffeinated beverage of the winter is a large coffee from The Black Sheep across the street. The coffee is divided between two large mugs, to each of which is added a packet of hot chocolate mix and enough hot water to top off the mug. If the coffee is appropriately milked, it’s a pretty decent mocha.

So what do we call this? “The CMI” is inelegant. “Poor man’s mocha” isn’t bad, but a little bland, and it really saves time more than money (though it does save money). Maybe “The Subprime Mocha”?