apotonick/cells — Issue #92: Add rescue methods to Cells
Author: mateusz-sojka
Created: 2011-12-21 00:03:20+00:00
State: open

Hi there,
the three main reasons the company I work for started using Cells was:
- encapsulating different parts of a website's views so that there is a real isolation from the outside
- reusing blocks of code (Cells ;)
- degrading gracefully in case of error on production side

The two first requirements where very well solved "out-of-the-box" by the Cells gem. Nevertheless, the last one had to be implemented by rescuing the errors. At first time, it just checked if the Rails App was in production mode and just don't show anything so that the end user gets a better web experience even if there are some bugs on the website.

Now, we're moving further and want to get some more control over the Cells behavior, so I changed some pieces of code so now we can do:

# config/initializers/cells.rb

Cells.setup do |config|

# All errors are show by default in development and test
config.show_all_errors = [:test]
# Errors are hidden by default in production mode
config.show_no_errors = [:development, :production]
config.set_error_callback { "raise BigError or notificate Airbrake" }
end

And the changes I've made to the Cells code are:

# lib/cell/rails.rb

# Environment base behavior
#
# You can set Cells behavior depending on the current environment
# Default:
# development, test => :show_all
# production => :show_none
#

def self.default_environment_errors
@environment_errors = {
:development => :show_all,
:test => :show_all,
:production => :show_none
}
end
self.default_environment_errors

# Set the show_all strategy to an array of environments
def self.show_all_errors=(envs=[])
envs.each do |env|
@environment_errors[env] = :show_all
end
end

# Set the show_none strategy to an array of environments
def self.show_no_errors=(envs=[])
envs.each do |env|
@environment_errors[env] = :show_none
end
end

def self.set_error_callback
@error_callback = yield if block_given?
end

def self.notify_on_error_hook
eval @error_callback if @error_callback
end

And in

# lib/cell.rb

# Main entry point for #render_cell.
def render_cell_for(controller, name, state, *args)
cell = create_cell_for(controller, name, *args)
yield cell if block_given?
cell.render_state(state, *args)
rescue => exception
# TODO => add some callback / trigger method here
# Airbrake.notify(exception) if defined?(Airbrake)
notify_on_error_hook
if @environment_errors[ENV['RAILS_ENV'].to_sym] == :show_all
# The assumption is, there is a #rescue_from action in the Cell
# In my app, there is an application_cell with the rescue_from action, and every other Cell inherits from it
cell.render_state(:rescue_from, exception, state)
else
""
end

end

So the question is: do you think you could use it in your project? If there is some interest on your side, we can talk about where to put this code and how should the tests look like so later I can make a pull request. Also, I'm planning to go further in this direction, so

Waiting for your feedback, thanks!