Module: Trane::Controller::ErrorHandler
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/trane/controller/error_handler.rb
Overview
Mixin that captures StandardError subclasses and maps them to
registered Trane errors. Resolves the exception class via the
precomputed errors_by_name index on the Registry snapshot —
single lookup on FQDN match, with a short-name fallback (via
String#rpartition) for hosts that registered errors by short
name. Include in your API base controller. Does NOT add
render contract: support — combine with Trane::Controller::Renderer
or use the composer Trane::Controller.
WARNING: this installs rescue_from StandardError at the class level. Including in a base controller that also serves HTML would catch errors Devise / Pundit / etc. expect to bubble up. Recommended: include only in API base controllers.
Rails-reserved exceptions (those in
ActionDispatch::ExceptionWrapper.rescue_responses, e.g.
ActiveRecord::RecordNotFound → 404, ActionController::ParameterMissing → 400)
are re-raised when no Trane error is registered for them, so Rails'
exception middleware applies its default status mapping. Hosts that
want to swallow these into the Trane envelope can register them
explicitly via Trane.errors { error "ActiveRecord::RecordNotFound", ... };
the Trane lookup wins over the re-raise path.
SECURITY NOTE: a registered error's envelope carries the exception's runtime #message, in EVERY environment including production. Framework and library exception messages are written for logs and may reveal internals (model names, query conditions). Prefer the recommended pattern (docs/wiki/Error-Handling.md) — rescue the framework exception and raise a domain error with a curated message — and register framework exceptions directly only when their messages are acceptable to expose.
PRODUCTION NOTE: re-raised exceptions surface via Rails' default
middleware. Keep config.consider_all_requests_local = false in
production so ActionDispatch::ShowExceptions serves the static
public/404.html / 500.html pages. With consider_all_requests_local
enabled in production, ActionDispatch::DebugExceptions would expose
the exception class + message + backtrace.
Class Method Summary collapse
-
.rails_reserved_names ⇒ Object
Returns the frozen Set of Rails-reserved exception class NAMES (Strings) derived from ActionDispatch::ExceptionWrapper.rescue_responses.
Class Method Details
.rails_reserved_names ⇒ Object
Returns the frozen Set of Rails-reserved exception class NAMES (Strings) derived from ActionDispatch::ExceptionWrapper.rescue_responses. Memoized on first call (after Rails boot completes). Returns an empty Set when Rails is not loaded.
Names, not Class objects, on purpose: memoizing classes would pin host-registered (Zeitwerk-reloadable) exception constants in the gem forever, and after a development reload the stale Class would no longer match its reloaded replacement. Names survive reloads.
NOTE: callers MUST invoke this post-boot. The Rails Engine initializers
merge AR/AC entries into rescue_responses during boot; calling this
earlier would memoize an incomplete list. In practice the first error
arrives in a request thread, which is always post-boot — but tests or
explicit pre-boot invocations would have to reset @rails_reserved_names
afterwards.
67 68 69 70 71 72 73 74 75 |
# File 'lib/trane/controller/error_handler.rb', line 67 def self.rails_reserved_names @rails_reserved_names ||= begin if defined?(ActionDispatch::ExceptionWrapper) Set.new(ActionDispatch::ExceptionWrapper.rescue_responses.keys.grep(String)).freeze else Set.new.freeze end end end |