From 08026b55004fde73d8b1a0c8b5de4d8c1dc36ece Mon Sep 17 00:00:00 2001 From: Vacarsu Date: Thu, 21 Sep 2023 23:08:18 -0700 Subject: [PATCH 1/3] find should always return a full primitive --- lib/scenic/graph.ex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/scenic/graph.ex b/lib/scenic/graph.ex index b773fb3c..d3fb2539 100644 --- a/lib/scenic/graph.ex +++ b/lib/scenic/graph.ex @@ -585,10 +585,9 @@ defmodule Scenic.Graph do @spec find(graph :: t(), (any -> as_boolean(term()))) :: list(Primitive.t()) def find(graph, finder) - # pass in an atom based id, and it will transform all mapped uids - def find(%__MODULE__{} = graph, finder) when is_function(finder, 1) do + def find(%__MODULE__{} = graph, finder) do reduce(graph, [], fn p, acc -> - Map.get(p, :id) + p |> finder.() |> case do true -> [p | acc] From ea15f17a49fc9890b7022f3820fe3dbb3d58d0e7 Mon Sep 17 00:00:00 2001 From: Vacarsu Date: Fri, 22 Sep 2023 15:00:22 -0700 Subject: [PATCH 2/3] fix tests add find_by_id method --- lib/scenic/graph.ex | 16 +++++++++++++--- test/scenic/graph_test.exs | 24 +++++++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/scenic/graph.ex b/lib/scenic/graph.ex index d3fb2539..f5a743c4 100644 --- a/lib/scenic/graph.ex +++ b/lib/scenic/graph.ex @@ -583,8 +583,6 @@ defmodule Scenic.Graph do """ @spec find(graph :: t(), (any -> as_boolean(term()))) :: list(Primitive.t()) - def find(graph, finder) - def find(%__MODULE__{} = graph, finder) do reduce(graph, [], fn p, acc -> p @@ -597,6 +595,18 @@ defmodule Scenic.Graph do |> Enum.reverse() end + def find_by_id(%__MODULE__{} = graph, finder) do + reduce(graph, [], fn p, acc -> + Map.get(p, :id) + |> finder.() + |> case do + true -> [p | acc] + false -> acc + end + end) + |> Enum.reverse() + end + # -------------------------------------------------------- # transform a single primitive by uid # pass in a list of uids to transform @@ -651,7 +661,7 @@ defmodule Scenic.Graph do # pass in a finder function def modify(%__MODULE__{} = graph, finder, action) when is_function(finder, 1) do graph - |> find(finder) + |> find_by_id(finder) |> Enum.map(fn %{id: id} -> id end) |> Enum.uniq() |> Enum.reduce(graph, &modify(&2, &1, action)) diff --git a/test/scenic/graph_test.exs b/test/scenic/graph_test.exs index 5695fe55..185b86ff 100644 --- a/test/scenic/graph_test.exs +++ b/test/scenic/graph_test.exs @@ -267,7 +267,25 @@ defmodule Scenic.GraphTest do end # ============================================================================ - test "find returns the matching items" do + test "find returns the matching items" do + graph = + Graph.build() + |> Text.add_to_graph("text one", id: {:a, :one}) + |> Text.add_to_graph("text two", id: {:a, :two}) + |> Text.add_to_graph("text three", id: {:b, :three}) + + # confirm result + assert Graph.find(graph, &match?({:a, :one}, &1.id)) == [ + Graph.get!(graph, {:a, :one}) + ] + + assert Graph.find(graph, &match?({:b, :three}, &1.id)) == [ + Graph.get!(graph, {:b, :three}) + ] + end + + # ============================================================================ + test "find_by_id returns the matching items" do graph = Graph.build() |> Text.add_to_graph("text one", id: {:a, :one}) @@ -275,12 +293,12 @@ defmodule Scenic.GraphTest do |> Text.add_to_graph("text three", id: {:b, :three}) # confirm result - assert Graph.find(graph, &match?({:a, _}, &1)) == [ + assert Graph.find_by_id(graph, &match?({:a, _}, &1)) == [ Graph.get!(graph, {:a, :one}), Graph.get!(graph, {:a, :two}) ] - assert Graph.find(graph, &match?({:b, _}, &1)) == [ + assert Graph.find_by_id(graph, &match?({:b, _}, &1)) == [ Graph.get!(graph, {:b, :three}) ] end From 5fe4a18be3ac6e9b53519885dd76f346e4a407d5 Mon Sep 17 00:00:00 2001 From: Vacarsu Date: Fri, 22 Sep 2023 15:38:19 -0700 Subject: [PATCH 3/3] add doc for find_by_id/2 --- lib/scenic/graph.ex | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/scenic/graph.ex b/lib/scenic/graph.ex index f5a743c4..907e8af1 100644 --- a/lib/scenic/graph.ex +++ b/lib/scenic/graph.ex @@ -595,6 +595,16 @@ defmodule Scenic.Graph do |> Enum.reverse() end + @doc """ + Find one or more primitives in a graph by id via a filter function. + + Pass in a function that accepts a primitive's id and returns a boolean. + + Returns a list of primitives. + + __Warning:__ This function crawls the entire graph and is thus slower than + accessing items via a fully-specified id. + """ def find_by_id(%__MODULE__{} = graph, finder) do reduce(graph, [], fn p, acc -> Map.get(p, :id)