diff --git a/lib/change_builders/full_diff/helpers.ex b/lib/change_builders/full_diff/helpers.ex index 87c1454..00135e5 100644 --- a/lib/change_builders/full_diff/helpers.ex +++ b/lib/change_builders/full_diff/helpers.ex @@ -98,13 +98,19 @@ defmodule AshPaperTrail.ChangeBuilders.FullDiff.Helpers do def unique_id(%Ash.Union{}, dumped_value), do: dumped_value def unique_id(nil, _dumped_value), do: nil - def unique_id(%{__struct__: resource}, dump_value) do - case Ash.Resource.Info.primary_key(resource) do - [] -> - nil - - primary_keys -> - Enum.reduce(primary_keys, [resource], &(&2 ++ [Map.get(dump_value, &1)])) + def unique_id(%{__struct__: resource} = struct, dump_value) do + if Ash.Resource.Info.resource?(resource) do + case Ash.Resource.Info.primary_key(resource) do + [] -> + nil + + primary_keys -> + Enum.reduce(primary_keys, [resource], &(&2 ++ [Map.get(dump_value, &1)])) + end + else + # For non-Ash structs (Time, Date, DateTime, Decimal, etc.), + # return the struct itself for value-based equality matching + struct end end diff --git a/test/ash_paper_trail/full_diff_test.exs b/test/ash_paper_trail/full_diff_test.exs index f2220fa..bc98cb2 100644 --- a/test/ash_paper_trail/full_diff_test.exs +++ b/test/ash_paper_trail/full_diff_test.exs @@ -932,4 +932,39 @@ defmodule AshPaperTrail.FullDiffTest do } = last_version_changes(ctx.domain, ctx.version_resource) end end + + describe "full_diff with primitive struct types" do + test "create with {:array, :time} attribute", ctx do + ctx.resource.create!(%{ + subject: "Schedule", + times: [~T[08:00:00], ~T[10:00:00], ~T[12:00:00]] + }) + + assert %{ + times: %{ + to: [ + %{added: ~T[08:00:00], index: %{to: 0}}, + %{added: ~T[10:00:00], index: %{to: 1}}, + %{added: ~T[12:00:00], index: %{to: 2}} + ] + } + } = last_version_changes(ctx.domain, ctx.version_resource) + end + + test "update {:array, :time} with reorder, add, and remove", ctx do + post = ctx.resource.create!(%{subject: "Schedule", times: [~T[08:00:00], ~T[10:00:00]]}) + + ctx.resource.update!(post, %{times: [~T[10:00:00], ~T[08:00:00], ~T[14:00:00]]}) + + assert %{ + times: %{ + to: [ + %{unchanged: ~T[10:00:00], index: %{from: 1, to: 0}}, + %{unchanged: ~T[08:00:00], index: %{from: 0, to: 1}}, + %{added: ~T[14:00:00], index: %{to: 2}} + ] + } + } = last_version_changes(ctx.domain, ctx.version_resource) + end + end end diff --git a/test/support/posts/full_diff_post.ex b/test/support/posts/full_diff_post.ex index 3e925cf..e7579b7 100644 --- a/test/support/posts/full_diff_post.ex +++ b/test/support/posts/full_diff_post.ex @@ -104,5 +104,10 @@ defmodule AshPaperTrail.Test.Posts.FullDiffPost do public? true allow_nil? true end + + attribute :times, {:array, :time} do + public? true + allow_nil? true + end end end