Runtime change that lazily populates an action argument from the record's own relationships.
Installed automatically by AshGrant.Transformers.AddArgumentResolvers when a
resource declares resolve_argument in its ash_grant block. Users rarely
reference this module directly.
Options
:name— argument name to set:path— list of atoms walking relationships to a leaf attribute (e.g.[:order, :center_id],[:order, :customer, :organization_id]). Intermediate keys are belongs_to relationships; the last is an attribute.:scopes_needing— list of scope atoms whose resolved filter references^arg(<name>). Injected by the transformer at compile time.
Runtime contract
If the actor is nil, or none of the actor's permissions (as returned by the
resource's configured AshGrant.PermissionResolver) use a scope in
:scopes_needing, the change is a no-op — no DB load is performed.
If the resource has no resolver configured, or the resolver raises/returns
an unexpected shape, the change conservatively resolves the argument
rather than skipping — otherwise production actors (Ash resource structs
that carry no literal :permissions field) would silently bypass the
resolver.
Otherwise, the change resolves the path:
- create: read the first-hop foreign key from the changeset's attributes, fetch the head record, then walk the remaining path keys through loaded relationships.
- update/destroy: load the relationship path on
changeset.data, then read the leaf attribute.
If any intermediate value is nil or the path cannot be resolved (e.g., the
referenced record was deleted), the change returns the changeset unchanged —
the scope will then evaluate against a nil argument and typically fail
closed (authorization denied).
Multi-tenancy
The changeset's :tenant is forwarded to the internal Ash.get!/Ash.load!
calls so that resources along from_path using attribute multitenancy can be
fetched correctly. Without this, those fetches would raise, be rescued, and
leave the argument unset — causing the scope to evaluate to false.