diff --git a/lib/diffo/provider/components/calculations/field_via_aliased_relationship.ex b/lib/diffo/provider/components/calculations/field_via_aliased_relationship.ex deleted file mode 100644 index 85f32d1..0000000 --- a/lib/diffo/provider/components/calculations/field_via_aliased_relationship.ex +++ /dev/null @@ -1,42 +0,0 @@ -# SPDX-FileCopyrightText: 2025 diffo 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 diff --git a/lib/diffo/provider/components/calculations/field_via_relationship.ex b/lib/diffo/provider/components/calculations/field_via_relationship.ex new file mode 100644 index 0000000..219965b --- /dev/null +++ b/lib/diffo/provider/components/calculations/field_via_relationship.ex @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Provider.Calculations.FieldViaRelationship 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] + type = opts[:type] + field = opts[:field] + + Enum.map(records, fn record -> + filter = [source_id: record.id] + filter = if type, do: Keyword.put(filter, :type, type), else: filter + filter = if alias_name, do: Keyword.put(filter, :alias, alias_name), else: filter + + Diffo.Provider.DefinedSimpleRelationship + |> Ash.Query.filter_input(filter) + |> Ash.read!(domain: Diffo.Provider) + |> Enum.flat_map(fn rel -> + Diffo.Provider.Instance + |> Ash.Query.filter_input(id: rel.target_id) + |> Ash.read!(domain: Diffo.Provider) + |> Enum.map(&Map.get(&1, field)) + end) + end) + end +end diff --git a/test/provider/extension/field_via_aliased_relationship_test.exs b/test/provider/extension/field_via_relationship_test.exs similarity index 76% rename from test/provider/extension/field_via_aliased_relationship_test.exs rename to test/provider/extension/field_via_relationship_test.exs index f58b723..21229de 100644 --- a/test/provider/extension/field_via_aliased_relationship_test.exs +++ b/test/provider/extension/field_via_relationship_test.exs @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: MIT -defmodule Diffo.Provider.Extension.FieldViaAliasedRelationshipTest do +defmodule Diffo.Provider.Extension.FieldViaRelationshipTest do @moduledoc false use ExUnit.Case, async: true @moduletag :domain_extended @@ -15,7 +15,7 @@ defmodule Diffo.Provider.Extension.FieldViaAliasedRelationshipTest do on_exit(&AshNeo4j.Sandbox.rollback/0) end - describe "FieldViaAliasedRelationship — aliased" do + describe "FieldViaRelationship — 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"}) @@ -65,8 +65,8 @@ defmodule Diffo.Provider.Extension.FieldViaAliasedRelationshipTest do end end - describe "FieldViaAliasedRelationship — unaliased (all targets)" do - test "returns fields from all related target instances regardless of alias" do + describe "FieldViaRelationship — type filter" do + test "type filters to only relationships of the matching type" 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"}) @@ -79,23 +79,15 @@ defmodule Diffo.Provider.Extension.FieldViaAliasedRelationshipTest do }) Diffo.Provider.create_defined_simple_relationship!(%{ - type: :assignedTo, - alias: :other, + type: :reliesOn, + alias: :link, 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) + shelf = Ash.load!(shelf, [:assigned_linked_name], domain: Servo) - assert shelf.all_linked_names == [] + assert shelf.assigned_linked_name == ["target-a"] end end end diff --git a/test/support/resource/instance/shelf_instance.ex b/test/support/resource/instance/shelf_instance.ex index e9fc1f4..fb8f2ee 100644 --- a/test/support/resource/instance/shelf_instance.ex +++ b/test/support/resource/instance/shelf_instance.ex @@ -86,10 +86,11 @@ defmodule Diffo.Test.Instance.ShelfInstance do calculations do calculate :linked_target_name, {:array, :string}, - {Diffo.Provider.Calculations.FieldViaAliasedRelationship, [alias: :link, field: :name]} + {Diffo.Provider.Calculations.FieldViaRelationship, [alias: :link, field: :name]} - calculate :all_linked_names, {:array, :string}, - {Diffo.Provider.Calculations.FieldViaAliasedRelationship, [field: :name]} + calculate :assigned_linked_name, {:array, :string}, + {Diffo.Provider.Calculations.FieldViaRelationship, + [type: :assignedTo, alias: :link, field: :name]} end actions do