mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: use values when already loading aggregates
This commit is contained in:
parent
9c5119d8c8
commit
24d802cd4b
4 changed files with 91 additions and 5 deletions
|
@ -1662,10 +1662,10 @@ defmodule Ash.Actions.Load do
|
|||
|
||||
cond do
|
||||
lateral_join?(query, relationship, source_data) ->
|
||||
{:ok, Ash.Query.unset(query, :load)}
|
||||
{:ok, %{query | load: []}}
|
||||
|
||||
Map.get(relationship, :no_attributes?) ->
|
||||
{:ok, query}
|
||||
{:ok, %{query | load: []}}
|
||||
|
||||
true ->
|
||||
query =
|
||||
|
@ -1714,7 +1714,7 @@ defmodule Ash.Actions.Load do
|
|||
new_query =
|
||||
query
|
||||
|> Ash.Query.filter(^[{relationship.destination_attribute, filter_value}])
|
||||
|> Ash.Query.unset(:load)
|
||||
|> Map.put(:load, [])
|
||||
|
||||
{:ok, new_query}
|
||||
end
|
||||
|
|
|
@ -812,6 +812,12 @@ defmodule Ash.Actions.Read do
|
|||
data[:tracer]
|
||||
)
|
||||
|
||||
ash_query =
|
||||
add_aggregates_and_attributes_to_loaded_relationships(
|
||||
ash_query,
|
||||
calculation_dependencies
|
||||
)
|
||||
|
||||
must_be_reselected =
|
||||
if request_opts[:initial_data] do
|
||||
# If there wasn't an explicit query select
|
||||
|
@ -1249,6 +1255,43 @@ defmodule Ash.Actions.Read do
|
|||
|
||||
defp validate_get(_, _, _), do: :ok
|
||||
|
||||
defp add_aggregates_and_attributes_to_loaded_relationships(
|
||||
query,
|
||||
calculation_deps
|
||||
) do
|
||||
calculation_deps = Enum.uniq(calculation_deps)
|
||||
|
||||
calculation_deps
|
||||
|> Enum.filter(&(&1.type == :relationship && loading?(query, &1)))
|
||||
|> Enum.reduce(query, fn relationship_dep, query ->
|
||||
to_load =
|
||||
calculation_deps
|
||||
|> Enum.filter(fn dep ->
|
||||
dep.type in [:attribute, :aggregate] &&
|
||||
dep.path ==
|
||||
relationship_dep.path ++ [{relationship_dep.relationship, relationship_dep.query}]
|
||||
end)
|
||||
|> Enum.map(fn dep ->
|
||||
if dep.type == :attribute do
|
||||
dep.attribute
|
||||
else
|
||||
dep.aggregate
|
||||
end
|
||||
end)
|
||||
|
||||
load =
|
||||
relationship_dep.path
|
||||
|> Enum.map(&elem(&1, 0))
|
||||
|> Enum.concat([relationship_dep.relationship])
|
||||
|> to_load(to_load)
|
||||
|
||||
Ash.Query.load(query, load)
|
||||
end)
|
||||
end
|
||||
|
||||
defp to_load([], leaf), do: leaf
|
||||
defp to_load([path | rest], leaf), do: [{path, to_load(rest, leaf)}]
|
||||
|
||||
defp calculation_dependency_requests(
|
||||
query,
|
||||
calculation_deps,
|
||||
|
@ -1727,7 +1770,9 @@ defmodule Ash.Actions.Read do
|
|||
|
||||
# TODO: Make more generic?
|
||||
defp query_unique_for_calc(query) do
|
||||
Ash.Query.unset(query, [:load])
|
||||
query
|
||||
|> Ash.Query.unset([:load])
|
||||
|> Map.put(:api, nil)
|
||||
end
|
||||
|
||||
defp loading?(query, %{
|
||||
|
|
|
@ -393,7 +393,7 @@ defmodule Ash.Engine do
|
|||
defp name_of({path, dep}, state) do
|
||||
case Enum.find(state.requests, &(&1.path == path)) do
|
||||
nil ->
|
||||
"unknown dependency: #{inspect(path, structs: false)} -> #{inspect(dep)}"
|
||||
"unknown dependency: #{inspect(path)} -> #{inspect(dep)}"
|
||||
|
||||
request ->
|
||||
"#{request.name} -> #{inspect(dep)}"
|
||||
|
|
|
@ -148,6 +148,20 @@ defmodule Ash.Test.CalculationTest do
|
|||
end
|
||||
end
|
||||
|
||||
defmodule BestFriendsBestFriendsFirstName do
|
||||
use Ash.Calculation
|
||||
|
||||
def load(_query, _opts, _) do
|
||||
[best_friend: :best_friends_first_name]
|
||||
end
|
||||
|
||||
def calculate(records, _opts, _) do
|
||||
Enum.map(records, fn record ->
|
||||
"bf: #{record.best_friend && record.best_friend.best_friends_first_name}"
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule FriendsNames do
|
||||
use Ash.Calculation
|
||||
|
||||
|
@ -211,6 +225,8 @@ defmodule Ash.Test.CalculationTest do
|
|||
constraints: [allow_empty?: true, trim?: false]
|
||||
end
|
||||
|
||||
calculate :best_friends_best_friends_first_name, :string, BestFriendsBestFriendsFirstName
|
||||
|
||||
calculate :best_friends_first_name_plus_stuff,
|
||||
:string,
|
||||
BestFriendsFirstNamePlusStuff
|
||||
|
@ -656,4 +672,29 @@ defmodule Ash.Test.CalculationTest do
|
|||
|
||||
assert best_friends_names == [nil, "zach daniel"]
|
||||
end
|
||||
|
||||
test "loading a nested aggregate works" do
|
||||
best_friends_best_friends_first_names =
|
||||
User
|
||||
|> Ash.Query.load(:best_friends_best_friends_first_name)
|
||||
|> Api.read!()
|
||||
|> Enum.map(& &1.best_friends_best_friends_first_name)
|
||||
|> Enum.sort()
|
||||
|
||||
assert best_friends_best_friends_first_names == ["bf: ", "bf: "]
|
||||
end
|
||||
|
||||
test "loading a nested aggregate works even when its already being loaded" do
|
||||
best_friends_best_friends_first_names =
|
||||
User
|
||||
|> Ash.Query.load([
|
||||
:best_friends_best_friends_first_name,
|
||||
best_friend: [best_friend: [:first_name]]
|
||||
])
|
||||
|> Api.read!()
|
||||
|> Enum.map(& &1.best_friends_best_friends_first_name)
|
||||
|> Enum.sort()
|
||||
|
||||
assert best_friends_best_friends_first_names == ["bf: ", "bf: "]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue