mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 21:43:02 +12:00
2c129a7ab7
resolves a bug where attributes were not selected for create notifications docs: add validations guide closes #631
87 lines
No EOL
2.2 KiB
Markdown
87 lines
No EOL
2.2 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
|
|
def init(opts) do
|
|
if is_atom(opts[:attribute]) do
|
|
{:ok, opts}
|
|
else
|
|
{:error, "attribute must be an atom!"}
|
|
end
|
|
end
|
|
|
|
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
|
|
``` |