Module: Plutonium::Interaction::Concerns::Dispatchable
- Extended by:
- ActiveSupport::Concern
- Includes:
- Scoping
- Included in:
- Base
- Defined in:
- lib/plutonium/interaction/concerns/dispatchable.rb
Overview
Turns an interaction into a dispatcher: instead of doing the work inline, it persists a Async::Run, enqueues it, and sends the user to it.
The interaction keeps everything else it already was — it declares
inputs, validates them, renders a form, and is gated by the same policy
as before. Only #execute changes.
The outcome stays synchronous
call still returns an Outcome immediately, because dispatching is what
succeeded. Whether the WORK succeeds is the run's business, reported on
the run's own page — which is why Outcome needs no third "pending" state.
Nothing is passed in at the call site
Every value the run needs is already reachable: the targets are the +resource+/+resources+ the controller resolved through the policy scope, and the authorization triple comes from the controller the interaction is rendering in. So no controller and no host app has to hand a dispatching interaction anything an inline one does not already get.
What dispatch records, and why it is exactly this
The job has no controller, so Async::Context rebuilds the authorization context from the row. Three of the columns exist purely so that rebuild cannot silently widen:
authorization_namespace— the portal's module NAME. Without it, perform-time lookup falls back to the base policy and every narrowing the portal applied is lost.policy_class_name— the policy dispatch ACTUALLY RESOLVED, never an inferred "#ModelPolicy". A namespaced portal and an STI fallback both make the inferred name wrong, and Context refuses to run when the recorded name and today's lookup disagree.policy_action— the predicate, so perform re-checks PERMISSION and not merely visibility.
Defined Under Namespace
Modules: ExecuteOverride Classes: NotEnabledError