mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: properly load manual to_one relationships
This commit is contained in:
parent
03482cf908
commit
5e3b71e79b
5 changed files with 77 additions and 5 deletions
|
@ -230,7 +230,11 @@ defmodule Ash.Actions.Load do
|
|||
|
||||
defp attach_to_one_loads(value, %{name: name, no_attributes?: true}, data, lead_path) do
|
||||
map_or_update(data, lead_path, fn record ->
|
||||
Map.put(record, name, value |> List.wrap() |> Enum.at(0))
|
||||
if is_map(data) do
|
||||
Map.put(record, name, value |> List.wrap() |> Enum.at(0) |> elem(1))
|
||||
else
|
||||
Map.put(record, name, value |> List.wrap() |> Enum.at(0))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
@ -248,7 +252,7 @@ defmodule Ash.Actions.Load do
|
|||
|
||||
map_or_update(data, lead_path, fn record ->
|
||||
related =
|
||||
Enum.filter(value, fn {key, _value} ->
|
||||
Enum.find_value(value, fn {key, value} ->
|
||||
key =
|
||||
if is_map(key) || !single_primary_key do
|
||||
key
|
||||
|
@ -257,10 +261,16 @@ defmodule Ash.Actions.Load do
|
|||
end
|
||||
|
||||
if last_relationship.source.primary_key_matches?(record, key) do
|
||||
value
|
||||
{:ok, value}
|
||||
end
|
||||
end)
|
||||
|> List.wrap()
|
||||
|> case do
|
||||
{:ok, value} ->
|
||||
value
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
|
||||
Map.put(
|
||||
record,
|
||||
|
|
|
@ -122,7 +122,7 @@ defmodule Ash.Resource do
|
|||
|> Enum.filter(& &1.primary_key?)
|
||||
|> Enum.map(&{&1.name, &1.type})
|
||||
|
||||
@primary_key @primary_key_with_types |> Enum.map(&elem(&1, 1))
|
||||
@primary_key @primary_key_with_types |> Enum.map(&elem(&1, 0))
|
||||
|
||||
if Ash.Resource.Info.primary_key_simple_equality?(__MODULE__) do
|
||||
def primary_key_matches?(left, right) do
|
||||
|
|
|
@ -91,6 +91,14 @@ defmodule Ash.Test.Policy.ComplexTest do
|
|||
|> Api.read!(actor: me)
|
||||
end
|
||||
|
||||
test "it properly scopes single loads" do
|
||||
assert [%{best_friend: %{name: "me"}}] =
|
||||
User
|
||||
|> Ash.Query.filter(best_friend.name == "me")
|
||||
|> Api.read!()
|
||||
|> Api.load!(:best_friend)
|
||||
end
|
||||
|
||||
test "aggregates can be loaded", %{me: me} do
|
||||
Post
|
||||
|> Ash.Query.load(:count_of_comments)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
defmodule Ash.Test.Support.PolicyComplex.User.Relationships.BestFriend do
|
||||
@moduledoc false
|
||||
use Ash.Resource.ManualRelationship
|
||||
require Ash.Query
|
||||
|
||||
def load(users, _, %{api: api, query: query}) do
|
||||
user_ids = Enum.map(users, & &1.id)
|
||||
|
||||
friend_links =
|
||||
Ash.Test.Support.PolicyComplex.FriendLink
|
||||
|> Ash.Query.filter(source_id in ^user_ids or destination_id in ^user_ids)
|
||||
|> api.read!()
|
||||
|
||||
all_relevant_user_ids =
|
||||
friend_links
|
||||
|> Enum.flat_map(fn %{source_id: source_id, destination_id: destination_id} ->
|
||||
[source_id, destination_id]
|
||||
end)
|
||||
|> Enum.uniq()
|
||||
|
||||
all_relevant_users =
|
||||
query
|
||||
|> Ash.Query.filter(id in ^all_relevant_user_ids)
|
||||
|> api.read!()
|
||||
|> Map.new(&{&1.id, &1})
|
||||
|
||||
{:ok,
|
||||
Map.new(users, fn user ->
|
||||
best_friend =
|
||||
friend_links
|
||||
|> Enum.filter(fn %{source_id: source_id, destination_id: destination_id} ->
|
||||
source_id == user.id || destination_id == user.id
|
||||
end)
|
||||
|> Enum.flat_map(fn %{source_id: source_id, destination_id: destination_id} ->
|
||||
if source_id == user.id do
|
||||
Map.get(all_relevant_users, destination_id)
|
||||
else
|
||||
Map.get(all_relevant_users, source_id)
|
||||
end
|
||||
|> List.wrap()
|
||||
end)
|
||||
|> Enum.uniq()
|
||||
# obviously a weird heuristic for being someone's best friend 😆
|
||||
|> Enum.sort_by(&String.jaro_distance(user.name, &1.name))
|
||||
|> Enum.at(0)
|
||||
|
||||
{user.id, best_friend}
|
||||
end)}
|
||||
end
|
||||
end
|
|
@ -69,5 +69,9 @@ defmodule Ash.Test.Support.PolicyComplex.User do
|
|||
has_many :friends, Ash.Test.Support.PolicyComplex.User do
|
||||
manual Ash.Test.Support.PolicyComplex.User.Relationships.Friends
|
||||
end
|
||||
|
||||
has_one :best_friend, Ash.Test.Support.PolicyComplex.User do
|
||||
manual Ash.Test.Support.PolicyComplex.User.Relationships.BestFriend
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue