Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule Diffo.Provider.Calculations.FieldViaAliasedRelationship do
@moduledoc false
use Ash.Resource.Calculation

@impl true
def load(_query, _opts, _context), do: []

@impl true
def calculate(records, opts, _context) do
alias_name = opts[:alias]
field = opts[:field]

Enum.map(records, fn record ->
record.id
|> traverse(alias_name)
|> Enum.flat_map(fn target_id ->
Diffo.Provider.Instance
|> Ash.Query.filter_input(id: target_id)
|> Ash.read!(domain: Diffo.Provider)
|> Enum.map(&Map.get(&1, field))
end)
end)
end

defp traverse(id, nil) do
Diffo.Provider.DefinedSimpleRelationship
|> Ash.Query.filter_input(source_id: id)
|> Ash.read!(domain: Diffo.Provider)
|> Enum.map(& &1.target_id)
end

defp traverse(id, alias_name) do
Diffo.Provider.DefinedSimpleRelationship
|> Ash.Query.filter_input(source_id: id, alias: alias_name)
|> Ash.read!(domain: Diffo.Provider)
|> Enum.map(& &1.target_id)
end
end
101 changes: 101 additions & 0 deletions test/provider/extension/field_via_aliased_relationship_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule Diffo.Provider.Extension.FieldViaAliasedRelationshipTest do
@moduledoc false
use ExUnit.Case, async: true
@moduletag :domain_extended

alias Diffo.Test.Parties
alias Diffo.Test.Servo

setup do
AshNeo4j.Sandbox.checkout()
on_exit(&AshNeo4j.Sandbox.rollback/0)
end

describe "FieldViaAliasedRelationship — aliased" do
test "returns field from target instance reached via alias" do
{:ok, shelf} = Parties.build_shelf_with_installer()
{:ok, card} = Servo.build_card(%{name: "target-card"})

Diffo.Provider.create_defined_simple_relationship!(%{
type: :assignedTo,
alias: :link,
source_id: shelf.id,
target_id: card.id
})

shelf = Ash.load!(shelf, [:linked_target_name], domain: Servo)

assert shelf.linked_target_name == ["target-card"]
end

test "returns empty list when no matching relationship exists" do
{:ok, shelf} = Parties.build_shelf_with_installer()

shelf = Ash.load!(shelf, [:linked_target_name], domain: Servo)

assert shelf.linked_target_name == []
end

test "alias filters to only the matching target" do
{:ok, shelf} = Parties.build_shelf_with_installer()
{:ok, card_a} = Servo.build_card(%{name: "target-a"})
{:ok, card_b} = Servo.build_card(%{name: "target-b"})

Diffo.Provider.create_defined_simple_relationship!(%{
type: :assignedTo,
alias: :link,
source_id: shelf.id,
target_id: card_a.id
})

Diffo.Provider.create_defined_simple_relationship!(%{
type: :assignedTo,
alias: :other,
source_id: shelf.id,
target_id: card_b.id
})

shelf = Ash.load!(shelf, [:linked_target_name], domain: Servo)

assert shelf.linked_target_name == ["target-a"]
end
end

describe "FieldViaAliasedRelationship — unaliased (all targets)" do
test "returns fields from all related target instances regardless of alias" do
{:ok, shelf} = Parties.build_shelf_with_installer()
{:ok, card_a} = Servo.build_card(%{name: "target-a"})
{:ok, card_b} = Servo.build_card(%{name: "target-b"})

Diffo.Provider.create_defined_simple_relationship!(%{
type: :assignedTo,
alias: :link,
source_id: shelf.id,
target_id: card_a.id
})

Diffo.Provider.create_defined_simple_relationship!(%{
type: :assignedTo,
alias: :other,
source_id: shelf.id,
target_id: card_b.id
})

shelf = Ash.load!(shelf, [:all_linked_names], domain: Servo)

assert Enum.sort(shelf.all_linked_names) == ["target-a", "target-b"]
end

test "returns empty list when no relationships exist" do
{:ok, shelf} = Parties.build_shelf_with_installer()

shelf = Ash.load!(shelf, [:all_linked_names], domain: Servo)

assert shelf.all_linked_names == []
end
end
end
8 changes: 8 additions & 0 deletions test/support/resource/instance/shelf_instance.ex
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ defmodule Diffo.Test.Instance.ShelfInstance do
end
end

calculations do
calculate :linked_target_name, {:array, :string},
{Diffo.Provider.Calculations.FieldViaAliasedRelationship, [alias: :link, field: :name]}

calculate :all_linked_names, {:array, :string},
{Diffo.Provider.Calculations.FieldViaAliasedRelationship, [field: :name]}
end

actions do
create :build do
description "creates a new Shelf resource instance for build"
Expand Down
Loading