Sharing CSS between Rails and PHP

Many web sites are built using a variety of web applications, using different web frameworks. These sub sites share the same branding and ought to re-use the same CSS and images. How do you re-use these files within your Rails application, without the maintenance overhead of copying and pasting the code into each new application?

I'm currently working on a project which is partly implemented in PHP, partly in WordPress, and partly in Ruby on Rails. There are some Merb and Sinatra applications waiting in the wings, and they all need to share the same layout and branding.

The Problem

Copying and pasting the CSS into each of these projects would clearly cause maintenance difficulties. The CSS used on each project would quickly diverge, causing inconsistencies in the design of each section of the site.

It seems as though all the applications have to share the same CSS files. When your applications are stored in separate directories and are served by different web servers, how do you go about sharing them?

We concluded that we'd serve the CSS and images from /assets when running in production mode on the live server. Apache was running the PHP site, so it would have been easy to create a new top level assets directory in the PHP project and serve all the content from there.

There were two problems with this approach:

  1. The PHP developers might want to make a layout change to their HTML and update the CSS accordingly, breaking the layout of all the other applications that used the CSS. This would be an easy mistake to make as there would be no hint that their changes would affect all the other applications.
  2. We don't develop the Rails applications under Apache, so /assets wouldn't be available to the Rails team during development.

The Solution

We decided to fix the first problem by creating a new project for the CSS and images that define the layout and brand. We then configured Apache to serve these files from /assets:

<Directory /var/apps/assets/current/public>
    Order allow,deny
    Allow from all
</Directory>
Alias /assets /var/apps/assets/current/public

This took care of the PHP side of things, as /assets would be available both in development, and in production (the developers just need to symlink the public directory to their local copy of the source code).

The Rails team were no better off at this point, as they develop using a local copy of Mongrel running on port 3000. In production the CSS will be available under /assets, so we need to serve it from http://localhost:3000/assets during development.

You can set this up by creating a symlink to a local copy of the assets. We added this code to config/environments/development.rb:

def symlink_to_shared_assets
  assets_path = File.join(RAILS_ROOT, "..", "assets", "public")
  if ! File.exist?(assets_path)
    $stderr.write("ERROR: can't find the assets module\n")
    exit 1
  end

  if ! File.exist?("public/assets")
    require "fileutils"
    FileUtils.ln_sf(assets_path, "public/assets")
  end
end

symlink_to_shared_assets

It's working rather nicely.