`:shared` context | automatically passing context to child actions
As part of the upcoming
Ash.Scope
capabilities, I decided to tackle something we've wanted for quite some time, which is the ability for some context to automatically be passed down to child actions & actions called from hooks. This will soon be in main
.
Here is the relevant docs:
Context
There are two kinds of contexts in Ash:
1. the context given to a changeset/action call, stored in changeset.context
,
2. the context given to a callback function like c:Ash.Resource.Change.change/3
, which contains
the above context in it's source_context
key, as well as additional information specific to the callback,
and/or commonly needed keys for callbacks (actor, tenant, etc.).
Actions accept a free-form map of context, which can be used for whatever you like. Whenever context is set, it is deep merged. I.e if you do changeset |> Ash.Changeset.set_context(%{a: %{b: 1}}) |> Ash.Changeset.set_context(%{a: %{c: 2}})
, the resulting context will be %{a: %{b: 1, c: 2}}
. Structs are not merged.
There are two special keys to note:
:private
The :private
key is reserved for use by Ash
itself. You shouldn't read from or write to it.
:shared
The :shared
key will be passed to all nested actions built by Ash, and should be passed by you to any actions you call within changes/preparations etc. Whenever :shared
context
is set, it is also written to the outer context. For example set_context(%{shared: %{locale: "en"}})
is equivalent to set_context(%{shared: %{locale: "en"}, locale: "en"})
This will generally happen automatically if you use one of the two abstractions provided by Ash for threading options through to nested action calls.
Careful with shared {: .warning}>
Shared context is passed to all nested actions, so don't pass massive values around, and also don't set context####
Ash.Scope
Ash.Scope
is newer and is the recommended way to do this. In action callbacks in Ash, you will be provided with a context, which can be passed down as a scope
option when running nested actions or building nested changesets/queries. For example:
#### Ash.Context.to_opts/2
Ash.Context.to_opts/2
is a helper function that converts a context map into a list of options that can be passed to nested actions. It automatically passes the shared
context to the nested action as well.
0 Replies