From 72a29651073634c8d1b14756816603846e0b73a0 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Sat, 13 Aug 2022 15:10:47 -0400 Subject: [PATCH] fix: properly parse string paths in `FilterForm` improvement: add `update_predicate/3` --- lib/ash_phoenix/filter_form/filter_form.ex | 46 ++++++++++++++++++---- test/filter_form_test.exs | 42 ++++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) diff --git a/lib/ash_phoenix/filter_form/filter_form.ex b/lib/ash_phoenix/filter_form/filter_form.ex index 19bdcfe..fcb30d8 100644 --- a/lib/ash_phoenix/filter_form/filter_form.ex +++ b/lib/ash_phoenix/filter_form/filter_form.ex @@ -379,7 +379,7 @@ defmodule AshPhoenix.FilterForm do path -> path - |> String.split() + |> String.split(".") |> Enum.map(&to_existing_atom/1) end end @@ -507,6 +507,10 @@ defmodule AshPhoenix.FilterForm do type: :boolean, default: false, doc: "If set to `true`, the function returns `{form, predicate_id}`" + ], + path: [ + type: {:or, [:string, {:list, {:or, [:string, :atom]}}]}, + doc: "The relationship path to apply the predicate to" ] ] @@ -522,14 +526,23 @@ defmodule AshPhoenix.FilterForm do predicate_id = Ash.UUID.generate() + predicate_params = %{ + "id" => predicate_id, + "field" => field, + "value" => value, + "operator" => operator_or_function + } + + predicate_params = + if opts[:path] do + Map.put(predicate_params, "path", opts[:path]) + else + predicate_params + end + predicate = new_predicate( - %{ - "id" => predicate_id, - "field" => field, - "value" => value, - "operator" => operator_or_function - }, + predicate_params, form ) @@ -584,6 +597,25 @@ defmodule AshPhoenix.FilterForm do |> set_validity() end + @doc "Update the predicate with the given id" + def update_predicate(form, id, func) do + %{ + form + | components: + Enum.map(form.components, fn + %__MODULE__{} = nested_form -> + update_predicate(nested_form, id, func) + + %Predicate{id: ^id} = pred -> + func.(pred) + + predicate -> + [predicate] + end) + } + |> set_validity() + end + defp predicate_errors(predicate, resource) do case Ash.Resource.Info.related(resource, predicate.path) do nil -> diff --git a/test/filter_form_test.exs b/test/filter_form_test.exs index 3b12902..57b9ca2 100644 --- a/test/filter_form_test.exs +++ b/test/filter_form_test.exs @@ -162,6 +162,48 @@ defmodule AshPhoenix.FilterFormTest do contains(comments.text, "new") ) end + + test "predicates can be added with paths" do + form = FilterForm.new(Post) + + form = + FilterForm.add_predicate( + form, + :text, + :contains, + "new", + path: "comments" + ) + + assert Ash.Query.equivalent_to?( + FilterForm.filter!(Post, form), + contains(comments.text, "new") + ) + end + + test "predicates can be updated" do + form = FilterForm.new(Post) + + {form, predicate_id} = + FilterForm.add_predicate( + form, + :text, + :contains, + "new", + path: "comments", + return_id?: true + ) + + form = + FilterForm.update_predicate(form, predicate_id, fn predicate -> + %{predicate | path: []} + end) + + assert Ash.Query.equivalent_to?( + FilterForm.filter!(Post, form), + contains(text, "new") + ) + end end describe "form_data implementation" do