I am trying to DRY my resources. Some actions share logic partially. For example, the following two actions share the same logic except filter by department id.
How can I chain action or call an action inside another action?
read :active do
description "Gets ongoing and future time off requests"
filter expr(status == :approved)
filter expr((starts_at <= today() && ends_at >= today()) || starts_at > today())
end
read :active_by_department do
description "Gets ongoing and future time off requests by department"
argument :department_id, :uuid
filter expr(person.department_id == ^arg(:department_id))
# Repetitive code
filter expr(status == :approved)
filter expr((starts_at <= today() && ends_at >= today()) || starts_at > today())
end
You can’t “chain” them but you can create a single preparation that contains the logic for each. And then use
prepare Prepararion1
prepare Preparation2
Thanks. This worked for me. Below is the answer for someone who might be looking for the same solution in the future.
I extracted the logic into its own preparation
Final results
# What name should I give this action?
read :active do
description "Gets ongoing and future time off requests"
prepare MyApp.Leaves.LeaveRequest.Preparations.FilterActive
end
read :active_by_department do
description "Gets ongoing and future time off requests by department"
argument :department_id, :uuid
filter expr(person.department_id == ^arg(:department_id))
prepare MyApp.Leaves.LeaveRequest.Preparations.FilterActive
end
Preparation implementation
defmodule MyApp.Leaves.LeaveRequest.Preparations.FilterActive do
use Ash.Resource.Preparation
def prepare(query, _opts, _context) do
query
|> Ash.Query.filter((starts_at <= today() && ends_at >= today()) || starts_at > today())
|> Ash.Query.filter(status == :approved)
end
end