improvement: support manual relationships (#66)

This commit is contained in:
Alan Heywood 2023-04-13 15:42:45 +10:00 committed by GitHub
parent e826534bce
commit d89a14175c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 10 deletions

View file

@ -235,6 +235,10 @@ defmodule AshGraphql.Dataloader do
cardinality = relationship.cardinality cardinality = relationship.cardinality
loads =
if Map.has_key?(relationship, :manual) && relationship.manual do
field
else
query = query =
query query
|> Ash.Query.new() |> Ash.Query.new()
@ -245,7 +249,10 @@ defmodule AshGraphql.Dataloader do
opts[:args] opts[:args]
) )
loaded = source.api.load!(records, [{field, query}], api_opts || []) {field, query}
end
loaded = source.api.load!(records, [loads], api_opts || [])
loaded = loaded =
case loaded do case loaded do

View file

@ -613,4 +613,57 @@ defmodule AshGraphql.ReadTest do
variables: %{"id" => post.id} variables: %{"id" => post.id}
) )
end end
test "manual relationships can be read" do
tag =
AshGraphql.Test.Tag
|> Ash.Changeset.for_create(
:create,
name: "My Tag"
)
|> AshGraphql.Test.Api.create!()
post_1 =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> Ash.Changeset.manage_relationship(
:tags,
[tag],
on_no_match: {:create, :create_action},
on_lookup: :relate
)
|> AshGraphql.Test.Api.create!()
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: true)
|> Ash.Changeset.manage_relationship(
:tags,
[tag],
on_no_match: {:create, :create_action},
on_lookup: :relate
)
|> AshGraphql.Test.Api.create!()
doc = """
query ($id: ID!) {
getPost(id: $id) {
text
relatedPosts {
text
}
}
}
"""
assert {:ok,
%{
data: %{
"getPost" => %{
"relatedPosts" => [%{"text" => "bar"}],
"text" => "foo"
}
}
}} ==
Absinthe.run(doc, AshGraphql.Test.Schema, variables: %{"id" => post_1.id})
end
end end

View file

@ -58,6 +58,35 @@ defmodule AfterActionRaiseResourceError do
end end
end end
defmodule RelatedPosts do
@moduledoc false
use Ash.Resource.ManualRelationship
require Ash.Query
def load(posts, _opts, %{api: api}) do
posts = api.load!(posts, :tags)
{
:ok,
posts
|> Enum.map(fn post ->
tag_ids =
post.tags
|> Enum.map(& &1.id)
other_posts =
AshGraphql.Test.Post
|> Ash.Query.filter(tags.id in ^tag_ids)
|> Ash.Query.filter(id != ^post.id)
|> api.read!()
{post.id, other_posts}
end)
|> Map.new()
}
end
end
defmodule AshGraphql.Test.Post do defmodule AshGraphql.Test.Post do
@moduledoc false @moduledoc false
@ -317,5 +346,9 @@ defmodule AshGraphql.Test.Post do
source_attribute_on_join_resource: :post_id, source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :tag_id destination_attribute_on_join_resource: :tag_id
) )
has_many :related_posts, AshGraphql.Test.Post do
manual(RelatedPosts)
end
end end
end end