mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: correct writeable attribute logic
This commit is contained in:
parent
035a857138
commit
6d12eb8546
2 changed files with 74 additions and 10 deletions
|
@ -133,18 +133,30 @@ defmodule Ash.Actions.Create do
|
|||
allowed_keys =
|
||||
resource
|
||||
|> Ash.attributes()
|
||||
|> Enum.filter(& &1.writeable?)
|
||||
|> Enum.map(& &1.name)
|
||||
|
||||
attributes_with_defaults =
|
||||
{attributes_with_defaults, unwriteable_attributes} =
|
||||
resource
|
||||
|> Ash.attributes()
|
||||
|> Enum.filter(&(not is_nil(&1.default)))
|
||||
|> Enum.reduce(attributes, fn attr, attributes ->
|
||||
if has_attr?(attributes, attr.name) do
|
||||
attributes
|
||||
else
|
||||
Map.put(attributes, attr.name, default(attr))
|
||||
|> Enum.reduce({%{}, []}, fn attribute, {new_attributes, unwriteable_attributes} ->
|
||||
cond do
|
||||
!attribute.writeable? && is_nil(attribute.default) ->
|
||||
{new_attributes, unwriteable_attributes}
|
||||
|
||||
!attribute.writeable? ->
|
||||
{new_attributes, [attribute | unwriteable_attributes]}
|
||||
|
||||
is_nil(attribute.default) ->
|
||||
case fetch_attr(attributes, attribute.name) do
|
||||
{:ok, value} ->
|
||||
{Map.put(new_attributes, attribute.name, value), unwriteable_attributes}
|
||||
|
||||
:error ->
|
||||
{new_attributes, unwriteable_attributes}
|
||||
end
|
||||
|
||||
true ->
|
||||
{Map.put(attributes, attribute.name, default(attribute)), unwriteable_attributes}
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -155,6 +167,13 @@ defmodule Ash.Actions.Create do
|
|||
|> Map.put(:action, :create)
|
||||
|> Map.put(:__ash_relationships__, %{})
|
||||
|
||||
changeset =
|
||||
Enum.reduce(
|
||||
unwriteable_attributes,
|
||||
changeset,
|
||||
&Ecto.Changeset.add_error(&2, &1, "attribute is not writeable")
|
||||
)
|
||||
|
||||
resource
|
||||
|> Ash.attributes()
|
||||
|> Enum.reject(&Map.get(&1, :allow_nil?))
|
||||
|
@ -172,7 +191,13 @@ defmodule Ash.Actions.Create do
|
|||
defp default(%{default: {mod, func}}), do: apply(mod, func, [])
|
||||
defp default(%{default: function}), do: function.()
|
||||
|
||||
defp has_attr?(map, name) do
|
||||
Map.has_key?(map, name) || Map.has_key?(map, to_string(name))
|
||||
defp fetch_attr(map, name) do
|
||||
case Map.fetch(map, name) do
|
||||
{:ok, value} ->
|
||||
value
|
||||
|
||||
:error ->
|
||||
Map.fetch(map, to_string(name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -133,11 +133,40 @@ defmodule Ash.Actions.Update do
|
|||
|> Enum.filter(& &1.writeable?)
|
||||
|> Enum.map(& &1.name)
|
||||
|
||||
{attributes, unwriteable_attributes} =
|
||||
resource
|
||||
|> Ash.attributes()
|
||||
|> Enum.reduce({%{}, []}, fn attribute, {new_attributes, unwriteable_attributes} ->
|
||||
cond do
|
||||
!attribute.writeable? && is_nil(attribute.default) ->
|
||||
{new_attributes, unwriteable_attributes}
|
||||
|
||||
!attribute.writeable? ->
|
||||
{new_attributes, [attribute | unwriteable_attributes]}
|
||||
|
||||
true ->
|
||||
case fetch_attr(attributes, attribute.name) do
|
||||
{:ok, value} ->
|
||||
{Map.put(new_attributes, attribute.name, value), unwriteable_attributes}
|
||||
|
||||
:error ->
|
||||
{new_attributes, unwriteable_attributes}
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
changeset =
|
||||
record
|
||||
|> Ecto.Changeset.cast(attributes, allowed_keys)
|
||||
|> Map.put(:action, :update)
|
||||
|
||||
changeset =
|
||||
Enum.reduce(
|
||||
unwriteable_attributes,
|
||||
changeset,
|
||||
&Ecto.Changeset.add_error(&2, &1, "attribute is not writeable")
|
||||
)
|
||||
|
||||
resource
|
||||
|> Ash.attributes()
|
||||
|> Enum.reject(&Map.get(&1, :allow_nil?))
|
||||
|
@ -151,4 +180,14 @@ defmodule Ash.Actions.Update do
|
|||
end
|
||||
end)
|
||||
end
|
||||
|
||||
defp fetch_attr(map, name) do
|
||||
case Map.fetch(map, name) do
|
||||
{:ok, value} ->
|
||||
value
|
||||
|
||||
:error ->
|
||||
Map.fetch(map, to_string(name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue