Class: Ruact::ServerFunctions::StandaloneDispatcher
- Inherits:
-
Object
- Object
- Ruact::ServerFunctions::StandaloneDispatcher
- Defined in:
- lib/ruact/server_functions/standalone_dispatcher.rb
Overview
Story 8.3 — execution path for STANDALONE server actions (host modules that ‘extend Ruact::ServerAction`). Invoked by EndpointController#dispatch_action when the resolved registry entry’s host is a Module rather than an ‘ActionController::Base` subclass.
Differences from the controller-hosted path (Story 8.1):
- No `host_class.dispatch` — no Rails `process_action` callback
chain, no `before_action` filters, no `rescue_from` on the host.
The dispatcher is in charge of the entire response cycle.
- The block runs via `instance_exec` on a fresh
{Ruact::ServerFunctions::StandaloneContext}, not on a controller
instance. The context exposes `params` / `session` /
`current_user` / `request` / `cookies` / `headers`; it does NOT
expose `render` / `redirect_to` / `head` (the block's return
value IS the response).
Same contract for response shape (parity with Story 8.1):
- `nil` block return → 204 No Content
- Hash / Array / scalar block return → 200 + JSON body
- `raise Ruact::ActionError.new(status:, body:)` → that status + JSON body
Defined Under Namespace
Classes: Result
Class Method Summary collapse
-
.apply_to_response(result, response) ⇒ Object
Writes a Result onto an ‘ActionDispatch::Response`.
-
.dispatch(entry, request, response = nil) ⇒ Result
Render directive describing the response.
Class Method Details
.apply_to_response(result, response) ⇒ Object
Writes a Result onto an ‘ActionDispatch::Response`. Used by tests/benches that drive the dispatcher directly (the request-cycle path goes through `EndpointController#dispatch_action` which calls `render` / `head` so Rails’ ‘ImplicitRender` does not interfere).
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/ruact/server_functions/standalone_dispatcher.rb', line 79 def apply_to_response(result, response) response.status = result.status if result.body.nil? || result.body.empty? response.headers.delete("Content-Type") response.body = "" else response.headers["Content-Type"] = result.content_type if result.content_type response.body = result.body end end |
.dispatch(entry, request, response = nil) ⇒ Result
Returns render directive describing the response.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/ruact/server_functions/standalone_dispatcher.rb', line 44 def dispatch(entry, request, response = nil) begin raw_args = extract_args(request) rescue JSON::ParserError => e # Story 8.3 review R3 — mirror the controller-DSL path's # structured 400 contract (see `Ruact::Controller#ruact_action`, # Re-run-4 2026-05-15). A malformed `application/json` body # is a client bug; surface it as JSON {error} + 400 so the # runtime's RuactActionError surface reports it cleanly. result = build_malformed_json_result(entry, e) apply_to_response(result, response) if response return result end params = ActionController::Parameters.new(raw_args) context = StandaloneContext.new(params: params, request: request) result = begin raw = context.instance_exec(params, &entry.block) build_success_result(raw) rescue Ruact::ActionError => e build_error_result(e) end maybe_warn_unread_current_user(entry, context) apply_to_response(result, response) if response result end |