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,17 +235,24 @@ defmodule AshGraphql.Dataloader do
cardinality = relationship.cardinality cardinality = relationship.cardinality
query = loads =
query if Map.has_key?(relationship, :manual) && relationship.manual do
|> Ash.Query.new() field
|> Ash.Query.set_tenant(tenant) else
|> Ash.Query.for_read( query =
relationship.read_action || query
Ash.Resource.Info.primary_action!(relationship.destination, :read).name, |> Ash.Query.new()
opts[:args] |> Ash.Query.set_tenant(tenant)
) |> Ash.Query.for_read(
relationship.read_action ||
Ash.Resource.Info.primary_action!(relationship.destination, :read).name,
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