Written September 3, 2008. Tagged Shell scripting, Rack.
When you visit /page?format=foo
(and sometimes /page.foo
, depending on the routes) in a Ruby on Rails app, Rails will try to render the action in that format - that is, using the page.foo.erb
template.
If you use the
respond_to do |wants|
wants.html { … }
wants.xml { … }
end
syntax, requesting an invalid format gives you an empty "406 Not Acceptable" response.
Actions that do not use this syntax, though, will cause an ActionController::MissingTemplate
exception – which the user sees as an unsightly "500 Internal Server Error".
That means actions that render implicitly like
def page
@page = Page.find(:first)
end
as well as explicitly like
def page
@page = Page.find(:first)
render :layout => 'example'
end
I don't want to show the 500 page unless necessary. In this case, a 404 page makes some sense; you could also argue for using a 406 error (for consistency with respond_to
, if nothing else).
I added this to my ApplicationController
:
# With +respond_to do |format|+, "406 Not Acceptable" is sent on invalid format.
# With a regular render (implicit or explicit), this exception is raised instead.
# Log it to Exception Logger, but show users a 404 page instead of error 500.
rescue_from(ActionController::MissingTemplate) do |e|
log_exception(e)
request.format = :html
render_404
end
The log_exception(e)
line should obviously be changed or removed if you don't use Exception Logger, or don't want the errors logged.
render_404
was described in an earlier blog post. If you prefer an empty error 406, a simple
head(:not_acceptable)
should do it.
Note that none of this affects the 406 error when passing an invalid format to a respond_to
action.