ash/documentation/topics/manual-actions.md

68 lines
2.5 KiB
Markdown
Raw Normal View History

All validation still takes place, but the `result` in any `after_action` callbacks
attached to that action will simply be the record that was read from the database initially.
For creates, the `result` will be `nil`, and you will be expected to handle the changeset in
an after_action callback and return an instance of the record. This is a good way to prevent
Ash from issuing an unnecessary update to the record, e.g updating the `updated_at` of the record
when an action actually only involves modifying relating records.
You could then handle the changeset automatically.
For example:
# in the action
```elixir
action :special_create do
manual? true
change MyApp.DoCreate
end
# The change
defmodule MyApp.DoCreate do
use Ash.Resource.Change
def change(changeset, _, _) do
Ash.Changeset.after_action(changeset, fn changeset, _result ->
# result will be `nil`, because this is a manual action
result = do_something_that_creates_the_record(changeset)
{:ok, result}
end)
end
end
2022-08-17 04:39:35 +12:00
```
# for manual reads
Manual read actions will simply be handed the ash query and the data layer query.
If you simply want to customize/intercept the query before it is sent to the data layer
then use `modify_query` instead. Using them in conjunction can help ensure that calculations and aggregates
are all correct. For example, you could modify the query to alter/replace the where clause/filter using
`modify_query` which will affect which records calculations are returned for. Then you can customize how it is
run using `manual`.
```elixir
# in the resource
actions do
read :action_name do
manual MyApp.ManualRead
# or `{MyApp.ManualRead, ...opts}`
end
end
# the implementation
defmodule MyApp.ManualRead do
use Ash.Resource.ManualRead
def read(ash_query, ecto_query, _opts, _context) do
...
{:ok, query_results} | {:error, error}
end
end
```