mirror of
https://github.com/ash-project/splode.git
synced 2024-09-19 12:52:46 +12:00
docs: add some more docs on how error classes work
This commit is contained in:
parent
0d49772317
commit
ff64778e68
1 changed files with 75 additions and 0 deletions
|
@ -100,6 +100,81 @@ def do_multiple_things(argument) do
|
|||
end
|
||||
```
|
||||
|
||||
## Error classes
|
||||
|
||||
When we combine errors into error classes, we choose the first error class for which there are any errors as the "class" of the combined error. For example, in Ash Framework, we have:
|
||||
|
||||
```elixir
|
||||
use Splode,
|
||||
error_classes: [
|
||||
forbidden: Ash.Error.Forbidden,
|
||||
invalid: Ash.Error.Invalid,
|
||||
framework: Ash.Error.Framework,
|
||||
unknown: Ash.Error.Unknown
|
||||
],
|
||||
unknown_error: Ash.Error.Unknown.UnknownError
|
||||
```
|
||||
|
||||
What this means is that if there are any `Forbidden` errors, then the class is `Forbidden`. A `Forbidden` error _can_ contain any of the lower classed errors. This allows people to match on and/or rescue on "the general type of failure" that occurred. Given that you have many varied kinds of errors, you can use this to your advantage to have both detailed errors, but simple to match on errors. Here is an example:
|
||||
|
||||
```elixir
|
||||
def get(conn, %{"user_id" => user_id}) do
|
||||
user = MyApp.Accounts.get_user!()
|
||||
render_user(conn, user)
|
||||
rescue
|
||||
e in Ash.Error.Forbidden ->
|
||||
render_error(conn, %{error: "You can't do this"})
|
||||
|
||||
e in Ash.Error.Invalid ->
|
||||
render_error(conn, %{error: "You did something wrong"})
|
||||
|
||||
e in [Ash.Error.Framework, Ash.Error.Unknown] ->
|
||||
render_error(conn, %{error: "Something went wrong"})
|
||||
end
|
||||
```
|
||||
|
||||
Or, alternatively, you can pattern match on them given a non-raised error class
|
||||
|
||||
```elixir
|
||||
def get(conn, %{"user_id" => user_id}) do
|
||||
case MyApp.Accounts.get_user() do
|
||||
{:ok, user} ->
|
||||
render_user(conn, user)
|
||||
|
||||
{:error, %Ash.Error.Forbidden{}} ->
|
||||
render_error(conn, %{error: "You can't do this"})
|
||||
|
||||
{:error, %Ash.Error.Invalid{}} ->
|
||||
render_error(conn, %{error: "You did something wrong"})
|
||||
|
||||
{:error, %error{}} when error in [Ash.Error.Framework, Ash.Error.Unknown] ->
|
||||
render_error(conn, %{error: "Something went wrong"})
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
# Raising Exceptions
|
||||
|
||||
To make a `!` version of a function that returns one of these errors is quite simple:
|
||||
|
||||
```elixir
|
||||
def get_user!(user_id) do
|
||||
with {:ok, user} <- get_user(user_id) do
|
||||
{:ok, user}
|
||||
else
|
||||
{:error, error} -> raise MyApp.Errors.to_class(error)
|
||||
end
|
||||
end
|
||||
def get_user(user_id) do
|
||||
case Repo.get(user_id) do
|
||||
nil ->
|
||||
{:error, MyApp.Error.NotFound.exception(resource: User, key: user_id)}
|
||||
user ->
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```elixir
|
||||
|
|
Loading…
Reference in a new issue