mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
improvement: optimize relates_to_actor_via checks
This commit is contained in:
parent
6c94e5e578
commit
0e13456eb0
6 changed files with 89 additions and 2 deletions
|
@ -391,10 +391,18 @@ defmodule Ash.DataLayer.Ets do
|
|||
kind: :count,
|
||||
relationship_path: relationship_path,
|
||||
query: query,
|
||||
authorization_filter: authorization_filter,
|
||||
name: name,
|
||||
load: load
|
||||
},
|
||||
{:ok, record} ->
|
||||
query =
|
||||
if authorization_filter do
|
||||
Ash.Query.do_filter(query, authorization_filter)
|
||||
else
|
||||
query
|
||||
end
|
||||
|
||||
with {:ok, loaded_record} <- api.load(record, relationship_path),
|
||||
related <- Ash.Filter.Runtime.get_related(loaded_record, relationship_path),
|
||||
{:ok, filtered} <-
|
||||
|
|
|
@ -1225,7 +1225,7 @@ defmodule Ash.Filter do
|
|||
case do_run_other_data_layer_filters(
|
||||
expr,
|
||||
api,
|
||||
Ash.Resource.Info.related(resource, path),
|
||||
Ash.Resource.Info.related(resource, at_path ++ path),
|
||||
data
|
||||
) do
|
||||
{:ok, new_nested} ->
|
||||
|
|
|
@ -168,7 +168,7 @@ defmodule Ash.Filter.Runtime do
|
|||
end
|
||||
|
||||
defp flatten_many_to_many(record, rel, values, rest) do
|
||||
full_flattened = Enum.map(values, &flatten_relationships(&1, [rest]))
|
||||
full_flattened = Enum.map(values, &flatten_relationships(&1, [rest])) |> List.flatten()
|
||||
|
||||
Enum.map(full_flattened, fn value ->
|
||||
record
|
||||
|
|
|
@ -21,3 +21,71 @@ defmodule Ash.Policy.Check.RelatesToActorVia do
|
|||
Ash.Expr.expr(exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}})))
|
||||
end
|
||||
end
|
||||
|
||||
# defmodule Ash.Policy.Check.RelatesToActorVia do
|
||||
# @moduledoc false
|
||||
# use Ash.Policy.FilterCheck
|
||||
|
||||
# require Ash.Expr
|
||||
|
||||
# @impl true
|
||||
# def describe(opts) do
|
||||
# path = Enum.join(opts[:relationship_path], ".")
|
||||
# "record.#{path} == actor"
|
||||
# end
|
||||
|
||||
# @impl true
|
||||
# def filter(opts) do
|
||||
# {last_relationship, to_many?} = relationship_info(opts[:resource], opts[:relationship_path])
|
||||
|
||||
# pkey =
|
||||
# last_relationship.destination
|
||||
# |> Ash.Resource.Info.primary_key()
|
||||
|
||||
# if to_many? do
|
||||
# Ash.Expr.expr(exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}})))
|
||||
# else
|
||||
# put_in_path(opts[:relationship_path], Enum.map(pkey, &{&1, {:_actor, &1}}))
|
||||
# end
|
||||
# end
|
||||
|
||||
# @impl true
|
||||
# def reject(opts) do
|
||||
# {last_relationship, to_many?} = relationship_info(opts[:resource], opts[:relationship_path])
|
||||
|
||||
# pkey =
|
||||
# last_relationship.destination
|
||||
# |> Ash.Resource.Info.primary_key()
|
||||
|
||||
# if to_many? do
|
||||
# Ash.Expr.expr(not exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}})))
|
||||
# else
|
||||
# [
|
||||
# or: [
|
||||
# [not: filter(opts)],
|
||||
# [put_in_path(opts[:relationship_path], Enum.map(pkey, &{:is_nil, &1}))]
|
||||
# ]
|
||||
# ]
|
||||
# end
|
||||
# end
|
||||
|
||||
# defp relationship_info(resource, path, to_many? \\ false)
|
||||
|
||||
# defp relationship_info(resource, [rel], to_many?) do
|
||||
# rel = Ash.Resource.Info.relationship(resource, rel)
|
||||
# {rel, to_many? || rel.cardinality == :many}
|
||||
# end
|
||||
|
||||
# defp relationship_info(resource, [rel | rest], to_many?) do
|
||||
# rel = Ash.Resource.Info.relationship(resource, rel)
|
||||
# relationship_info(rel.destination, rest, to_many? || rel.cardinality == :many)
|
||||
# end
|
||||
|
||||
# defp put_in_path([], value) do
|
||||
# value
|
||||
# end
|
||||
|
||||
# defp put_in_path([key | rest], value) do
|
||||
# [{key, put_in_path(rest, value)}]
|
||||
# end
|
||||
# end
|
||||
|
|
|
@ -90,4 +90,11 @@ defmodule Ash.Test.Policy.ComplexTest do
|
|||
|> Ash.Query.filter(comments.text == "comment by a friend of a friend on my post")
|
||||
|> Api.read!(actor: me)
|
||||
end
|
||||
|
||||
test "aggregates can be loaded", %{me: me} do
|
||||
Post
|
||||
|> Ash.Query.load(:count_of_comments)
|
||||
|> Ash.Query.filter(count_of_comments == 10)
|
||||
|> Api.read!(actor: me)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,6 +43,10 @@ defmodule Ash.Test.Support.PolicyComplex.Post do
|
|||
end
|
||||
end
|
||||
|
||||
aggregates do
|
||||
count :count_of_comments, :comments
|
||||
end
|
||||
|
||||
code_interface do
|
||||
define_for Ash.Test.Support.PolicyComplex.Api
|
||||
define :create, args: [:text]
|
||||
|
|
Loading…
Reference in a new issue