diff --git a/test/create_test.exs b/test/create_test.exs index 8a4327a9..0b906ace 100644 --- a/test/create_test.exs +++ b/test/create_test.exs @@ -63,4 +63,66 @@ defmodule AshPostgres.CreateTest do assert Ash.Resource.get_metadata(post, :upsert_skipped) end + + describe "manage_relationship from hooks on create" do + test "before_transaction hook" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create_with_post_from_before_transaction, %{ + title: "test comment" + }) + |> Ash.create!() + + assert comment.post_id != nil + loaded = Ash.load!(comment, :post) + assert loaded.post.title == "created-in-before-transaction" + end + + test "before_action hook" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create_with_post_from_before_action, %{ + title: "test comment" + }) + |> Ash.create!() + + assert comment.post_id != nil + loaded = Ash.load!(comment, :post) + assert loaded.post.title == "created-in-before-action" + end + + test "before_transaction hook via bulk_create" do + result = + Ash.bulk_create!( + [%{title: "bulk comment"}], + AshPostgres.Test.Comment, + :create_with_post_from_before_transaction, + return_records?: true, + return_errors?: true + ) + + assert result.status == :success + [comment] = result.records + assert comment.post_id != nil + loaded = Ash.load!(comment, :post) + assert loaded.post.title == "created-in-before-transaction" + end + + test "before_action hook via bulk_create" do + result = + Ash.bulk_create!( + [%{title: "bulk comment"}], + AshPostgres.Test.Comment, + :create_with_post_from_before_action, + return_records?: true, + return_errors?: true + ) + + assert result.status == :success + [comment] = result.records + assert comment.post_id != nil + loaded = Ash.load!(comment, :post) + assert loaded.post.title == "created-in-before-action" + end + end end diff --git a/test/support/resources/comment.ex b/test/support/resources/comment.ex index 9c243c2b..1844ba1d 100644 --- a/test/support/resources/comment.ex +++ b/test/support/resources/comment.ex @@ -41,6 +41,68 @@ defmodule AshPostgres.Test.Comment do read :with_modify_query do modify_query({AshPostgres.Test.Comment.ModifyQuery, :modify, []}) end + + # Create actions with manage_relationship from hooks + create :create_with_post_from_before_transaction do + argument(:rating, :map) + + change(fn changeset, _context -> + Ash.Changeset.before_transaction(changeset, fn changeset -> + Ash.Changeset.manage_relationship( + changeset, + :post, + %{title: "created-in-before-transaction"}, + on_no_match: :create + ) + end) + end) + end + + create :create_with_post_from_before_action do + argument(:rating, :map) + + change(fn changeset, _context -> + Ash.Changeset.before_action(changeset, fn changeset -> + Ash.Changeset.manage_relationship( + changeset, + :post, + %{title: "created-in-before-action"}, + on_no_match: :create + ) + end) + end) + end + + # Update actions with manage_relationship from hooks (non-atomic) + update :update_with_post_from_before_transaction do + require_atomic?(false) + + change(fn changeset, _context -> + Ash.Changeset.before_transaction(changeset, fn changeset -> + Ash.Changeset.manage_relationship( + changeset, + :post, + %{title: "created-in-before-transaction"}, + on_no_match: :create + ) + end) + end) + end + + update :update_with_post_from_before_action do + require_atomic?(false) + + change(fn changeset, _context -> + Ash.Changeset.before_action(changeset, fn changeset -> + Ash.Changeset.manage_relationship( + changeset, + :post, + %{title: "created-in-before-action"}, + on_no_match: :create + ) + end) + end) + end end attributes do diff --git a/test/update_test.exs b/test/update_test.exs index 18466c05..4a6a6253 100644 --- a/test/update_test.exs +++ b/test/update_test.exs @@ -257,4 +257,90 @@ defmodule AshPostgres.UpdateTest do assert [%Post{}] = author.posts end + + describe "manage_relationship from hooks on update" do + test "before_transaction hook" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create, %{title: "test comment"}) + |> Ash.create!() + + assert comment.post_id == nil + + updated = + comment + |> Ash.Changeset.for_update(:update_with_post_from_before_transaction, %{}) + |> Ash.update!() + + assert updated.post_id != nil + loaded = Ash.load!(updated, :post) + assert loaded.post.title == "created-in-before-transaction" + end + + test "before_action hook" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create, %{title: "test comment"}) + |> Ash.create!() + + assert comment.post_id == nil + + updated = + comment + |> Ash.Changeset.for_update(:update_with_post_from_before_action, %{}) + |> Ash.update!() + + assert updated.post_id != nil + loaded = Ash.load!(updated, :post) + assert loaded.post.title == "created-in-before-action" + end + + test "before_transaction hook via bulk_update" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create, %{title: "test comment"}) + |> Ash.create!() + + assert comment.post_id == nil + + result = + AshPostgres.Test.Comment + |> Ash.Query.filter(id == ^comment.id) + |> Ash.bulk_update!(:update_with_post_from_before_transaction, %{}, + strategy: :stream, + return_records?: true, + return_errors?: true + ) + + assert result.status == :success + [updated] = result.records + assert updated.post_id != nil + loaded = Ash.load!(updated, :post) + assert loaded.post.title == "created-in-before-transaction" + end + + test "before_action hook via bulk_update" do + comment = + AshPostgres.Test.Comment + |> Ash.Changeset.for_create(:create, %{title: "test comment"}) + |> Ash.create!() + + assert comment.post_id == nil + + result = + AshPostgres.Test.Comment + |> Ash.Query.filter(id == ^comment.id) + |> Ash.bulk_update!(:update_with_post_from_before_action, %{}, + strategy: :stream, + return_records?: true, + return_errors?: true + ) + + assert result.status == :success + [updated] = result.records + assert updated.post_id != nil + loaded = Ash.load!(updated, :post) + assert loaded.post.title == "created-in-before-action" + end + end end