diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index a25f2f6d..18195e19 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -2429,33 +2429,47 @@ defmodule Ash.Changeset do )} :error -> - [first_pkey_field | _] = Ash.Resource.Info.primary_key(changeset.resource) + if changeset.action.type == :update || Map.get(changeset.action, :soft?) do + [first_pkey_field | _] = Ash.Resource.Info.primary_key(changeset.resource) - full_atomic_update = - expr( - if ^condition_expr do - ^error_expr - else - ^atomic_ref(changeset, first_pkey_field) - end - ) + full_atomic_update = + expr( + if ^condition_expr do + ^error_expr + else + ^atomic_ref(changeset, first_pkey_field) + end + ) - case Ash.Filter.hydrate_refs(full_atomic_update, %{ - resource: changeset.resource, - public: false - }) do - {:ok, full_atomic_update} -> - {:cont, - atomic_update( - changeset, - first_pkey_field, - full_atomic_update - )} + case Ash.Filter.hydrate_refs(full_atomic_update, %{ + resource: changeset.resource, + public: false + }) do + {:ok, full_atomic_update} -> + {:cont, + atomic_update( + changeset, + first_pkey_field, + full_atomic_update + )} - {:error, error} -> - {:halt, - {:not_atomic, - "Failed to validate expression #{inspect(full_atomic_update)}: #{inspect(error)}"}} + {:error, error} -> + {:halt, + {:not_atomic, + "Failed to validate expression #{inspect(full_atomic_update)}: #{inspect(error)}"}} + end + else + {:cont, + filter( + changeset, + expr( + if ^condition_expr do + ^error_expr + else + true + end + ) + )} end end else diff --git a/test/actions/bulk/bulk_destroy_test.exs b/test/actions/bulk/bulk_destroy_test.exs index 0f7eb687..4e7c0aeb 100644 --- a/test/actions/bulk/bulk_destroy_test.exs +++ b/test/actions/bulk/bulk_destroy_test.exs @@ -129,6 +129,10 @@ defmodule Ash.Test.Actions.BulkDestroyTest do end end + destroy :destroy_with_validation do + validate attribute_does_not_equal(:title, "can't delete") + end + destroy :destroy_with_argument do require_atomic? false @@ -425,6 +429,29 @@ defmodule Ash.Test.Actions.BulkDestroyTest do assert [] = Ash.read!(Post) end + test "runs validations" do + assert_raise Ash.Error.Invalid, ~r/must not equal "can't delete"/, fn -> + assert %Ash.BulkResult{ + records: [ + %{title: "title1", title2: nil}, + %{title: "title2", title2: nil} + ] + } = + Ash.bulk_create!([%{title: "can't delete"}, %{title: "title2"}], Post, :create, + return_stream?: true, + return_records?: true + ) + |> Stream.map(fn {:ok, result} -> + result + end) + |> Ash.bulk_destroy!(:destroy_with_validation, %{}, + resource: Post, + return_records?: true, + return_errors?: true + ) + end + end + test "runs after batch hooks" do assert %Ash.BulkResult{ records: [