Sass with Rails - avoiding disappearing stylesheets in production

A few days ago I noticed that some of the pages on the Hotels app on wego.com were completely unstyled. They turned out looking rather Jakob Nielsen-istic:

Wego.com Hotels - no CSS


But we were attached to our ugly shade of green to leave those pages in their naked glory. Preliminary CSI work told me that some cached stylesheets generated by Rails were empty files. Why is this is happening?

stylesheet_link_tag and the :cache option

Was I overriding the stylesheets generated by Rails in different pages? Because we have a lot of cobranded sites and country sites on wego.com, I use the :cache option when using stylesheet_link_tag very often.

For example, the main wego.com site’s layout template has a stylesheet_link_tag like this (in reality there are a whole lot more stylesheets):

<%= stylesheet_link_tag 'yui/reset-fonts', 'search',  :cache => 'cache/search/listings' %>

When I need to make a new page for a cobranded site, I’ll create a new layout template with this:

<%= stylesheet_link_tag 'yui/reset-fonts', 'search', "sites/#{current_site}/cobrand", :cache => "cache/#{current_site}/search/listings" %>

Oftentimes I’d copy and paste (boo and hiss all you want!) the stylesheet_link_tag from one layout template to another and forget to update the cache path (the :cache => '/path/to/stylesheet' part). Two different stylesheet sets being cached to the same path is naturally a very stupid thing to do. So this wasn’t it, but it’s good to point this out because I have made this mistake at least 2 times!

Don’t check in generated CSS files by accident

Next, since I was using Sass, I was by now pretty sure that was it. First things first: did I check in a generated CSS file into source control (we use Git)? It’s another amateur mistake, but unsurprisingly, I’ve done this a couple of times. I think I’d wasted about an hour hunting down the reason for a style change that just wouldn’t show up. Yeah, I could have just added *.css to .gitignore, but I’m still using a mix of pure CSS and Sass templates.

The problem

In the end, I found this blog post by Ari Lerner on the CitrusByte blog about similar woes with Sass in production that set me on the path to a solution. It seems that when Rails encounters stylesheet_link_tag calls, it starts to pull together all the stylesheets and sometimes Sass is unable to generate the CSS files fast enough. Rails then throws an exception about not being able to find the CSS files and outputs an empty CSS file to the cache path.

The solution

The solution? Generate all the CSS files from Sass templates prior to restarting Rails when deploying. I added a rake task for updating all the Sass stylesheets:

namespace :sass do
  desc 'Updates stylesheets if necessary from their Sass templates.'
  task :update => :environment do
    Sass::Plugin.update_stylesheets
  end
end

Then, I created a mirror of this as a Capistrano task:

namespace :sass do
  desc 'Updates the stylesheets generated by Sass'
  task :update, :roles => :app do
    invoke_command "cd #{latest_release}; RAILS_ENV=#{rails_env} rake sass:update"
  end

  # Generate all the stylesheets manually (from their Sass templates) before each restart.
  before 'deploy:restart', 'sass:update'
end

Now, whenever I do a cap deploy, the stylesheets are generated before the Rails processes are restarted, ensuring that Rails’ stylesheet_link_tag helper is always able to find the pure CSS files when trying to merge them together and caching them to a single file.

9 Comments & TrackBacks (Add yours)

Paper doll icon
Geoff's Gravatar

Not experienced this yet but its nice to know. I’ve added a those Rake and Cap tasks to my deployment now so I should manage to avoid it in future.

Posted by: Geoff on August 7, 2008 11pm

Paper doll icon
A Fresh Cup » Blog Archive » Double Shot #265's Gravatar

[…] Sass with Rails - Avoiding Disappearing Stylesheets in Production - A good thing to know about dynamic stylesheets. […]

Posted by: A Fresh Cup » Blog Archive » Double Shot #265 on August 8, 2008 6pm

Paper doll icon
JasonOng's Gravatar

I didn’t realise Rails 2.1 has cache option for the stylesheet link helper. Thanks for the info!

Posted by: JasonOng on August 13, 2008 9am

Paper doll icon
David Salgado's Gravatar

Just curious - what’s your objection to checking in the generated CSS files?

I love using Sass while I’m tweaking my pages in development, but I prefer deploying with the generated CSS files. Or, do you have some clever dynamic CSS going on?

Posted by: David Salgado on August 13, 2008 4pm

Paper doll icon
Glenn's Gravatar

Good tip. I really love using Sass, going back to regular CSS feels so clumsy now.

Posted by: Glenn on August 20, 2008 7pm

Paper doll icon
tabrez's Gravatar

“I found this blog post by Ari Lerner[…]”

the correct url is: http://blog.citrusbyte.com/2008/03/20/sass-production-woes-in-rails/

Posted by: tabrez on August 31, 2008 2pm

Paper doll icon
Chu Yeow's Gravatar

@David Salgado: Actually, I have no objections against checking them in. Would save me quite a few headaches too like the one I just wrote about in this post!

Posted by: Chu Yeow on September 12, 2008 2pm

Paper doll icon
mann's Gravatar

Real great tip and i had learned a lot today. Thank you.

Posted by: mann on September 14, 2008 2pm

Paper doll icon
sass in production with caching — award tour's Gravatar

[…] Sass with Rails - avoiding disappearing stylesheets in production. this bit me in the ass moments ago. […]

Posted by: sass in production with caching — award tour on October 7, 2008 11pm

You can subscribe to the RSS feed for comments on this post.

Post a comment

(required)

(required, but never displayed)


You can format your comments using XHTML. Your email address will not be displayed or used for nefarious purposes.

Only following tags are allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>