Ruby on Rails is pretty neat stuff. Whenever I try to find out how to do something, it seems that I’m not the first to look. And, fortunately, many have usually solved that problem before. One thing that bugged me with Riding Resource was error pages. Sure, Rails allows you to create static 404 and 500 and other pages for those situations when things go awry. But the fact that those pages were static caused me some heartburn.
For one, if the layout of the website changed, it meant I needed to update the error pages. This is certainly not DRY. And, using static pages, I could not use any Ruby code in my error page, or do anything dynamically at all.
After some quick searching, I came across this post by Rob Hurring which lead me to this post on has_many :bugs, :through => :rails regarding how to create customized error pages with Ruby on Rails. Granted, neither of these solutions was exactly what I was looking for, so a little customization was required. However, the basic requirements were met.
- we can see that we can rescue_from many of the standard ActionController errors.
- using :with, we can specify a method to invoke to process the rescue activity
- the method called to rescue us can render a page with a layout
This took care of everything we needed. For almost all of the error types that would arise, we could redirect to a custom 404 template that allowed for Ruby to be embedded that would use any number of existing layouts, which keeps things tight and DRY.
One caveat that we had particularly related to Riding Resource was that meta tags are currently generated on the fly by a view helper, but we are actually looking at the current params to determine what controller/action we are in, and, therefore, what meta tags to spit out. Unfortunately, I could not find a way to detect, within the template, what status the template had been rendered with.
I ended up creating an instance variable before rendering the error template:
unless ActionController::Base.consider_all_requests_local # yeah, its a long line rescue_from ActiveRecord::RecordNotFound, ActionController::RoutingError, ActionController::UnknownController, ActionController::UnknownAction, :with => :render_404 rescue_from RuntimeError, :with => :render_500 end protected def render_404 @status = "404" render :template => "shared/404", :status => :not_found end
By creating this instance variable, I could then check for the value of @status in my meta tag generator and properly handle things.
One caveat to this solution, in general, is that errors that occur with your process of rendering the custom page will result in no errors being shown at all, except for in the log. Note Ron’s trick to be able to generate the custom error pages even while in development mode.
In the long term I will probably clean up the meta tag generator to create instance variables and then use partials to get the information into the view, but that’s for another day. We also recently added Thoughtbot’s Paperclip plugin to be able to easily attach pictures of facilities, but that post will be made once we get watermarking working.