2023-11-14 07:58:09 +13:00
|
|
|
defmodule Ash.Test.Actions.HasManyTest do
|
|
|
|
@moduledoc false
|
|
|
|
use ExUnit.Case, async: true
|
|
|
|
|
|
|
|
require Ash.Query
|
|
|
|
|
|
|
|
defmodule Comment do
|
|
|
|
use Ash.Resource,
|
2024-03-28 09:06:40 +13:00
|
|
|
domain: Ash.Test.Actions.HasManyTest.OtherDomain,
|
2023-11-14 07:58:09 +13:00
|
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
actions do
|
2024-03-28 09:06:40 +13:00
|
|
|
default_accept :*
|
|
|
|
defaults [:read, :destroy, create: :*, update: :*]
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private? true
|
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
|
|
|
uuid_primary_key :id
|
|
|
|
|
2024-03-28 09:06:40 +13:00
|
|
|
attribute :post_id, :uuid do
|
|
|
|
public?(true)
|
|
|
|
end
|
2023-11-14 07:58:09 +13:00
|
|
|
|
2024-03-28 09:06:40 +13:00
|
|
|
attribute :content, :string do
|
|
|
|
public?(true)
|
|
|
|
end
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-28 09:06:40 +13:00
|
|
|
defmodule OtherDomain do
|
|
|
|
use Ash.Domain
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
resources do
|
2024-03-28 09:06:40 +13:00
|
|
|
resource Comment
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-07-02 09:21:01 +12:00
|
|
|
defmodule MeowCommentRelationship do
|
|
|
|
use Ash.Resource.ManualRelationship
|
|
|
|
|
|
|
|
require Ash.Query
|
|
|
|
|
|
|
|
def load(records, _opts, %{query: query, actor: actor, authorize?: authorize?}) do
|
|
|
|
post_ids = Enum.map(records, & &1.id)
|
|
|
|
|
|
|
|
{:ok,
|
|
|
|
query
|
|
|
|
|> Ash.Query.filter(post_id in ^post_ids)
|
|
|
|
|> Ash.Query.filter(content == "meow")
|
|
|
|
|> Ash.read!(actor: actor, authorize?: authorize?)
|
|
|
|
|> Enum.group_by(& &1.post_id)}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-14 07:58:09 +13:00
|
|
|
defmodule Post do
|
|
|
|
@moduledoc false
|
|
|
|
use Ash.Resource,
|
2024-03-28 09:06:40 +13:00
|
|
|
domain: Ash.Test.Actions.HasManyTest.Domain,
|
2023-11-14 07:58:09 +13:00
|
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private?(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
actions do
|
2024-03-28 09:06:40 +13:00
|
|
|
default_accept :*
|
|
|
|
defaults [:read, :destroy, create: :*, update: :*]
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
update :add_comment do
|
2024-04-26 14:18:38 +12:00
|
|
|
require_atomic? false
|
2023-11-14 07:58:09 +13:00
|
|
|
accept []
|
|
|
|
argument(:comment, :map, allow_nil?: false)
|
|
|
|
change manage_relationship(:comment, :comments, on_no_match: :create, on_match: :update)
|
|
|
|
end
|
|
|
|
|
|
|
|
update :delete_comment do
|
2024-04-26 14:18:38 +12:00
|
|
|
require_atomic? false
|
2023-11-14 07:58:09 +13:00
|
|
|
accept []
|
|
|
|
argument(:comment, :map, allow_nil?: false)
|
|
|
|
change manage_relationship(:comment, :comments, on_no_match: :error, on_match: :destroy)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
2024-07-02 09:21:01 +12:00
|
|
|
uuid_primary_key :id, type: :uuid_v7
|
2024-03-28 09:06:40 +13:00
|
|
|
|
|
|
|
attribute :title, :string do
|
|
|
|
public?(true)
|
|
|
|
end
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
relationships do
|
|
|
|
has_many :comments, Comment do
|
|
|
|
destination_attribute :post_id
|
2024-03-28 09:06:40 +13:00
|
|
|
public?(true)
|
|
|
|
domain(OtherDomain)
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
2024-07-02 09:21:01 +12:00
|
|
|
|
|
|
|
has_many :meow_comments, Comment do
|
|
|
|
manual MeowCommentRelationship
|
|
|
|
end
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-28 09:06:40 +13:00
|
|
|
defmodule Domain do
|
2023-11-14 07:58:09 +13:00
|
|
|
@moduledoc false
|
2024-03-28 09:06:40 +13:00
|
|
|
use Ash.Domain
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
resources do
|
2024-03-28 09:06:40 +13:00
|
|
|
resource Post
|
|
|
|
resource Comment
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "destroyed items are removed from the relationship" do
|
|
|
|
post =
|
|
|
|
Post
|
|
|
|
|> Ash.Changeset.for_create(:create, %{
|
|
|
|
title: "buz"
|
|
|
|
})
|
2024-03-28 09:06:40 +13:00
|
|
|
|> Ash.create!()
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:add_comment, %{
|
|
|
|
comment: %{content: "foo"}
|
|
|
|
})
|
2024-03-28 09:06:40 +13:00
|
|
|
|> Ash.update!()
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
assert length(post.comments) == 1
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:add_comment, %{
|
|
|
|
comment: %{content: "bar"}
|
|
|
|
})
|
2024-03-28 09:06:40 +13:00
|
|
|
|> Ash.update!()
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
assert length(post.comments) == 2
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:delete_comment, %{
|
|
|
|
comment: Enum.at(post.comments, 0)
|
|
|
|
})
|
2024-03-28 09:06:40 +13:00
|
|
|
|> Ash.update!()
|
2023-11-14 07:58:09 +13:00
|
|
|
|
|
|
|
assert length(post.comments) == 1
|
|
|
|
end
|
2024-07-02 09:21:01 +12:00
|
|
|
|
|
|
|
test "manual relationships work as expected" do
|
|
|
|
post =
|
|
|
|
Post
|
|
|
|
|> Ash.Changeset.for_create(:create, %{
|
|
|
|
title: "buz"
|
|
|
|
})
|
|
|
|
|> Ash.create!()
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:add_comment, %{
|
|
|
|
comment: %{content: "meow"}
|
|
|
|
})
|
|
|
|
|> Ash.update!()
|
|
|
|
|> Ash.load!(:meow_comments)
|
|
|
|
|
|
|
|
assert length(post.meow_comments) == 1
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:add_comment, %{
|
|
|
|
comment: %{content: "bar"}
|
|
|
|
})
|
|
|
|
|> Ash.update!()
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:add_comment, %{
|
|
|
|
comment: %{content: "meow"}
|
|
|
|
})
|
|
|
|
|> Ash.update!()
|
|
|
|
|> Ash.load!(:meow_comments)
|
|
|
|
|
|
|
|
assert length(post.meow_comments) == 2
|
|
|
|
|
|
|
|
post =
|
|
|
|
post
|
|
|
|
|> Ash.Changeset.for_update(:delete_comment, %{
|
|
|
|
comment: Enum.at(post.meow_comments, 0)
|
|
|
|
})
|
|
|
|
|> Ash.update!()
|
|
|
|
|> Ash.load!(:meow_comments)
|
|
|
|
|
|
|
|
assert length(post.meow_comments) == 1
|
|
|
|
end
|
2023-11-14 07:58:09 +13:00
|
|
|
end
|