Module: Ruact::ServerFunctions::ErrorPayload
- Defined in:
- lib/ruact/server_functions/error_payload.rb
Overview
Story 8.4 — Builds the structured JSON body returned by Ruact::ServerFunctions::ErrorRendering#__ruact_render_action_error for any server-action exception that bubbles past a host’s ‘rescue_from` chain.
The function is pure (no ‘Rails.env`, no `Ruact.config` reads) — the caller resolves `mode` (`:development` or `:production`) and passes it in. That keeps the module trivially testable without stubbing Rails env.
In ‘:development` mode the payload carries the full surface: action name, error class, message, split backtrace (first 25 frames per bucket), contextual suggestion, and (for `ActiveRecord::RecordInvalid`) the model’s ‘full_messages`.
In ‘:production` mode the payload is reduced to four baseline keys: `_ruact_server_action_error`, `action_name`, `error_class`, `message`. React components can render their own UI from those four fields without any accidental backtrace leakage on the wire.
Constant Summary collapse
- MAX_FRAMES_PER_BUCKET =
Maximum frames preserved per bucket. The full backtrace is still in the server log; the wire payload is for the overlay, which is unreadable past a couple of dozen frames anyway.
25
Class Method Summary collapse
Class Method Details
.build(action_name:, error:, mode:) ⇒ Hash{String=>Object}
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/ruact/server_functions/error_payload.rb', line 35 def self.build(action_name:, error:, mode:) # Pitfall #5: defensive dup against frozen-string `Exception#message` # implementations. = error..to_s.dup payload = { "_ruact_server_action_error" => true, "action_name" => action_name.to_s, "error_class" => error.class.name, "message" => } return payload if mode == :production frames = BacktraceCleaner.split(error.backtrace) payload["app_frames"] = frames[:app].first(MAX_FRAMES_PER_BUCKET) payload["gem_frames"] = frames[:gem].first(MAX_FRAMES_PER_BUCKET) payload["suggestion"] = ErrorSuggestion.for(error) validation_errors = extract_validation_errors(error) payload["validation_errors"] = validation_errors if validation_errors upload_limit = extract_upload_limit(error) payload["upload_limit"] = upload_limit if upload_limit payload end |