Posts for January, 2006

This isn’t Typo

Thought I should mention that this site isn't using Typo anymore. It had been running on a very old, and heavily customized version which made it extremely hard to upgrade. I started looking at converting to new version with themes and felt like it was overkill. What was once little Typo has really grown into a non-trivial app.

Instead, I whipped up something really simple called Post. A short list of features..

All in 431 lines of code and 423 lines of test. Remember when this stuff was hard?

A stack of books I no longer need

So long!

Here's the stack of books I sold to Powells today. Man, that felt good.

I traded for The Work of Charles and Ray Eames, By Design and Scandanavian Design to fuel my recent interest in modern furniture and architecture.

Adding that to the recently purchased The Elements of Typographic Style and The Elements of Style (1959 printing!) gives me quite a pile of reading to do.

Customizing disable_web for multiple sites

On Measure Map, we have two separate applications: the frontend that users log into and see their stats, and the tracker, where things about your blog are recorded. Links to tracker are sourced in users' blogs as Javascript, so they had better return valid Javascript code at all times, even when we take the application offline for maintenance.

Ok, so how do we override Switchtower's disable_web task to use a custom page? Here's one way. It assumes a custom page lives at config/templates/maintenance.rhtml.

task :disable_web do
  # Get the current path
  dir = `pwd`.chomp

  # Copy the template to the current path (this is where 'render' looks)
  `cp #{dir}/config/templates/maintenance.rhtml #{dir}/maintenance.rhtml`

  # Read in file with replacements
  maintenance = render("maintenance", :deadline => ENV['UNTIL'], :reason => ENV['REASON'])

  # Copy to the server
  put maintenance, "#{shared_path}/system/maintenance.html", :mode => 0644

  # Remove local copy
  `rm #{dir}/maintenance.rhtml`

  # Just in case something goes wrong, clean up
  on_rollback do
    `rm #{dir}/maintenance.rhtml`
    delete "#{shared_path}/system/maintenance.html"
  end
end

Remember when using the default mod_rewrite rules to support the maintenance page, you will redirect everything to this file, so you can't use any external stylesheet or image files unless you get tricky with mod_rewrite.

Cool, so now we have our own maintenance page. Next problem; how to use separate files for our two applications? Here's a nice DRY version that's easy to extend to as many roles as you need.

# Stay DRY by configuring the task
def move_maintenance_file(name)
  Proc.new do
    dir = `pwd`.chomp
    `cp #{dir}/config/templates/#{name}.rhtml #{dir}/#{name}.rhtml`
    maintenance = render(name, :deadline => ENV['UNTIL'], :reason => ENV['REASON'])
    put maintenance, "#{shared_path}/system/maintenance.html", :mode => 0644
    `rm #{dir}/#{name}.rhtml`
    on_rollback do
      `rm #{dir}/#{name}.rhtml`
      delete "#{shared_path}/system/maintenance.html"
    end
  end
end

# Define two new tasks for disabling web on our different applications
task :disable_web_frontend, :roles => :web_frontend, &move_maintenance_file('maintenance')
task :disable_web_tracker, :roles => :web_tracker, &move_maintenance_file('maintenance-tracker')

# Override disable_web to send different files to web_frontend and web_tracker
task :disable_web do
  disable_web_frontend
  disable_web_tracker
end

With this in place, we simply create two files, config/templates/maintenance.rhtml for the frontend, and config/templates/maintenance-tracker.rhtml for the tracker, and we're all set.