Skip to content

Commit

Permalink
fix: ensure that belongs_to relationships are properly not reloaded w…
Browse files Browse the repository at this point in the history
…ith `lazy?: true`

closes #1208
  • Loading branch information
zachdaniel committed May 29, 2024
1 parent 49b6962 commit e9897eb
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
26 changes: 21 additions & 5 deletions lib/ash/actions/read/read.ex
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ defmodule Ash.Actions.Read do

query =
if opts[:initial_data] do
select = source_fields(query) ++ (query.select || [])
select = source_fields(query, opts[:lazy?] && opts[:initial_data]) ++ (query.select || [])

select =
if reuse_values? do
Expand Down Expand Up @@ -679,9 +679,18 @@ defmodule Ash.Actions.Read do
|> Enum.concat(Map.values(query.aggregates))
end

defp source_fields(query) do
defp source_fields(query, lazy_for_initial_data \\ nil) do
query
|> Ash.Query.accessing([:relationships], false)
|> then(fn relationships ->
if lazy_for_initial_data do
Enum.reject(relationships, fn relationship ->
Ash.Resource.loaded?(lazy_for_initial_data, relationship, lists: :any)
end)
else
relationships
end
end)
|> Enum.flat_map(fn name ->
case Ash.Resource.Info.relationship(query.resource, name) do
%{no_attributes?: true} ->
Expand Down Expand Up @@ -958,7 +967,7 @@ defmodule Ash.Actions.Read do
true
) do
results
|> attach_fields(initial_data, query, query, false)
|> attach_fields(initial_data, query, query, false, true)
|> cleanup_field_auth(query)
|> compute_expression_at_runtime_for_missing_records(query, data_layer_calculations)
|> case do
Expand Down Expand Up @@ -1646,7 +1655,8 @@ defmodule Ash.Actions.Read do
data,
original_query,
query,
missing_pkeys?
missing_pkeys?,
no_relationships? \\ false
) do
{aggregates_in_data, aggregates_in_aggregates} =
original_query.aggregates
Expand All @@ -1660,9 +1670,15 @@ defmodule Ash.Actions.Read do

fields_from_data =
(original_query.select || []) ++
Keyword.keys(original_query.load || []) ++
Enum.map(aggregates_in_data, & &1.load) ++ Enum.map(calculations_in_data, & &1.load)

fields_from_data =
if no_relationships? do
fields_from_data
else
Keyword.keys(original_query.load || []) ++ fields_from_data
end

fields_from_aggregates =
Enum.map(aggregates_in_aggregates, & &1.name)

Expand Down
1 change: 1 addition & 0 deletions lib/ash/process_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ defmodule Ash.ProcessHelpers do
case e do
%{stacktrace: %{stacktrace: stacktrace}} when not is_nil(stacktrace) ->
update_in(e.stacktrace.stacktrace, &(&1 ++ Enum.drop(stacktrace, 1)))

_ ->
e
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ defmodule Ash.MixProject do
],
groups_for_extras: [
"Start Here": [
"documentation/home.md",
"readme.md",
"documentation/tutorials/get-started.md"
],
Tutorials: ~r"documentation/tutorials",
Expand Down
9 changes: 9 additions & 0 deletions test/actions/load_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,15 @@ defmodule Ash.Test.Actions.LoadTest do
for post <- author.posts do
assert post.author.id == author.id
end

post = Enum.at(author.posts, 0)
post = Map.update!(post, :author, &Map.put(&1, :name, "shouldn't change"))

assert post.author.name == "shouldn't change"
author_after_load =
post |> Ash.load!(:author, authorize?: false, lazy?: true) |> Map.get(:author)

assert author_after_load.name == "shouldn't change"
end

test "nested lazy loads work" do
Expand Down

0 comments on commit e9897eb

Please sign in to comment.