fix: properly handle "bare" references, and track it for potential later use

This commit is contained in:
Zach Daniel 2022-08-24 11:54:12 -04:00
parent 80833c3f58
commit 91d3bf314a
2 changed files with 56 additions and 29 deletions

View file

@ -234,7 +234,7 @@ defmodule Ash.Filter do
filter filter
{:error, error} -> {:error, error} ->
raise error raise Ash.Error.to_error_class(error)
end end
end end
@ -296,7 +296,13 @@ defmodule Ash.Filter do
field = field =
case ref.attribute do case ref.attribute do
field when is_atom(field) -> field when is_atom(field) ->
Ash.Resource.Info.field(resource, field) case Ash.Resource.Info.field(resource, field) do
nil ->
field
field ->
field
end
field -> field ->
field field
@ -307,7 +313,16 @@ defmodule Ash.Filter do
errors = errors =
refs refs
|> Enum.flat_map(fn ref -> |> Enum.flat_map(fn
%{attribute: attribute, relationship_path: relationship_path} when is_atom(attribute) ->
[
NoSuchAttributeOrRelationship.exception(
attribute_or_relationship: attribute,
resource: Ash.Resource.Info.related(resource, relationship_path)
)
]
ref ->
field = ref.attribute field = ref.attribute
# This handles manually added calcualtions and aggregates # This handles manually added calcualtions and aggregates
@ -337,6 +352,7 @@ defmodule Ash.Filter do
multiple_filter_errors = multiple_filter_errors =
refs refs
|> Enum.filter(&is_map(&1.attribute))
|> Enum.filter(fn ref -> |> Enum.filter(fn ref ->
Map.fetch(ref.attribute, :filterable?) == {:ok, :simple_equality} Map.fetch(ref.attribute, :filterable?) == {:ok, :simple_equality}
end) end)
@ -1675,8 +1691,15 @@ defmodule Ash.Filter do
defp attribute(%{public?: true, resource: resource}, attribute), defp attribute(%{public?: true, resource: resource}, attribute),
do: Ash.Resource.Info.public_attribute(resource, attribute) do: Ash.Resource.Info.public_attribute(resource, attribute)
defp attribute(%{public?: false, resource: resource}, attribute), defp attribute(%{public?: false, resource: resource}, attribute) do
do: Ash.Resource.Info.attribute(resource, attribute) case Ash.Resource.Info.attribute(resource, attribute) do
nil ->
raise "what"
attr ->
attr
end
end
defp aggregate(%{public?: true, resource: resource}, aggregate), defp aggregate(%{public?: true, resource: resource}, aggregate),
do: Ash.Resource.Info.public_aggregate(resource, aggregate) do: Ash.Resource.Info.public_aggregate(resource, aggregate)
@ -1782,6 +1805,10 @@ defmodule Ash.Filter do
end end
end end
defp add_expression_part(%Ref{} = ref, _context, _expression) do
{:ok, %{ref | bare?: true}}
end
defp add_expression_part({%Ref{} = ref, nested_statement}, context, expression) do defp add_expression_part({%Ref{} = ref, nested_statement}, context, expression) do
case related(context, ref.relationship_path) do case related(context, ref.relationship_path) do
nil -> nil ->
@ -2314,7 +2341,7 @@ defmodule Ash.Filter do
new_ref = %{ new_ref = %{
ref ref
| relationship_path: ref.relationship_path ++ [relationship.name], | relationship_path: ref.relationship_path ++ [relationship.name],
attribute: Ash.Resource.Info.attribute(relationship.destination, key), attribute: attribute(%{context | resource: relationship.destination}, key),
resource: relationship.destination resource: relationship.destination
} }

View file

@ -1,6 +1,6 @@
defmodule Ash.Query.Ref do defmodule Ash.Query.Ref do
@moduledoc "Represents a relation/attribute reference" @moduledoc "Represents a relation/attribute reference"
defstruct [:attribute, :relationship_path, :resource, :simple_equality?] defstruct [:attribute, :relationship_path, :resource, :simple_equality?, :bare?]
defimpl Inspect do defimpl Inspect do
def inspect(ref, _opts) do def inspect(ref, _opts) do