Within a large project that uses a lot of partials to load in page components, there are a lot of potential points of failure. Add in a developer new to the project, or a front-end developer pressed into service working directly on your views, and the chances of someone editing a partial without realising it’s used in several more places than they’d noticed are fairly high. And if the partial hits an error, the exception will roll all the way up the chain and the end-user will see your 500 page.
Now there are several things that should prevent this from being a problem. Your test coverage should be high enough and run often enough that a page throwing an exception will be noticed very quickly. The partials should be self-contained enough that it doesn’t really matter what context they’re called in. And the project should be well enough documented that a developer can quickly see what dependencies any given piece of code might have.
Every now and again that’s still not enough, or time doesn’t allow you to be quite as consistent as you might want. I’ve run into this particular problem a couple of times, and have just added a solution to one project that I hope will give us a little more protection should the worst happen and a problematic partial makes it into the live environment.
By adding the following code in a file that is loaded from config/environments/production.rb I’m able to trap any exceptions that might occur in a partial, log them, and ensure the worst that happens to a page is a blank space that should have contained content:
module ActionView
module Partials
private
def render_and_rescue_partial(partial_path, local_assigns = nil, deprecated_local_assigns = nil) #:nodoc:
unrescued_render_partial(partial_path, local_assigns, deprecated_local_assigns)
rescue => err
# This is where we handle the exception, logging it, emailing, or whatever
return ''
end
alias_method :unrescued_render_partial, :render_partial
alias_method :render_partial, :render_and_rescue_partial
end
end
Basically, it wraps itself around the standard render_partial method, captures any exceptions, handles them, and then returns an empty string. It wouldn’t be hard to extend it to be a little more refined and only capture errors from a certain subset of contexts.
This sort of error handling is a bad idea in a development environment, where you want to see errors as they happen to ensure you’re motivated to fix them. In production, this might help us look a little less foolish if something slips through the net, and let the user see the page they requested.