Exceptions and request formats.

How to handle ActionView::MissingTemplate exceptions and to render the html version of the 404 template irrespective of which format the original request is being made for.

In the recently released realestate.com.au/share application, one of the most consistent exceptions we received was an “ActionView::TemplateMissing” exception because someone or something was hitting the following URLS.

http://www.realestate.com.au/share/share+accommodation-some-location.xml
http://www.realestate.com.au/share/share+accommodation-some-location.zip

The logical decision was to rescue these exceptions in the ApplicationController itself and serve the generic 404 page. So initially, we had a simple rescue block:

rescue_from "ActionView::MissingTemplate" do |exception|
  respond_to do |format|
    format.any {
      render "error_pages/404",
        :status => :not_found
    }
  end
end

This kept causing a TemplateNotFound exception because even though we were trying to respond to any format, it was still expecting the 404 template to exist in a zip or xml format. Having a symlink as 404.xml.erb or 404.zip.erb also is a bad solution because the expectation of the format is cascading i.e. any views rendered within the 404 would also be expected to have that format, and generally thats a bad idea. So I decided to simply override the request format in this particular case and save myself the trouble. Hence:

rescue_from "ActionView::MissingTemplate" do |exception|
  request.format = :html
  render "error_pages/404",
    :status => :not_found
end