improvement: handle pkey-less resources when attaching fields

improvement: set lazy defaults when applying changeset attributes
This commit is contained in:
Zach Daniel 2024-01-21 00:45:23 -05:00
parent a08582ed0f
commit d013818c0a
5 changed files with 47 additions and 14 deletions

View file

@ -103,7 +103,7 @@
{Credo.Check.Readability.ModuleNames, []},
{Credo.Check.Readability.ParenthesesInCondition, false},
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
{Credo.Check.Readability.PredicateFunctionNames, []},
{Credo.Check.Readability.PredicateFunctionNames, false},
{Credo.Check.Readability.PreferImplicitTry, []},
{Credo.Check.Readability.RedundantBlankLines, []},
{Credo.Check.Readability.Semicolons, []},

View file

@ -634,6 +634,7 @@ defmodule Ash.Actions.Read do
result
|> Enum.concat(rest)
|> Enum.sort_by(& &1.__metadata__[:private][:result_index])}
{:error, error} ->
{:error, error}
end
@ -1127,14 +1128,14 @@ defmodule Ash.Actions.Read do
fields_from_calculations =
Enum.map(calculations_in_calculations, & &1.name)
Enum.map(data, fn record ->
case Enum.find(data_with_selected, fn selected_record ->
record.__struct__.primary_key_matches?(record, selected_record)
end) do
nil ->
Ash.Resource.put_metadata(record, :private, %{missing_from_data_layer: true})
match ->
if Enum.empty?(fields_from_calculations) and Enum.empty?(fields_from_aggregates) and
Enum.empty?(fields_from_data) do
data
else
# we have to assume they are all there and in the same order. Not my
# favorite thing, but no way around it in the short term.
if Enum.empty?(Ash.Resource.Info.primary_key(original_query.resource)) do
Enum.zip_with([data, data_with_selected], fn [record, match] ->
record
|> Map.merge(Map.take(match, fields_from_data))
|> Map.update!(
@ -1151,8 +1152,36 @@ defmodule Ash.Actions.Read do
Map.take(match.calculations, fields_from_calculations)
)
)
end)
else
Enum.map(data, fn record ->
case Enum.find(data_with_selected, fn selected_record ->
record.__struct__.primary_key_matches?(record, selected_record)
end) do
nil ->
Ash.Resource.put_metadata(record, :private, %{missing_from_data_layer: true})
match ->
record
|> Map.merge(Map.take(match, fields_from_data))
|> Map.update!(
:aggregates,
&Map.merge(
&1,
Map.take(match.aggregates, fields_from_aggregates)
)
)
|> Map.update!(
:calculations,
&Map.merge(
&1,
Map.take(match.calculations, fields_from_calculations)
)
)
end
end)
end
end)
end
end
defp validate_get([_, _ | _] = results, %{get?: true}, query) do

View file

@ -4307,6 +4307,8 @@ defmodule Ash.Changeset do
def apply_attributes(changeset, opts \\ [])
def apply_attributes(%{valid?: true} = changeset, _opts) do
changeset = set_defaults(changeset, changeset.action_type, true)
{:ok,
Enum.reduce(changeset.attributes, changeset.data, fn {attribute, value}, data ->
Map.put(data, attribute, value)

View file

@ -1296,8 +1296,10 @@ defmodule Ash.Query do
add_error(query, :load, error)
end
else
add_error(query,
Ash.Error.Query.InvalidLoad.exception(load: {resource_calculation.name, args}))
add_error(
query,
Ash.Error.Query.InvalidLoad.exception(load: {resource_calculation.name, args})
)
end
end

View file

@ -1,8 +1,8 @@
%{
"benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"},
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
"credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"},
"credo": {:hex, :credo, "1.7.3", "05bb11eaf2f2b8db370ecaa6a6bda2ec49b2acd5e0418bc106b73b07128c0436", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
"dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"},