improvement: enrich but also simplify changed? behavior

This commit is contained in:
Zach Daniel 2021-11-06 14:12:53 -04:00
parent 9818809907
commit a8b6a7d1e5
2 changed files with 130 additions and 12 deletions

View file

@ -149,6 +149,8 @@ defmodule AshPhoenix.Form do
:id,
:transform_errors,
:original_data,
any_removed?: false,
added?: false,
changed?: false,
touched_forms: MapSet.new(),
data_updates: [],
@ -1471,20 +1473,17 @@ defmodule AshPhoenix.Form do
end
defp changed?(form) do
is_changed?(form) ||
form.any_removed? ||
is_changed?(form) ||
Enum.any?(form.forms, fn {_key, forms} ->
forms
|> List.wrap()
|> Enum.any?(& &1.changed?)
|> Enum.any?(&(&1.changed? || &1.added?))
end)
end
defp is_changed?(form) do
if form.type == :create do
true
else
attributes_changed?(form) || arguments_changed?(form)
end
attributes_changed?(form) || arguments_changed?(form)
end
defp attributes_changed?(%{source: %Ash.Query{}}), do: false
@ -1644,6 +1643,15 @@ defmodule AshPhoenix.Form do
path: Enum.reverse(trail)
end
found_form = form.forms[key]
any_removed? =
if found_form && !found_form.added? do
true
else
false
end
new_config =
form.form_keys
|> Keyword.update!(key, fn config ->
@ -1659,6 +1667,7 @@ defmodule AshPhoenix.Form do
%{
form
| forms: new_forms,
any_removed?: form.any_removed? || any_removed?,
form_keys: new_config,
opts: Keyword.put(form.opts, :forms, new_config)
}
@ -1674,11 +1683,21 @@ defmodule AshPhoenix.Form do
new_config = do_remove_data(form, key, i)
found_form = Enum.at(form.forms[key] || [], i)
any_removed? =
if found_form && !found_form.added? do
true
else
false
end
new_forms =
form.forms
|> Map.put_new(key, [])
|> Map.update!(key, fn forms ->
forms
|> Kernel.||([])
|> List.delete_at(i)
|> Enum.with_index()
|> Enum.map(fn {nested_form, i} ->
@ -1689,6 +1708,7 @@ defmodule AshPhoenix.Form do
%{
form
| forms: new_forms,
any_removed?: form.any_removed? || any_removed?,
form_keys: new_config,
opts: Keyword.put(form.opts, :forms, new_config)
}
@ -1803,15 +1823,15 @@ defmodule AshPhoenix.Form do
case config[:type] || :single do
:single ->
%{new_form | name: form.name <> "[#{key}]", id: form.id <> "_#{key}"}
%{new_form | name: form.name <> "[#{key}]", id: form.id <> "_#{key}", added?: true}
:list ->
forms = List.wrap(forms)
if opts[:prepend] do
[new_form | forms]
[%{new_form | added?: true} | forms]
else
forms ++ [new_form]
forms ++ [%{new_form | added?: true}]
end
|> Enum.with_index()
|> Enum.map(fn {nested_form, index} ->

View file

@ -24,13 +24,13 @@ defmodule AshPhoenix.FormTest do
end
describe "the .changed? field is updated as data changes" do
test "it is true for a create form with no changes" do
test "it is false for a create form with no changes" do
form =
Post
|> Form.for_create(:create)
|> Form.validate(%{})
assert form.changed?
refute form.changed?
end
test "it is false by default for update forms" do
@ -80,6 +80,104 @@ defmodule AshPhoenix.FormTest do
refute form.changed?
end
test "adding a form causes changed? to be true on the root form, but not the nested form" do
form =
Comment
|> Form.for_create(:create,
api: Api,
forms: [
post: [
resource: Post,
create_action: :create
]
]
)
|> Form.add_form(:post, params: %{})
assert form.changed?
refute form.forms[:post].changed?
end
test "removing a form that was there prior marks the form as changed" do
post =
Post
|> Ash.Changeset.new(%{text: "post"})
|> Api.create!()
comment =
Comment
|> Ash.Changeset.new(%{text: "comment"})
|> Ash.Changeset.replace_relationship(:post, post)
|> Api.create!()
# Check the persisted post.comments count after create
post = Post |> Api.get!(post.id) |> Api.load!(:comments)
assert Enum.count(post.comments) == 1
form =
post
|> Form.for_update(:update,
api: Api,
forms: [
comments: [
resource: Comment,
type: :list,
data: [comment],
create_action: :create,
update_action: :update
]
]
)
refute form.changed?
form = Form.remove_form(form, [:comments, 0])
assert form.changed?
end
test "removing a form that was added does not mark the form as changed" do
post =
Post
|> Ash.Changeset.new(%{text: "post"})
|> Api.create!()
comment =
Comment
|> Ash.Changeset.new(%{text: "comment"})
|> Ash.Changeset.replace_relationship(:post, post)
|> Api.create!()
# Check the persisted post.comments count after create
post = Post |> Api.get!(post.id) |> Api.load!(:comments)
assert Enum.count(post.comments) == 1
form =
post
|> Form.for_update(:update,
api: Api,
forms: [
comments: [
resource: Comment,
type: :list,
data: [comment],
create_action: :create,
update_action: :update
]
]
)
refute form.changed?
form = Form.add_form(form, [:comments])
assert form.changed?
form = Form.remove_form(form, [:comments, 1])
refute form.changed?
end
end
describe "errors" do