fix: prefer source_attribute is required, instead of relationship name

we only do this if the source attribute is accepted by the action

fixes #1362
This commit is contained in:
Zach Daniel 2024-08-02 09:40:49 -04:00
parent 4e223cb4e0
commit 54738baad2
2 changed files with 71 additions and 13 deletions

View file

@ -3012,6 +3012,16 @@ defmodule Ash.Changeset do
) )
%{name: name} -> %{name: name} ->
if required_attribute.name in changeset.action.accept do
add_error(
changeset,
Required.exception(
resource: changeset.resource,
field: required_attribute.name,
type: :attribute
)
)
else
add_error( add_error(
changeset, changeset,
Required.exception( Required.exception(
@ -3022,6 +3032,7 @@ defmodule Ash.Changeset do
) )
end end
end end
end
defp is_belongs_to_rel_being_managed?(attribute, changeset, only_if_relating?) do defp is_belongs_to_rel_being_managed?(attribute, changeset, only_if_relating?) do
Enum.any?(changeset.relationships, fn Enum.any?(changeset.relationships, fn

View file

@ -66,8 +66,8 @@ defmodule Ash.Test.Actions.CreateTest do
end end
actions do actions do
default_accept :* default_accept [:bio, :date]
defaults [:read, :destroy, create: :*, update: :*] defaults [:read, :destroy, :create, :update]
end end
attributes do attributes do
@ -134,8 +134,8 @@ defmodule Ash.Test.Actions.CreateTest do
end end
actions do actions do
default_accept :* default_accept [:bio, :name]
defaults [:read, :destroy, create: :*, update: :*] defaults [:read, :destroy, :create, :update]
create :only_allow_name do create :only_allow_name do
accept([:name]) accept([:name])
@ -256,8 +256,21 @@ defmodule Ash.Test.Actions.CreateTest do
end end
actions do actions do
default_accept :* default_accept [
defaults [:read, :destroy, create: :*, update: :*] :list_attribute_with_constraints,
:required_boolean_with_default,
:required_with_default,
:binary,
:date,
:list_attribute,
:tag3,
:tag2,
:tag,
:contents,
:title
]
defaults [:read, :destroy, :create, :update]
create :create_with_required do create :create_with_required do
require_attributes [:tag] require_attributes [:tag]
@ -331,6 +344,31 @@ defmodule Ash.Test.Actions.CreateTest do
end end
end end
defmodule PostRequiringAuthorId do
@moduledoc false
use Ash.Resource, data_layer: Ash.DataLayer.Ets, domain: Ash.Test.Domain
ets do
private?(true)
end
actions do
default_accept [:author_id, :title]
defaults [:read, :destroy, create: :*, update: :*]
end
attributes do
uuid_primary_key :id
attribute(:title, :string, allow_nil?: false, public?: true)
timestamps()
end
relationships do
belongs_to(:author, Author, public?: true, allow_nil?: false)
end
end
defmodule GeneratedPkey do defmodule GeneratedPkey do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
@ -1230,6 +1268,15 @@ defmodule Ash.Test.Actions.CreateTest do
|> Ash.create!() |> Ash.create!()
end end
test "when creating with belongs_to relationship specified as an attribute, the attribute is in the error" do
assert {:error,
%Ash.Error.Invalid{errors: [%Ash.Error.Changes.Required{field: :author_id}]}} =
PostRequiringAuthorId
|> Ash.Changeset.new()
|> Ash.Changeset.for_create(:create, %{title: "foobar"})
|> Ash.create()
end
test "it sets the relationship on the destination record accordingly" do test "it sets the relationship on the destination record accordingly" do
author = author =
Author Author