class RailsDynamicErrors::DynamicErrors

This is a Rack compatible middleware that implements the key functionality of the rails_dynamic_errors gem. It serves two roles:

The middleware is inserted into the Rails application’s middleware stack automatically. As such, the end user should never need to use it directly.

In order to avoid disrupting standard Rails functionality, this middleware respects the Rails exception handling related configuration options. As such, it will only process exceptions and error conditions if:

Configuration of which exceptions and error conditions to catch is done within the main Rails application’s configuration, using an option set namespaced to rails_dynamic_errors. Specifically:

Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle

This option must be an array of integer HTTP error status codes (404, etc.)

Public Class Methods

new(app) click to toggle source

Initialize the middleware (standard Rack method)

# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 27
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source

Call the middleware (standard Rack method)

# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 32
def call(env)
  response = @app.call(env)
  # 404 errors for unmatched routes aren't actually raised until
  # ActionDispatch::DebugExceptions. If we're supposed to catch 404s and
  # the application indicates there was no matching route, throw and
  # handle a 404 generating exception
  if can_process_exceptions?(env) && catch_not_found_error? && request_unhandled?(response)
    raise ActionController::RoutingError.new("No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}")
  else
    response
  end
rescue Exception => exception
  if can_process_exceptions?(env)
    process_exception(env, exception)
  else
    raise exception
  end
end

Private Instance Methods

can_handle_http_error_status_code?(status_code) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 60
def can_handle_http_error_status_code?(status_code)
  http_error_status_codes_to_handle.include?(status_code)
end
can_process_exceptions?(env) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 52
def can_process_exceptions?(env)
  ! env['action_dispatch.show_detailed_exceptions'] && env['action_dispatch.show_exceptions']
end
catch_not_found_error?() click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 56
def catch_not_found_error?
  can_handle_http_error_status_code?(404)
end
dynamic_error_path(status_code) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 93
def dynamic_error_path(status_code)
  # Error page routes need to reflect where the engine has been mounted
  "#{RailsDynamicErrors::Engine.mounted_at}/#{status_code}"
end
exception_http_error_status_code(env, exception) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 82
def exception_http_error_status_code(env, exception)
  wrapper = ActionDispatch::ExceptionWrapper.new(env, exception)
  wrapper.status_code
end
generate_dynamic_error_page(env, exception, status_code) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 87
def generate_dynamic_error_page(env, exception, status_code)
  env['PATH_INFO'] = dynamic_error_path(status_code)
  env['action_dispatch.exception'] = exception
  Rails.application.routes.call(env)
end
http_error_status_codes_to_handle() click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 64
def http_error_status_codes_to_handle
  Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle || []
end
process_exception(env, exception) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 73
def process_exception(env, exception)
  status_code = exception_http_error_status_code(env, exception)
  if can_handle_http_error_status_code?(status_code)
    generate_dynamic_error_page(env, exception, status_code)
  else
    raise exception
  end
end
request_unhandled?(response) click to toggle source
# File lib/rails_dynamic_errors/middleware/dynamic_errors.rb, line 68
def request_unhandled?(response)
  # Returned by Rails when no matching route was found
  [404, {'X-Cascade' => 'pass'}, ['Not Found']] == response
end