There are a number of different ways to handle custom error pages in rails. Most use rails’s rescue_from method. This approach allows your error pages to be dynamically rendered in response to errors.
The way I see it, if my site has just encountered an error, I want to immediately go into damage control mode. Do I want to risk dynamically generating an error page? No, not at all. There could be an error in the page rendering that will cause another error when I try to render the error page. Not an ideal situation to say the least. It’s much safer to serve up previously generated static content.
While rails does come with a default, static, error page, said page is largely unstyled, and contains no links to help the user get back to what they were doing. I feel that it’s bad enough that I have to display an error to the user; leaving them with nowhere to go, looking at a jarring, or even ugly, error page isn’t going to make them the happy users that we all want.
Lastly, I don’t want to have to remember to keep the site’s error pages up to date with the latest layout and style.
To summarize, I want static error pages, rendered using rails’s ActionView, and I want them updated automatically any time the site’s style or layout changes.
To accomplish these goals I wrote a rake task and a capistrano recipe. The rake task visits the site, collects the rendered error pages, and stores them in the <RAILS_ROOT>/public directory, where rails will automatically look for them when errors occur. Here’s the rake task:
The capistrano recipe simply runs the rake task each time the application is deployed. Here’s the recipe:desc "Generate static error pages (404 and 500)"
task :generate_static_error_pages => [:environment] do
require "console_app"
urls_and_paths.each do |url, path|
r = app.get(url)
if 200 == r
File.open(Rails.public_path + path, "w") do |f|
f.write(app.instance_variable_get(:@body))
end
else
$stderr.puts "Error generating static file #{path} #{r.inspect}"
end
end
end
def urls_and_paths
[["/static/404_not_found", "/404.html"],
["/static/500_internal_server_error", "/500.html"],]
end
desc "Generate static error pages"
task :generate_static_error_pages, :except => {:no_release => true} do
run "cd #{current_path} ;
RAILS_ENV=production rake generate_static_error_pages"
end
I’ve instructed capistrano to execute this recipe each time I deploy my application by using one of capistrano’s many handy callbacks:
The result is that I have consistently styled, static error pages, that are updated automatically each time I deploy my application.after "deploy:symlink", "generate_static_error_pages"
Comments
Leave a comment Trackback