mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 21:43:02 +12:00
improvement: if "" fails to cast, cast it as nil
instead
improvement: ReadActionRequiresActor error improvement: `ensure_selected` change
This commit is contained in:
parent
ff0de75138
commit
ad0af9831c
6 changed files with 77 additions and 4 deletions
|
@ -211,6 +211,8 @@ defmodule Ash.Changeset do
|
||||||
|
|
||||||
Datalayers currently are not notified of the `select` for a changeset(unlike queries), and creates/updates select all fields when they are performed.
|
Datalayers currently are not notified of the `select` for a changeset(unlike queries), and creates/updates select all fields when they are performed.
|
||||||
A select provided on a changeset simply sets the unselected fields to `nil` before returning the result.
|
A select provided on a changeset simply sets the unselected fields to `nil` before returning the result.
|
||||||
|
|
||||||
|
Use `ensure_selected/2` if you simply wish to make sure a field has been selected, without deselecting any other fields.
|
||||||
"""
|
"""
|
||||||
def select(changeset, fields, opts \\ []) do
|
def select(changeset, fields, opts \\ []) do
|
||||||
if opts[:replace?] do
|
if opts[:replace?] do
|
||||||
|
@ -220,6 +222,27 @@ defmodule Ash.Changeset do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Ensures that the given attributes are selected.
|
||||||
|
|
||||||
|
The first call to `select/2` will *limit* the fields to only the provided fields.
|
||||||
|
Use `ensure_selected/2` to say "select this field (or these fields) without deselecting anything else".
|
||||||
|
|
||||||
|
See `select/2` for more.
|
||||||
|
"""
|
||||||
|
def ensure_selected(changeset, fields) do
|
||||||
|
if changeset.select do
|
||||||
|
Ash.Changeset.select(changeset, List.wrap(fields))
|
||||||
|
else
|
||||||
|
to_select =
|
||||||
|
changeset.resource
|
||||||
|
|> Ash.Resource.Info.attributes()
|
||||||
|
|> Enum.map(& &1.name)
|
||||||
|
|
||||||
|
Ash.Changeset.select(changeset, to_select)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Ensure the the specified attributes are `nil` in the changeset results.
|
Ensure the the specified attributes are `nil` in the changeset results.
|
||||||
"""
|
"""
|
||||||
|
|
16
lib/ash/error/query/read_action_requires_actor.ex
Normal file
16
lib/ash/error/query/read_action_requires_actor.ex
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
defmodule Ash.Error.Query.ReadActionRequiresActor do
|
||||||
|
@moduledoc "Used when an actor is referenced in a filter template, but no actor exists"
|
||||||
|
use Ash.Error.Exception
|
||||||
|
|
||||||
|
def_ash_error([], class: :invalid)
|
||||||
|
|
||||||
|
defimpl Ash.ErrorKind do
|
||||||
|
def id(_), do: Ash.UUID.generate()
|
||||||
|
|
||||||
|
def code(_), do: "actor_required"
|
||||||
|
|
||||||
|
def message(_error) do
|
||||||
|
"actor is required"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -63,6 +63,7 @@ defmodule Ash.Query do
|
||||||
InvalidLimit,
|
InvalidLimit,
|
||||||
InvalidOffset,
|
InvalidOffset,
|
||||||
NoReadAction,
|
NoReadAction,
|
||||||
|
ReadActionRequiresActor,
|
||||||
Required
|
Required
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +368,7 @@ defmodule Ash.Query do
|
||||||
|
|
||||||
defp add_action_filters(query, action, actor) do
|
defp add_action_filters(query, action, actor) do
|
||||||
if Ash.Filter.template_references_actor?(action.filter) and is_nil(actor) do
|
if Ash.Filter.template_references_actor?(action.filter) and is_nil(actor) do
|
||||||
Ash.Query.add_error(query, "Read action requires actor")
|
Ash.Query.add_error(query, ReadActionRequiresActor.exception([]))
|
||||||
else
|
else
|
||||||
built_filter =
|
built_filter =
|
||||||
Ash.Filter.build_filter_from_template(
|
Ash.Filter.build_filter_from_template(
|
||||||
|
@ -597,6 +598,8 @@ defmodule Ash.Query do
|
||||||
if the source field is not selected on the query/provided data an error will be produced. If loading
|
if the source field is not selected on the query/provided data an error will be produced. If loading
|
||||||
a relationship with a query, an error is produced if the query does not select the destination field
|
a relationship with a query, an error is produced if the query does not select the destination field
|
||||||
of the relationship.
|
of the relationship.
|
||||||
|
|
||||||
|
Use `ensure_selected/2` if you simply wish to make sure a field has been selected, without deselecting any other fields.
|
||||||
"""
|
"""
|
||||||
def select(query, fields, opts \\ []) do
|
def select(query, fields, opts \\ []) do
|
||||||
query = to_query(query)
|
query = to_query(query)
|
||||||
|
@ -608,6 +611,14 @@ defmodule Ash.Query do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Ensures that the given attributes are selected.
|
||||||
|
|
||||||
|
The first call to `select/2` will *limit* the fields to only the provided fields.
|
||||||
|
Use `ensure_selected/2` to say "select this field (or these fields) without deselecting anything else".
|
||||||
|
|
||||||
|
See `select/2` for more.
|
||||||
|
"""
|
||||||
def ensure_selected(query, fields) do
|
def ensure_selected(query, fields) do
|
||||||
if query.select do
|
if query.select do
|
||||||
Ash.Query.select(query, List.wrap(fields))
|
Ash.Query.select(query, List.wrap(fields))
|
||||||
|
|
|
@ -72,4 +72,11 @@ defmodule Ash.Resource.Change.Builtins do
|
||||||
def select(value) do
|
def select(value) do
|
||||||
{Ash.Resource.Change.Select, target: value}
|
{Ash.Resource.Change.Select, target: value}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Passes the provided value into `Ash.Changeset.ensure_selected/2`
|
||||||
|
"""
|
||||||
|
def ensure_selected(value) do
|
||||||
|
{Ash.Resource.Change.Select, target: value, ensure?: true}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,10 @@ defmodule Ash.Resource.Change.Select do
|
||||||
use Ash.Resource.Change
|
use Ash.Resource.Change
|
||||||
|
|
||||||
def change(changeset, opts, _) do
|
def change(changeset, opts, _) do
|
||||||
|
if opts[:ensure?] do
|
||||||
|
Ash.Changeset.ensure_selected(changeset, opts[:target] || [])
|
||||||
|
else
|
||||||
Ash.Changeset.select(changeset, opts[:target] || [])
|
Ash.Changeset.select(changeset, opts[:target] || [])
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -356,12 +356,24 @@ defmodule Ash.Type do
|
||||||
{:ok, value}
|
{:ok, value}
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
|
case term do
|
||||||
|
"" ->
|
||||||
|
cast_input(type, nil, constraints)
|
||||||
|
|
||||||
|
_ ->
|
||||||
{:error, "is invalid"}
|
{:error, "is invalid"}
|
||||||
|
end
|
||||||
|
|
||||||
{:error, other} ->
|
{:error, other} ->
|
||||||
|
case term do
|
||||||
|
"" ->
|
||||||
|
cast_input(type, nil, constraints)
|
||||||
|
|
||||||
|
_ ->
|
||||||
{:error, other}
|
{:error, other}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Casts a value from the data store to an instance of the type, or errors
|
Casts a value from the data store to an instance of the type, or errors
|
||||||
|
|
Loading…
Reference in a new issue