I’m trying to use change filter and custom validation in a single update action. The custom validation is atomic and validating fields through relationship.
It gives error related to the generated SQL. I’m new to Ash and maybe there are something that I’m missing.
Here’s the simplified code. Project has many task, and task can be updated only if the project is not canceled.
# Project resource
defmodule Project do
attributes do
attribute :is_canceled, :boolean
end
end
# Task resource
defmodule Task do
attributes do
attribute :name, :string
attribute :description, :string
attribute :is_deleted, :boolean
timestamps()
end
actions do
update :update do
change filter expr(is_deleted == false)
validate {CustomValidation,
fields: [:project, :is_canceled, :is_deleted],
expression: expr(not (project.is_canceled == false)),
message: "project is canceled"}
end
end
relationships do
belongs_to :project, Project
end
end
# Custom validation
defmodule CustomValidation do
@impl true
def atomic(_changeset, opts, _context) do
opts =
case opts do
{:templated, opts} -> opts
opts -> opts
end
{
:atomic,
opts[:fields],
opts[:expression],
expr(
error(Ash.Error.Changes.InvalidAttribute, %{
message: ^opts[:message]
})
)
}
end
end
The error is
(Postgrex.Error) ERROR 42703 (undefined_column) column s1.is_deleted does not exist
With the generated SQL
UPDATE "tasks" AS s0
SET "id" = s1."__new_id",
"description" = $1,
"updated_at" = $2,
"name" = $3
FROM
(SELECT ss0."id" AS "id",
(CASE
WHEN NOT ((sp1."is_canceled"::boolean = $4::boolean)
AND (ss0."is_deleted"::boolean = $5::boolean)) THEN ash_raise_error($6::JSONB, NULL::UUID)
ELSE ss0."id"::UUID
END) AS "__new_id"
FROM "tasks" AS ss0
LEFT OUTER JOIN "public"."projects" AS sp1 ON ss0."project_id" = sp1."id"
WHERE (ss0."id" = $7)) AS s1
WHERE (s0."id" = s1."id")
AND (s1."is_deleted"::boolean = $8::boolean) RETURNING s0."id",
s0."name",
s0."description",
s0."is_deleted",
s0."inserted_at",
s0."updated_at",
s0."project_id"






















