diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index ef757e411..174588c71 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -885,6 +885,20 @@ defmodule Ash.Changeset do {:error, _} -> {:cont, {:atomic, false}} + [{:atomic, _, expr, _as_error} | rest] -> + exprs = [expr | Enum.map(rest, &elem(&1, 2))] + + new_expr = + Enum.reduce(exprs, condition, fn expr, condition -> + if condition == true do + expr + else + expr(^condition and ^expr) + end + end) + + {:cont, {:atomic, new_expr}} + {:atomic, _, expr, _as_error} -> new_expr = if condition == true do diff --git a/test/changeset/changeset_test.exs b/test/changeset/changeset_test.exs index f3074a646..2022355f1 100644 --- a/test/changeset/changeset_test.exs +++ b/test/changeset/changeset_test.exs @@ -332,6 +332,43 @@ defmodule Ash.Test.Changeset.ChangesetTest do end end + defmodule ResourceWithMultipleConstraintChanges do + @moduledoc false + use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets + + ets do + private?(true) + end + + actions do + default_accept :* + defaults [:read, :destroy, create: :*, update: :*] + end + + attributes do + uuid_primary_key :id + + attribute :publication_status, :atom do + public? true + allow_nil? false + default :draft + end + + attribute :published_at, :utc_datetime_usec, public?: true + end + + changes do + change set_attribute(:publication_status, :published) do + where [ + attribute_equals(:published_at, nil), + compare(:published_at, + less_than_or_equal_to: &DateTime.utc_now/0 + ) + ] + end + end + end + describe "new" do test "it wraps a new resource in a `create` changeset" do assert %Ash.Changeset{ @@ -1202,4 +1239,18 @@ defmodule Ash.Test.Changeset.ChangesetTest do refute Ash.Changeset.present?(changeset, :author_id) end end + + test "some test" do + resource = + ResourceWithMultipleConstraintChanges + |> Ash.Changeset.for_create(:create, %{}) + |> Ash.create!() + + updated_resource = + resource + |> Ash.Changeset.for_update(:update, %{published_at: ~U[2024-01-01T09:22:22Z]}) + |> Ash.update!() + + assert :published == updated_resource.publication_status + end end