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
1 Like
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
4 Likes