defmodule Ash.Test.Resource.Validation.MatchTest do @moduledoc false use ExUnit.Case, async: true require Ash.Expr defmodule Post do @moduledoc false use Ash.Resource, domain: Ash.Test.Domain, data_layer: Ash.DataLayer.Ets ets do private?(true) end actions do default_accept :* defaults [:read, :destroy, :create] update :atomic_update do argument :alternative_language, :string validate match(:language_code, ~r/^[a-z]{2,3}$/) do always_atomic? true end validate match(:alternative_language, ~r/^[a-z]{2,3}$/) do always_atomic? true end end end attributes do uuid_primary_key :id attribute :language_code, :string do public?(true) end attribute :other, :string do public?(true) end end end describe "is atomic" do setup do post = Post |> Ash.Changeset.for_create(:create, %{language_code: "en"}) |> Ash.create!() {:ok, post: post} end test "on arguments and fixed changes", %{post: post} do post |> Ash.Changeset.for_update(:atomic_update, %{ language_code: "it", alternative_language: "it" }) |> Ash.update!() end test "if arguments are omitted", %{post: post} do post |> Ash.Changeset.for_update(:atomic_update, %{language_code: "it"}) |> Ash.update!() end test "on atomic_update with fixed value", %{post: post} do post |> Ash.Changeset.new() |> Ash.Changeset.atomic_update(:language_code, "it") |> Ash.Changeset.for_update(:atomic_update, %{}) |> Ash.update!() end end describe "is not atomic" do setup do post = Post |> Ash.Changeset.for_create(:create, %{language_code: "en"}) |> Ash.create!() {:ok, post: post} end test "if the attribute is not changing", %{post: post} do assert {:error, %Ash.Error.Invalid{errors: [error]}} = post |> Ash.Changeset.for_update(:atomic_update, %{other: "foo"}) |> Ash.update() assert error.message =~ "not changing" end test "if the attribute is updated with atomic_update", %{post: post} do assert {:error, %Ash.Error.Invalid{errors: [error]}} = post |> Ash.Changeset.new() |> Ash.Changeset.atomic_update( :language_code, Ash.Expr.expr(language_code <> "new") ) |> Ash.Changeset.for_update(:atomic_update, %{}) |> Ash.update() assert error.message =~ "can't match on an atomic expression" end end end