fix: properly parse string paths in FilterForm

improvement: add `update_predicate/3`
This commit is contained in:
Zach Daniel 2022-08-13 15:10:47 -04:00
parent c7278d0f04
commit 72a2965107
2 changed files with 81 additions and 7 deletions

View file

@ -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 ->

View file

@ -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