Skip to content

Commit

Permalink
fix: honor reuse_values? when lazy loading relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Oct 2, 2024
1 parent 58e319c commit 02bff6f
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 14 deletions.
6 changes: 4 additions & 2 deletions lib/ash/actions/read/calculations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,7 @@ defmodule Ash.Actions.Read.Calculations do
nil ->
related_query =
relationship.destination
|> Ash.Query.set_context(%{private: %{lazy?: true}})
|> Ash.Query.set_context(%{private: %{lazy?: true, reuse_values?: reuse_values?}})
|> Ash.Query.select([])
|> merge_query_load(
further,
Expand Down Expand Up @@ -1814,7 +1814,9 @@ defmodule Ash.Actions.Read.Calculations do
Ash.Resource.loaded?(initial_data, relationship_path ++ [calculation], type: :request)
end

defp loaded_and_reusable?(_initial_data, _relationship_path, _calculation, _false), do: false
defp loaded_and_reusable?(_initial_data, _relationship_path, _calculation, false) do
false
end

defp add_calculation_dependency(query, source, dest) do
%{
Expand Down
7 changes: 5 additions & 2 deletions lib/ash/actions/read/read.ex
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ defmodule Ash.Actions.Read do

defp load_relationships(data, query, opts) do
lazy? = !!opts[:lazy?]
reuse_values? = !!opts[:reuse_values?]

context =
%{
Expand All @@ -384,15 +385,17 @@ defmodule Ash.Actions.Read do
Ash.Actions.Read.Relationships.load(
data,
query,
lazy?
lazy?,
reuse_values?
)
end

_ ->
Ash.Actions.Read.Relationships.load(
data,
query,
lazy?
lazy?,
reuse_values?
)
end
end
Expand Down
18 changes: 10 additions & 8 deletions lib/ash/actions/read/relationships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ defmodule Ash.Actions.Read.Relationships do
{:ok, records}
end

def load(records, query, lazy?) do
def load(records, query, lazy?, reuse_values?) do
query.load
|> with_related_queries(query, records, lazy?)
|> fetch_related_records(records)
|> fetch_related_records(records, reuse_values?)
|> attach_related_records(records)
end

Expand All @@ -39,9 +39,9 @@ defmodule Ash.Actions.Read.Relationships do
end)
end

defp fetch_related_records(batch, records, acc \\ [])
defp fetch_related_records(batch, records, reuse_values?, acc \\ [])

defp fetch_related_records([], _records, acc) do
defp fetch_related_records([], _records, _reuse_values?, acc) do
Enum.map(acc, fn
{a, b, %Task{} = task} ->
{a, b, Task.await(task, :infinity)}
Expand All @@ -54,12 +54,12 @@ defmodule Ash.Actions.Read.Relationships do
end)
end

defp fetch_related_records([first | rest], records, acc) do
defp fetch_related_records([first | rest], records, reuse_values?, acc) do
result =
case first do
{relationship, {:lazy, query}} ->
{relationship, {:lazy, query},
lazy_related_records(records, relationship, query, Enum.empty?(rest))}
lazy_related_records(records, relationship, query, Enum.empty?(rest), reuse_values?)}

{relationship, %{valid?: true} = related_query} ->
do_fetch_related_records(records, relationship, related_query, Enum.empty?(rest))
Expand All @@ -68,10 +68,10 @@ defmodule Ash.Actions.Read.Relationships do
{relationship, related_query, {:error, errors}}
end

fetch_related_records(rest, records, [result | acc])
fetch_related_records(rest, records, reuse_values?, [result | acc])
end

defp lazy_related_records(records, relationship, related_query, last?) do
defp lazy_related_records(records, relationship, related_query, last?, reuse_values?) do
primary_key = Ash.Resource.Info.primary_key(relationship.source)

related_records_with_lazy_join_source =
Expand Down Expand Up @@ -101,6 +101,8 @@ defmodule Ash.Actions.Read.Relationships do
fn ->
Ash.load(related_records_with_lazy_join_source, related_query,
lazy?: true,
reuse_values?:
reuse_values? || related_query.context[:private][:reuse_values?] || false,
domain: related_query.domain,
actor: related_query.context.private[:actor],
tenant: related_query.tenant,
Expand Down
7 changes: 5 additions & 2 deletions lib/ash/changeset/changeset.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4280,8 +4280,11 @@ defmodule Ash.Changeset do
],
meta: [
type: :any,
doc:
"Freeform data that will be retained along with the options, which can be used to track/manage the changes that are added to the `relationships` key."
doc: """
Freeform data that will be retained along with the options, which can be used to track/manage the changes
that are added to the `relationships` key. Use the `meta[:order]` option to specify the order in which multiple
calls to `manage_relationship` should be executed.
"""
],
ignore?: [
type: :any,
Expand Down
2 changes: 2 additions & 0 deletions test/support/policy_complex/resources/post.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Ash.Test.Support.PolicyComplex.Post do
@moduledoc false

use Ash.Resource,
domain: Ash.Test.Support.PolicyComplex.Domain,
data_layer: Ash.DataLayer.Ets,
Expand Down Expand Up @@ -44,6 +45,7 @@ defmodule Ash.Test.Support.PolicyComplex.Post do
end

create :create do
primary? true
accept [:text]
change relate_actor(:author)
end
Expand Down

0 comments on commit 02bff6f

Please sign in to comment.