mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-20 07:12:49 +12:00
fix: synthetically cast attributes in read forms
fix: raise explicitly on non-existent action
This commit is contained in:
parent
728df80432
commit
4c013819d0
3 changed files with 77 additions and 3 deletions
|
@ -81,6 +81,8 @@ defmodule AshPhoenix.Form.Auto do
|
|||
end
|
||||
|
||||
def related(resource, action, auto_opts) do
|
||||
passed_in_action = action
|
||||
|
||||
action =
|
||||
if is_atom(action) do
|
||||
Ash.Resource.Info.action(resource, action)
|
||||
|
@ -88,6 +90,10 @@ defmodule AshPhoenix.Form.Auto do
|
|||
action
|
||||
end
|
||||
|
||||
if is_nil(action) && is_atom(passed_in_action) do
|
||||
raise "No such action :#{passed_in_action} for #{inspect(resource)}"
|
||||
end
|
||||
|
||||
action.arguments
|
||||
|> Enum.reject(& &1.private?)
|
||||
|> Enum.filter(&(&1.type in [{:array, :map}, :map, Ash.Type.Map, {:array, Ash.Type.Map}]))
|
||||
|
|
|
@ -639,14 +639,53 @@ defmodule AshPhoenix.Form do
|
|||
Ash.Query.for_read(
|
||||
resource,
|
||||
action,
|
||||
opts[:params] || %{},
|
||||
params || %{},
|
||||
query_opts
|
||||
)
|
||||
|> add_errors_for_unhandled_params(params)
|
||||
}
|
||||
|> set_changed?()
|
||||
|> set_validity()
|
||||
end
|
||||
|
||||
defp add_errors_for_unhandled_params(%{action: nil} = query, _params), do: query
|
||||
|
||||
defp add_errors_for_unhandled_params(query, params) do
|
||||
arguments = Enum.map(query.action.arguments, &to_string(&1.name))
|
||||
|
||||
remaining_params = Map.drop(params, arguments)
|
||||
|
||||
Enum.reduce(remaining_params, query, fn {key, value}, query ->
|
||||
attribute = Ash.Resource.Info.public_attribute(query.resource, key)
|
||||
|
||||
if attribute do
|
||||
case Ash.Changeset.cast_input(attribute.type, value, attribute.constraints, query) do
|
||||
{:ok, casted} ->
|
||||
%{query | params: Map.put(query.params, key, casted)}
|
||||
|
||||
{:error, error} ->
|
||||
messages =
|
||||
if Keyword.keyword?(error) do
|
||||
[error]
|
||||
else
|
||||
List.wrap(error)
|
||||
end
|
||||
|
||||
messages
|
||||
|> Enum.reduce(query, fn message, query ->
|
||||
message
|
||||
|> Ash.Changeset.error_to_exception_opts(attribute)
|
||||
|> Enum.reduce(query, fn opts, query ->
|
||||
Ash.Query.add_error(query, Ash.Error.Changes.InvalidAttribute.exception(opts))
|
||||
end)
|
||||
end)
|
||||
end
|
||||
else
|
||||
query
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@doc "A utility to get the list of attributes the action underlying the form accepts"
|
||||
def attributes(form) do
|
||||
AshPhoenix.Form.Auto.accepted_attributes(form.resource, form.source.action)
|
||||
|
@ -760,6 +799,7 @@ defmodule AshPhoenix.Form do
|
|||
params,
|
||||
source_opts
|
||||
)
|
||||
|> add_errors_for_unhandled_params(params)
|
||||
end
|
||||
|
||||
%{
|
||||
|
@ -2078,8 +2118,26 @@ defmodule AshPhoenix.Form do
|
|||
end
|
||||
|
||||
defp add_form_resource_and_action(opts, config, key, trail) do
|
||||
default =
|
||||
cond do
|
||||
config[:create_action] && (config[:create_resource] || config[:resource]) ->
|
||||
:create
|
||||
|
||||
config[:read_action] && (config[:read_resource] || config[:resource]) ->
|
||||
:read
|
||||
|
||||
config[:update_action] && (config[:update_resource] || config[:resource]) ->
|
||||
:update
|
||||
|
||||
config[:destroy_action] && (config[:destroy_resource] || config[:resource]) ->
|
||||
:destroy
|
||||
|
||||
true ->
|
||||
:create
|
||||
end
|
||||
|
||||
action =
|
||||
case opts[:type] || :create do
|
||||
case opts[:type] || default do
|
||||
:create ->
|
||||
config[:create_action] ||
|
||||
raise AshPhoenix.Form.NoActionConfigured,
|
||||
|
@ -2106,7 +2164,7 @@ defmodule AshPhoenix.Form do
|
|||
end
|
||||
|
||||
resource =
|
||||
case opts[:type] || :create do
|
||||
case opts[:type] || default do
|
||||
:create ->
|
||||
config[:create_resource] || config[:resource] ||
|
||||
raise AshPhoenix.Form.NoResourceConfigured, path: Enum.reverse(trail, [key])
|
||||
|
|
|
@ -23,6 +23,16 @@ defmodule AshPhoenix.FormTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "a read will validate attributes" do
|
||||
form =
|
||||
Post
|
||||
|> Form.for_read(:read)
|
||||
|> Form.validate(%{"text" => [1, 2, 3]})
|
||||
|> form_for("action")
|
||||
|
||||
assert form.errors[:text] == {"is invalid", []}
|
||||
end
|
||||
|
||||
test "validation errors are attached to fields" do
|
||||
form = Form.for_create(PostWithDefault, :create, api: Api)
|
||||
form = AshPhoenix.Form.validate(form, %{"text" => ""}, errors: form.submitted_once?)
|
||||
|
|
Loading…
Reference in a new issue