mirror of
https://github.com/ash-project/ash.git
synced 2024-09-17 03:53:02 +12:00
improvement: add :* as a valid value in skip_unknown_inputs
improvement: add `skip_unknown_inputs` to individual actions improvement: add `skip_unknown_inputs` constraint to embedded resources
This commit is contained in:
parent
4763181ff9
commit
32c8da1f8d
17 changed files with 75 additions and 33 deletions
|
@ -187,6 +187,7 @@ spark_locals_without_parens = [
|
||||||
sensitive?: 1,
|
sensitive?: 1,
|
||||||
short_name: 1,
|
short_name: 1,
|
||||||
skip_global_validations?: 1,
|
skip_global_validations?: 1,
|
||||||
|
skip_unknown_inputs: 1,
|
||||||
soft?: 1,
|
soft?: 1,
|
||||||
sort: 1,
|
sort: 1,
|
||||||
sortable?: 1,
|
sortable?: 1,
|
||||||
|
|
|
@ -471,7 +471,7 @@ end
|
||||||
| [`return_stream?`](#reactor-bulk_create-return_stream?){: #reactor-bulk_create-return_stream? } | `boolean` | `false` | If set to `true`, instead of an `Ash.BulkResult`, a mixed stream is returned. |
|
| [`return_stream?`](#reactor-bulk_create-return_stream?){: #reactor-bulk_create-return_stream? } | `boolean` | `false` | If set to `true`, instead of an `Ash.BulkResult`, a mixed stream is returned. |
|
||||||
| [`rollback_on_error?`](#reactor-bulk_create-rollback_on_error?){: #reactor-bulk_create-rollback_on_error? } | `boolean` | `true` | Whether or not to rollback the transaction on error, if the resource is in a transaction. |
|
| [`rollback_on_error?`](#reactor-bulk_create-rollback_on_error?){: #reactor-bulk_create-rollback_on_error? } | `boolean` | `true` | Whether or not to rollback the transaction on error, if the resource is in a transaction. |
|
||||||
| [`select`](#reactor-bulk_create-select){: #reactor-bulk_create-select } | `atom \| list(atom)` | | A select statement to apply to records. Ignored if `return_records?` is not `true`. |
|
| [`select`](#reactor-bulk_create-select){: #reactor-bulk_create-select } | `atom \| list(atom)` | | A select statement to apply to records. Ignored if `return_records?` is not `true`. |
|
||||||
| [`skip_unknown_inputs`](#reactor-bulk_create-skip_unknown_inputs){: #reactor-bulk_create-skip_unknown_inputs } | `atom \| list(atom)` | | A list of inputs that, if provided, will be ignored if they are not recognized by the action. |
|
| [`skip_unknown_inputs`](#reactor-bulk_create-skip_unknown_inputs){: #reactor-bulk_create-skip_unknown_inputs } | `atom \| String.t \| list(atom \| String.t)` | | A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. |
|
||||||
| [`sorted?`](#reactor-bulk_create-sorted?){: #reactor-bulk_create-sorted? } | `boolean` | `false` | Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`. |
|
| [`sorted?`](#reactor-bulk_create-sorted?){: #reactor-bulk_create-sorted? } | `boolean` | `false` | Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`. |
|
||||||
| [`stop_on_error?`](#reactor-bulk_create-stop_on_error?){: #reactor-bulk_create-stop_on_error? } | `boolean` | `false` | If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. |
|
| [`stop_on_error?`](#reactor-bulk_create-stop_on_error?){: #reactor-bulk_create-stop_on_error? } | `boolean` | `false` | If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. |
|
||||||
| [`success_state`](#reactor-bulk_create-success_state){: #reactor-bulk_create-success_state } | `:success \| :partial_success` | `:success` | Bulk results can be entirely or partially successful. Chooses the `Ash.BulkResult` state to consider the step a success. |
|
| [`success_state`](#reactor-bulk_create-success_state){: #reactor-bulk_create-success_state } | `:success \| :partial_success` | `:success` | Bulk results can be entirely or partially successful. Chooses the `Ash.BulkResult` state to consider the step a success. |
|
||||||
|
@ -673,7 +673,7 @@ end
|
||||||
| [`reuse_values?`](#reactor-bulk_update-reuse_values?){: #reactor-bulk_update-reuse_values? } | `boolean` | `false` | Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. |
|
| [`reuse_values?`](#reactor-bulk_update-reuse_values?){: #reactor-bulk_update-reuse_values? } | `boolean` | `false` | Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. |
|
||||||
| [`rollback_on_error?`](#reactor-bulk_update-rollback_on_error?){: #reactor-bulk_update-rollback_on_error? } | `boolean` | `true` | Whether or not to rollback the transaction on error, if the resource is in a transaction. |
|
| [`rollback_on_error?`](#reactor-bulk_update-rollback_on_error?){: #reactor-bulk_update-rollback_on_error? } | `boolean` | `true` | Whether or not to rollback the transaction on error, if the resource is in a transaction. |
|
||||||
| [`select`](#reactor-bulk_update-select){: #reactor-bulk_update-select } | `atom \| list(atom)` | | A select statement to apply to records. Ignored if `return_records?` is not `true`. |
|
| [`select`](#reactor-bulk_update-select){: #reactor-bulk_update-select } | `atom \| list(atom)` | | A select statement to apply to records. Ignored if `return_records?` is not `true`. |
|
||||||
| [`skip_unknown_inputs`](#reactor-bulk_update-skip_unknown_inputs){: #reactor-bulk_update-skip_unknown_inputs } | `atom \| list(atom)` | | A list of inputs that, if provided, will be ignored if they are not recognized by the action. |
|
| [`skip_unknown_inputs`](#reactor-bulk_update-skip_unknown_inputs){: #reactor-bulk_update-skip_unknown_inputs } | `atom \| String.t \| list(atom \| String.t)` | | A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. |
|
||||||
| [`sorted?`](#reactor-bulk_update-sorted?){: #reactor-bulk_update-sorted? } | `boolean` | `false` | Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`. |
|
| [`sorted?`](#reactor-bulk_update-sorted?){: #reactor-bulk_update-sorted? } | `boolean` | `false` | Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`. |
|
||||||
| [`stop_on_error?`](#reactor-bulk_update-stop_on_error?){: #reactor-bulk_update-stop_on_error? } | `boolean` | `false` | If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. |
|
| [`stop_on_error?`](#reactor-bulk_update-stop_on_error?){: #reactor-bulk_update-stop_on_error? } | `boolean` | `false` | If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. |
|
||||||
| [`strategy`](#reactor-bulk_update-strategy){: #reactor-bulk_update-strategy } | `list(:atomic \| :atomic_batches \| :stream)` | `[:atomic]` | The strategy or strategies to enable. `:stream` is used in all cases if the data layer does not support atomics. |
|
| [`strategy`](#reactor-bulk_update-strategy){: #reactor-bulk_update-strategy } | `list(:atomic \| :atomic_batches \| :stream)` | `[:atomic]` | The strategy or strategies to enable. `:stream` is used in all cases if the data layer does not support atomics. |
|
||||||
|
|
|
@ -1028,6 +1028,7 @@ end
|
||||||
| [`skip_global_validations?`](#actions-create-skip_global_validations?){: #actions-create-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
| [`skip_global_validations?`](#actions-create-skip_global_validations?){: #actions-create-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
||||||
| [`error_handler`](#actions-create-error_handler){: #actions-create-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
| [`error_handler`](#actions-create-error_handler){: #actions-create-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
||||||
| [`notifiers`](#actions-create-notifiers){: #actions-create-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
| [`notifiers`](#actions-create-notifiers){: #actions-create-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
||||||
|
| [`skip_unknown_inputs`](#actions-create-skip_unknown_inputs){: #actions-create-skip_unknown_inputs } | `atom \| String.t \| list(atom \| String.t)` | `[]` | A list of unknown fields to skip, or `:*` to skip all unknown fields. |
|
||||||
| [`manual?`](#actions-create-manual?){: #actions-create-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
| [`manual?`](#actions-create-manual?){: #actions-create-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
||||||
|
|
||||||
|
|
||||||
|
@ -1510,6 +1511,7 @@ update :flag_for_review, primary?: true
|
||||||
| [`skip_global_validations?`](#actions-update-skip_global_validations?){: #actions-update-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
| [`skip_global_validations?`](#actions-update-skip_global_validations?){: #actions-update-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
||||||
| [`error_handler`](#actions-update-error_handler){: #actions-update-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
| [`error_handler`](#actions-update-error_handler){: #actions-update-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
||||||
| [`notifiers`](#actions-update-notifiers){: #actions-update-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
| [`notifiers`](#actions-update-notifiers){: #actions-update-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
||||||
|
| [`skip_unknown_inputs`](#actions-update-skip_unknown_inputs){: #actions-update-skip_unknown_inputs } | `atom \| String.t \| list(atom \| String.t)` | `[]` | A list of unknown fields to skip, or `:*` to skip all unknown fields. |
|
||||||
| [`manual?`](#actions-update-manual?){: #actions-update-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
| [`manual?`](#actions-update-manual?){: #actions-update-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
||||||
|
|
||||||
|
|
||||||
|
@ -1752,6 +1754,7 @@ end
|
||||||
| [`skip_global_validations?`](#actions-destroy-skip_global_validations?){: #actions-destroy-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
| [`skip_global_validations?`](#actions-destroy-skip_global_validations?){: #actions-destroy-skip_global_validations? } | `boolean` | `false` | If true, global validations will be skipped. Useful for manual actions. |
|
||||||
| [`error_handler`](#actions-destroy-error_handler){: #actions-destroy-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
| [`error_handler`](#actions-destroy-error_handler){: #actions-destroy-error_handler } | `mfa` | | Sets the error handler on the changeset. See `Ash.Changeset.handle_errors/2` for more |
|
||||||
| [`notifiers`](#actions-destroy-notifiers){: #actions-destroy-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
| [`notifiers`](#actions-destroy-notifiers){: #actions-destroy-notifiers } | `list(module)` | | Notifiers that will be called specifically for this action. |
|
||||||
|
| [`skip_unknown_inputs`](#actions-destroy-skip_unknown_inputs){: #actions-destroy-skip_unknown_inputs } | `atom \| String.t \| list(atom \| String.t)` | `[]` | A list of unknown fields to skip, or `:*` to skip all unknown fields. |
|
||||||
| [`manual?`](#actions-destroy-manual?){: #actions-destroy-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
| [`manual?`](#actions-destroy-manual?){: #actions-destroy-manual? } | `boolean` | | Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more. |
|
||||||
|
|
||||||
|
|
||||||
|
|
29
lib/ash.ex
29
lib/ash.ex
|
@ -98,6 +98,11 @@ defmodule Ash do
|
||||||
""",
|
""",
|
||||||
default: false
|
default: false
|
||||||
],
|
],
|
||||||
|
skip_unknown_inputs: [
|
||||||
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
|
doc:
|
||||||
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys."
|
||||||
|
],
|
||||||
reuse_values?: [
|
reuse_values?: [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -248,6 +253,11 @@ defmodule Ash do
|
||||||
Metadata to be merged into the metadata field for all notifications sent from this operation.
|
Metadata to be merged into the metadata field for all notifications sent from this operation.
|
||||||
"""
|
"""
|
||||||
],
|
],
|
||||||
|
skip_unknown_inputs: [
|
||||||
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
|
doc:
|
||||||
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys."
|
||||||
|
],
|
||||||
load: [
|
load: [
|
||||||
type: :any,
|
type: :any,
|
||||||
doc: "A load statement to add onto the changeset"
|
doc: "A load statement to add onto the changeset"
|
||||||
|
@ -402,9 +412,9 @@ defmodule Ash do
|
||||||
"If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously"
|
"If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously"
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
skip_unknown_inputs: [
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
doc:
|
doc:
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys."
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -452,11 +462,6 @@ defmodule Ash do
|
||||||
doc:
|
doc:
|
||||||
"The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics."
|
"The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics."
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
|
||||||
doc:
|
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
|
||||||
],
|
|
||||||
load: [
|
load: [
|
||||||
type: :any,
|
type: :any,
|
||||||
doc: "A load statement to apply on the resulting records."
|
doc: "A load statement to apply on the resulting records."
|
||||||
|
@ -516,11 +521,6 @@ defmodule Ash do
|
||||||
type: :any,
|
type: :any,
|
||||||
doc:
|
doc:
|
||||||
"A filter to apply to records. This is also applied to a stream of inputs."
|
"A filter to apply to records. This is also applied to a stream of inputs."
|
||||||
],
|
|
||||||
skip_unknown_inputs: [
|
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
|
||||||
doc:
|
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> Spark.Options.merge(
|
|> Spark.Options.merge(
|
||||||
|
@ -572,11 +572,6 @@ defmodule Ash do
|
||||||
]},
|
]},
|
||||||
doc:
|
doc:
|
||||||
"The fields to upsert. If not set, the action's `upsert_fields` is used. Unlike singular `create`, `bulk_create` with `upsert?` requires that `upsert_fields` be specified explicitly in one of these two locations."
|
"The fields to upsert. If not set, the action's `upsert_fields` is used. Unlike singular `create`, `bulk_create` with `upsert?` requires that `upsert_fields` be specified explicitly in one of these two locations."
|
||||||
],
|
|
||||||
skip_unknown_inputs: [
|
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
|
||||||
doc:
|
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> Spark.Options.merge(
|
|> Spark.Options.merge(
|
||||||
|
|
|
@ -61,8 +61,22 @@ defmodule Ash.Actions.Helpers do
|
||||||
defp set_context(%Ash.ActionInput{} = action_input, context),
|
defp set_context(%Ash.ActionInput{} = action_input, context),
|
||||||
do: Ash.ActionInput.set_context(action_input, context)
|
do: Ash.ActionInput.set_context(action_input, context)
|
||||||
|
|
||||||
|
defp set_skip_unknown_opts(opts, %{action: %{skip_unknown_inputs: skip_unknown_inputs}}) do
|
||||||
|
Keyword.update(
|
||||||
|
opts,
|
||||||
|
:skip_unknown_inputs,
|
||||||
|
skip_unknown_inputs,
|
||||||
|
&Enum.concat(List.wrap(&1), skip_unknown_inputs)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp set_skip_unknown_opts(opts, _query_or_changeset) do
|
||||||
|
opts
|
||||||
|
end
|
||||||
|
|
||||||
def set_context_and_get_opts(domain, query_or_changeset, opts) do
|
def set_context_and_get_opts(domain, query_or_changeset, opts) do
|
||||||
opts = transform_tenant(opts)
|
opts = transform_tenant(opts)
|
||||||
|
opts = set_skip_unknown_opts(opts, query_or_changeset)
|
||||||
query_or_changeset = set_context(query_or_changeset, opts[:context] || %{})
|
query_or_changeset = set_context(query_or_changeset, opts[:context] || %{})
|
||||||
|
|
||||||
domain =
|
domain =
|
||||||
|
|
|
@ -962,6 +962,9 @@ defmodule Ash.Changeset do
|
||||||
match?("_" <> _, key) ->
|
match?("_" <> _, key) ->
|
||||||
{:cont, changeset}
|
{:cont, changeset}
|
||||||
|
|
||||||
|
:* in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
|
{:cont, changeset}
|
||||||
|
|
||||||
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
{:cont, changeset}
|
{:cont, changeset}
|
||||||
|
|
||||||
|
@ -998,6 +1001,9 @@ defmodule Ash.Changeset do
|
||||||
{:halt, {:not_atomic, reason}}
|
{:halt, {:not_atomic, reason}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
:* in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
|
{:cont, changeset}
|
||||||
|
|
||||||
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
{:cont, changeset}
|
{:cont, changeset}
|
||||||
|
|
||||||
|
@ -1020,6 +1026,9 @@ defmodule Ash.Changeset do
|
||||||
match?("_" <> _, key) ->
|
match?("_" <> _, key) ->
|
||||||
{:cont, changeset}
|
{:cont, changeset}
|
||||||
|
|
||||||
|
:* in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
|
{:cont, changeset}
|
||||||
|
|
||||||
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
key in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
{:cont, changeset}
|
{:cont, changeset}
|
||||||
|
|
||||||
|
@ -1112,9 +1121,9 @@ defmodule Ash.Changeset do
|
||||||
doc: "set the tenant on the changeset"
|
doc: "set the tenant on the changeset"
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
skip_unknown_inputs: [
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
doc:
|
doc:
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys."
|
||||||
],
|
],
|
||||||
context: [
|
context: [
|
||||||
type: :map,
|
type: :map,
|
||||||
|
@ -2037,6 +2046,9 @@ defmodule Ash.Changeset do
|
||||||
cond do
|
cond do
|
||||||
!Ash.Resource.Info.action_input?(changeset.resource, action.name, name) ->
|
!Ash.Resource.Info.action_input?(changeset.resource, action.name, name) ->
|
||||||
cond do
|
cond do
|
||||||
|
:* in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
|
changeset
|
||||||
|
|
||||||
name in skip_unknown_inputs ->
|
name in skip_unknown_inputs ->
|
||||||
changeset
|
changeset
|
||||||
|
|
||||||
|
|
|
@ -364,6 +364,7 @@ defmodule Ash.EmbeddableType do
|
||||||
:destroy_action,
|
:destroy_action,
|
||||||
:update_action,
|
:update_action,
|
||||||
:domain,
|
:domain,
|
||||||
|
:skip_unknown_inputs,
|
||||||
:__source__
|
:__source__
|
||||||
])
|
])
|
||||||
|> Keyword.put(:on_update,
|
|> Keyword.put(:on_update,
|
||||||
|
@ -448,6 +449,8 @@ defmodule Ash.EmbeddableType do
|
||||||
|> Enum.concat(
|
|> Enum.concat(
|
||||||
Enum.flat_map(Ash.Resource.Info.primary_key(__MODULE__), &[&1, to_string(&1)])
|
Enum.flat_map(Ash.Resource.Info.primary_key(__MODULE__), &[&1, to_string(&1)])
|
||||||
)
|
)
|
||||||
|
|> Enum.concat(List.wrap(constraints[:skip_unknown_inputs]))
|
||||||
|
|> Enum.concat(List.wrap(constraints[:items][:skip_unknown_inputs]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_change(old_value, "", constraints) do
|
def prepare_change(old_value, "", constraints) do
|
||||||
|
|
|
@ -474,10 +474,6 @@ defmodule Ash.Helpers do
|
||||||
get_domain(resource, opts)
|
get_domain(resource, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_domain(%resource{}, opts) do
|
|
||||||
get_domain(resource, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_domain(nil, opts) do
|
def get_domain(nil, opts) do
|
||||||
cond do
|
cond do
|
||||||
domain = opts[:domain] ->
|
domain = opts[:domain] ->
|
||||||
|
|
|
@ -472,9 +472,9 @@ defmodule Ash.Query do
|
||||||
doc: "set the tenant on the query"
|
doc: "set the tenant on the query"
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
skip_unknown_inputs: [
|
||||||
type: {:list, {:or, [:atom, :string]}},
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
doc:
|
doc:
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action."
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys."
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -648,6 +648,9 @@ defmodule Ash.Query do
|
||||||
has_argument?(action, name) ->
|
has_argument?(action, name) ->
|
||||||
set_argument(query, name, value)
|
set_argument(query, name, value)
|
||||||
|
|
||||||
|
:* in List.wrap(opts[:skip_unknown_inputs]) ->
|
||||||
|
query
|
||||||
|
|
||||||
name in skip_unknown_inputs ->
|
name in skip_unknown_inputs ->
|
||||||
query
|
query
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ defmodule Ash.Reactor.Dsl.BulkCreate do
|
||||||
return_stream?: boolean,
|
return_stream?: boolean,
|
||||||
rollback_on_error?: boolean,
|
rollback_on_error?: boolean,
|
||||||
select: [atom],
|
select: [atom],
|
||||||
skip_unknown_inputs: [atom],
|
skip_unknown_inputs: list(atom | String.t()),
|
||||||
sorted?: boolean,
|
sorted?: boolean,
|
||||||
stop_on_error?: boolean,
|
stop_on_error?: boolean,
|
||||||
success_state: :success | :partial_success,
|
success_state: :success | :partial_success,
|
||||||
|
@ -226,9 +226,9 @@ defmodule Ash.Reactor.Dsl.BulkCreate do
|
||||||
required: false
|
required: false
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
skip_unknown_inputs: [
|
||||||
type: {:wrap_list, :atom},
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
doc:
|
doc:
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action.",
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys.",
|
||||||
required: false
|
required: false
|
||||||
],
|
],
|
||||||
sorted?: [
|
sorted?: [
|
||||||
|
|
|
@ -88,7 +88,7 @@ defmodule Ash.Reactor.Dsl.BulkUpdate do
|
||||||
reuse_values?: boolean,
|
reuse_values?: boolean,
|
||||||
rollback_on_error?: boolean,
|
rollback_on_error?: boolean,
|
||||||
select: [atom],
|
select: [atom],
|
||||||
skip_unknown_inputs: [atom],
|
skip_unknown_inputs: list(atom | String.t()),
|
||||||
sorted?: boolean,
|
sorted?: boolean,
|
||||||
stop_on_error?: boolean,
|
stop_on_error?: boolean,
|
||||||
strategy: :atomic | :atomic_batches | :stream,
|
strategy: :atomic | :atomic_batches | :stream,
|
||||||
|
@ -290,9 +290,9 @@ defmodule Ash.Reactor.Dsl.BulkUpdate do
|
||||||
required: false
|
required: false
|
||||||
],
|
],
|
||||||
skip_unknown_inputs: [
|
skip_unknown_inputs: [
|
||||||
type: {:wrap_list, :atom},
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
doc:
|
doc:
|
||||||
"A list of inputs that, if provided, will be ignored if they are not recognized by the action.",
|
"A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys.",
|
||||||
required: false
|
required: false
|
||||||
],
|
],
|
||||||
sorted?: [
|
sorted?: [
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule Ash.Resource.Actions.Action do
|
||||||
:run,
|
:run,
|
||||||
constraints: [],
|
constraints: [],
|
||||||
touches_resources: [],
|
touches_resources: [],
|
||||||
|
skip_unknown_inputs: [],
|
||||||
arguments: [],
|
arguments: [],
|
||||||
allow_nil?: false,
|
allow_nil?: false,
|
||||||
transaction?: false,
|
transaction?: false,
|
||||||
|
@ -20,6 +21,7 @@ defmodule Ash.Resource.Actions.Action do
|
||||||
name: atom,
|
name: atom,
|
||||||
description: String.t() | nil,
|
description: String.t() | nil,
|
||||||
arguments: [Ash.Resource.Actions.Argument.t()],
|
arguments: [Ash.Resource.Actions.Argument.t()],
|
||||||
|
skip_unknown_inputs: list(atom() | String.t()),
|
||||||
allow_nil?: boolean,
|
allow_nil?: boolean,
|
||||||
touches_resources: [Ash.Resource.t()],
|
touches_resources: [Ash.Resource.t()],
|
||||||
constraints: Keyword.t(),
|
constraints: Keyword.t(),
|
||||||
|
|
|
@ -13,6 +13,7 @@ defmodule Ash.Resource.Actions.Create do
|
||||||
touches_resources: [],
|
touches_resources: [],
|
||||||
delay_global_validations?: false,
|
delay_global_validations?: false,
|
||||||
skip_global_validations?: false,
|
skip_global_validations?: false,
|
||||||
|
skip_unknown_inputs: [],
|
||||||
upsert?: false,
|
upsert?: false,
|
||||||
upsert_identity: nil,
|
upsert_identity: nil,
|
||||||
upsert_fields: nil,
|
upsert_fields: nil,
|
||||||
|
@ -32,6 +33,7 @@ defmodule Ash.Resource.Actions.Create do
|
||||||
allow_nil_input: list(atom),
|
allow_nil_input: list(atom),
|
||||||
manual: module | nil,
|
manual: module | nil,
|
||||||
upsert?: boolean,
|
upsert?: boolean,
|
||||||
|
skip_unknown_inputs: list(atom | String.t()),
|
||||||
notifiers: [module()],
|
notifiers: [module()],
|
||||||
delay_global_validations?: boolean,
|
delay_global_validations?: boolean,
|
||||||
skip_global_validations?: boolean,
|
skip_global_validations?: boolean,
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Ash.Resource.Actions.Destroy do
|
||||||
:error_handler,
|
:error_handler,
|
||||||
manual: nil,
|
manual: nil,
|
||||||
require_atomic?: Application.compile_env(:ash, :require_atomic_by_default?, true),
|
require_atomic?: Application.compile_env(:ash, :require_atomic_by_default?, true),
|
||||||
|
skip_unknown_inputs: [],
|
||||||
atomic_upgrade?: true,
|
atomic_upgrade?: true,
|
||||||
atomic_upgrade_with: nil,
|
atomic_upgrade_with: nil,
|
||||||
arguments: [],
|
arguments: [],
|
||||||
|
@ -35,6 +36,7 @@ defmodule Ash.Resource.Actions.Destroy do
|
||||||
notifiers: list(module),
|
notifiers: list(module),
|
||||||
arguments: list(Ash.Resource.Actions.Argument.t()),
|
arguments: list(Ash.Resource.Actions.Argument.t()),
|
||||||
atomic_upgrade?: boolean(),
|
atomic_upgrade?: boolean(),
|
||||||
|
skip_unknown_inputs: list(atom() | String.t()),
|
||||||
atomic_upgrade_with: nil | atom(),
|
atomic_upgrade_with: nil | atom(),
|
||||||
require_atomic?: boolean,
|
require_atomic?: boolean,
|
||||||
accept: nil | list(atom),
|
accept: nil | list(atom),
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Ash.Resource.Actions.Read do
|
||||||
get?: nil,
|
get?: nil,
|
||||||
manual: nil,
|
manual: nil,
|
||||||
metadata: [],
|
metadata: [],
|
||||||
|
skip_unknown_inputs: [],
|
||||||
modify_query: nil,
|
modify_query: nil,
|
||||||
multitenancy: nil,
|
multitenancy: nil,
|
||||||
name: nil,
|
name: nil,
|
||||||
|
@ -29,6 +30,7 @@ defmodule Ash.Resource.Actions.Read do
|
||||||
filters: [any],
|
filters: [any],
|
||||||
manual: atom | {atom, Keyword.t()} | nil,
|
manual: atom | {atom, Keyword.t()} | nil,
|
||||||
metadata: [Ash.Resource.Actions.Metadata.t()],
|
metadata: [Ash.Resource.Actions.Metadata.t()],
|
||||||
|
skip_unknown_inputs: list(atom | String.t()),
|
||||||
modify_query: nil | mfa,
|
modify_query: nil | mfa,
|
||||||
multitenancy: atom,
|
multitenancy: atom,
|
||||||
name: atom,
|
name: atom,
|
||||||
|
|
|
@ -69,6 +69,11 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
||||||
type: {:list, {:behaviour, Ash.Notifier}},
|
type: {:list, {:behaviour, Ash.Notifier}},
|
||||||
doc: "Notifiers that will be called specifically for this action."
|
doc: "Notifiers that will be called specifically for this action."
|
||||||
],
|
],
|
||||||
|
skip_unknown_inputs: [
|
||||||
|
type: {:wrap_list, {:or, [:atom, :string]}},
|
||||||
|
default: [],
|
||||||
|
doc: "A list of unknown fields to skip, or `:*` to skip all unknown fields."
|
||||||
|
],
|
||||||
manual?: [
|
manual?: [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
doc: """
|
doc: """
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Ash.Resource.Actions.Update do
|
||||||
accept: nil,
|
accept: nil,
|
||||||
require_attributes: [],
|
require_attributes: [],
|
||||||
allow_nil_input: [],
|
allow_nil_input: [],
|
||||||
|
skip_unknown_inputs: [],
|
||||||
manual: nil,
|
manual: nil,
|
||||||
manual?: false,
|
manual?: false,
|
||||||
require_atomic?: Application.compile_env(:ash, :require_atomic_by_default?, true),
|
require_atomic?: Application.compile_env(:ash, :require_atomic_by_default?, true),
|
||||||
|
@ -33,6 +34,7 @@ defmodule Ash.Resource.Actions.Update do
|
||||||
type: :update,
|
type: :update,
|
||||||
name: atom,
|
name: atom,
|
||||||
manual: module | nil,
|
manual: module | nil,
|
||||||
|
skip_unknown_inputs: list(atom | String.t()),
|
||||||
atomic_upgrade?: boolean(),
|
atomic_upgrade?: boolean(),
|
||||||
atomic_upgrade_with: nil | atom(),
|
atomic_upgrade_with: nil | atom(),
|
||||||
notifiers: list(module),
|
notifiers: list(module),
|
||||||
|
|
Loading…
Reference in a new issue