Hook context
Read the user, current and saved values, and request information available inside a hook.
Every hook receives an argument usually named ctx that describes the current operation.
Collection and global hooks receive a ridu.HookContext, which holds the whole document. Field
hooks receive an operation.Context and their own value as a separate argument.
Collection and field contexts
The two contexts answer the same questions in different ways:
| To… | In a collection or global hook | In a field hook |
|---|---|---|
| Check what is happening | ctx.Operation |
ctx.Operation |
| Identify the signed-in user | ctx.Actor, a document; nil when anonymous |
ctx.Actor.ID; empty when anonymous |
| Read the values being saved | ctx.Data |
The value argument, ctx.Siblings, ctx.Root |
| Read the saved values before a change | ctx.Original |
ctx.Prior, for this field’s group or row |
| Change what is saved | Set entries in ctx.Data |
Return operation.Set(...) or operation.Clear |
| Change the response | Set entries in ctx.Document.Values |
Return a change from an .AfterRead(...) hook |
| Read another document | ctx.Local.Find(...) |
ctx.Local.FindByID(...) |
| Save another document | ctx.Local.Create(...), Update, or Delete |
Not available; use a collection hook |
| Check the content locale | ctx.Locale |
ctx.Locale |
The complete lists are in collection hook arguments and field hook arguments.
Change stored values or response values
In a collection hook, change what is saved by setting entries in ctx.Data before the save:
ctx.Data["lastEditedBy"] = store.String(ctx.Actor.ID). The hook returns only an error, never a
replacement document, and assigning a new map to ctx.Data does not replace Ridu’s map.
After the save, ctx.Document holds the document Ridu returns. Changing ctx.Document.Values
in AfterChange, AfterOperation, or AfterRead changes the response only; the saved document
stays the same.
ctx.Operation names the whole operation, not the current hook. An AfterRead hook preparing
the response to a create sees operation.Create, not operation.Read. Write hooks see the
locale being written; AfterRead sees the response locale, whose values may include fallback
text from another locale.
Read other fields from a field hook
A field hook receives read-only views of the values around it:
ctx.Siblingsholds this field and the other fields in the same group or array row.ctx.Rootholds the document’s top-level fields.ctx.Priorholds the saved version of the same group or row before this operation.
title, _ := ctx.Siblings.String("title")
price, _ := ctx.Siblings.Get("price").NumberValue()
previousTitle, _ := ctx.Prior.String("title")Changing a map or list read from these views does not change the document. Return
operation.Set(...) or operation.Clear[T]() to change the hook’s own field. See
Using other field values for nested rows, translations, and
related-document lookups.
Pass the user and locale to related operations
A collection or global hook’s ctx.Local is the ordinary local API. When a nested operation
should use the same user, pass Actor: ctx.Actor and ActorCollection: ctx.ActorCollection in
its options. Pass Locale: ctx.Locale when it should use the same content language. These
options are not filled in automatically; a nil actor makes an anonymous request.
Pass ctx.Context to share the active transaction and request cancellation. The
AfterChange audit example passes all of these, and
Save related documents together
explains what rolls back when a related write fails.
The field context’s ctx.Local.FindByID reader already carries the user, auth collection, exact
locale, and transaction. It only supports reads; use a collection or global hook for related
writes.
Avoid triggering the same hook again
A local API call runs the target collection’s hooks too. If a posts hook writes an audit entry,
attach it to posts only; attaching it to the audit collection would make each log entry create
another log entry. Similarly, updating a post from its own AfterChange hook can start a loop.
Ridu rejects excessive recursion, but design the hook so it does not call itself. Change
ctx.Data before saving when the change belongs to the same document. Use a separate collection
when the hook creates a related record, and check what that collection’s hooks will do.
Calls made from AfterCommit use new transactions and can trigger hooks again. Keep notification
hooks focused on delivery instead of updating the same document after every save.
Read unsaved values during a live check
A .LiveValidate(...) callback receives operation.LiveValidationContext. It has the unsaved
form values and saved values for comparison, but no writable ctx.Data. Defaults and save hooks
have not run, and related lookups through ctx.Local are read-only.
See Live server validation for its context properties and lookup limits. These checks run separately from document and field hooks.