mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +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.
|
||||
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
|
||||
if opts[:replace?] do
|
||||
|
@ -220,6 +222,27 @@ defmodule Ash.Changeset do
|
|||
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 """
|
||||
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,
|
||||
InvalidOffset,
|
||||
NoReadAction,
|
||||
ReadActionRequiresActor,
|
||||
Required
|
||||
}
|
||||
|
||||
|
@ -367,7 +368,7 @@ defmodule Ash.Query do
|
|||
|
||||
defp add_action_filters(query, action, 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
|
||||
built_filter =
|
||||
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
|
||||
a relationship with a query, an error is produced if the query does not select the destination field
|
||||
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
|
||||
query = to_query(query)
|
||||
|
@ -608,6 +611,14 @@ defmodule Ash.Query do
|
|||
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
|
||||
if query.select do
|
||||
Ash.Query.select(query, List.wrap(fields))
|
||||
|
|
|
@ -72,4 +72,11 @@ defmodule Ash.Resource.Change.Builtins do
|
|||
def select(value) do
|
||||
{Ash.Resource.Change.Select, target: value}
|
||||
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
|
||||
|
|
|
@ -3,6 +3,10 @@ defmodule Ash.Resource.Change.Select do
|
|||
use Ash.Resource.Change
|
||||
|
||||
def change(changeset, opts, _) do
|
||||
Ash.Changeset.select(changeset, opts[:target] || [])
|
||||
if opts[:ensure?] do
|
||||
Ash.Changeset.ensure_selected(changeset, opts[:target] || [])
|
||||
else
|
||||
Ash.Changeset.select(changeset, opts[:target] || [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -356,10 +356,22 @@ defmodule Ash.Type do
|
|||
{:ok, value}
|
||||
|
||||
:error ->
|
||||
{:error, "is invalid"}
|
||||
case term do
|
||||
"" ->
|
||||
cast_input(type, nil, constraints)
|
||||
|
||||
_ ->
|
||||
{:error, "is invalid"}
|
||||
end
|
||||
|
||||
{:error, other} ->
|
||||
{:error, other}
|
||||
case term do
|
||||
"" ->
|
||||
cast_input(type, nil, constraints)
|
||||
|
||||
_ ->
|
||||
{:error, other}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue