mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
105 lines
2.4 KiB
Markdown
105 lines
2.4 KiB
Markdown
# Validations
|
|
|
|
## Builtin Validations
|
|
|
|
Checkout the documentation for `Ash.Resource.Validation.Builtins` to see the builtin validations.
|
|
|
|
Some examples of usage of builtin validations
|
|
|
|
```elixir
|
|
validate match(:email, ~r/@/)
|
|
|
|
validate compare(:age, greater_than_or_equal_to: 18) do
|
|
message "must be over 18 to sign up"
|
|
end
|
|
|
|
validate present(:last_name) do
|
|
where [present(:first_name), present(:middle_name)]
|
|
message "must also be supplied if setting first name and middle_name"
|
|
end
|
|
```
|
|
|
|
## Custom Validations
|
|
|
|
```elixir
|
|
defmodule MyApp.Validations.IsPrime do
|
|
# transform and validate opts
|
|
|
|
use Ash.Resource.Validation
|
|
|
|
@impl true
|
|
def init(opts) do
|
|
if is_atom(opts[:attribute]) do
|
|
{:ok, opts}
|
|
else
|
|
{:error, "attribute must be an atom!"}
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def validate(changeset, opts) do
|
|
value = Ash.Changeset.get_attribute(changeset, opts[:attribute])
|
|
# this is a function I made up for example
|
|
if is_nil(value) || Math.is_prime?(value) do
|
|
:ok
|
|
else
|
|
# The returned error will be passed into `Ash.Error.to_ash_error/3`
|
|
{:error, field: opts[:attribute], message: "must be prime"}
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
This could then be used in a resource via:
|
|
|
|
```elixir
|
|
validate {MyApp.Validations.IsPrime, attribute: :foo}
|
|
```
|
|
|
|
## Where
|
|
|
|
The `where` can be used to perform changes/validations conditionally. This functions by running the validation, and if the validation returns an error, we discard the error and skip the operation. This means that even custom validations can be used in conditions.
|
|
|
|
For example:
|
|
|
|
```elixir
|
|
validate present(:other_number) do
|
|
where [{MyApp.Validations.IsPrime, attribute: :foo}]
|
|
end
|
|
```
|
|
|
|
## Action vs Global Validations
|
|
|
|
You can place a validation in any create, update, or destroy action. For example:
|
|
|
|
```elixir
|
|
actions do
|
|
create :create do
|
|
validate compare(:age, greater_than_or_equal_to: 18)
|
|
end
|
|
end
|
|
```
|
|
|
|
Or you can use the global validations block to validate on all actions of a given type. Where statements can be used in either. Use `on` to determine the types of actions the validation runs on. By default, it only runs on create an update actions
|
|
|
|
```elixir
|
|
validations do
|
|
validate present([:foo, :bar], at_least: 1) do
|
|
on [:create, :update]
|
|
where present(:baz)
|
|
end
|
|
end
|
|
```
|
|
|
|
## Action-Specific Validation
|
|
|
|
You can also put a validation directly in an action, like so:
|
|
|
|
```elixir
|
|
actions do
|
|
create do
|
|
...
|
|
validate present([:foo, :bar], at_least: 1)
|
|
end
|
|
end
|
|
```
|