Skip to content

Commit

Permalink
revert
Browse files Browse the repository at this point in the history
  • Loading branch information
NickNeck committed Jul 27, 2023
1 parent d1fcd41 commit 80693ff
Show file tree
Hide file tree
Showing 6 changed files with 1,862 additions and 0 deletions.
127 changes: 127 additions & 0 deletions docs/cast.md
@@ -0,0 +1,127 @@
# Cast

`Xema` provides the functions `Xema.cast/2` and `Xema.cast!/2` to convert data according to the
schema. The converted data will also be validated against the schema. The function `Xema.cast/2`
returns an error tuple with a `CastError` when the data cannot be converted.

```elixir
iex> schema = Xema.new({:integer, minimum: 1})
iex> Xema.cast(schema, "5")
{:ok, 5}
iex> Xema.cast(schema, "-5")
{:error, %Xema.ValidationError{
reason: %{minimum: 1, value: -5}
}}
iex> {:error, error} = Xema.cast(schema, [])
{:error, %Xema.CastError{
key: nil,
path: [],
to: :integer,
value: []
}}
iex> Exception.message(error)
"cannot cast [] to :integer"
```

With `use Xema` the functions are also available.

```elixir
iex> defmodule Int do
...> use Xema
...>
...> xema do: integer(minimum: 1)
...> end
iex>
iex> Int.cast("6")
{:ok, 6}
iex> Int.cast("-1")
{:error, %Xema.ValidationError{
reason: %{minimum: 1, value: -1}
}}
```

## Maps

To convert map keys the schema has to specify the `keys` keyword.

```elixir
iex> defmodule MapSchema do
...> use Xema
...>
...> xema do
...> map(
...> keys: :atoms,
...> properties: %{
...> pos: integer(minimum: 0),
...> neg: integer(maximum: 0)
...> }
...> )
...> end
...> end
iex>
iex> MapSchema.cast(%{"pos" => "5", "neg" => "-5"})
{:ok, %{pos: 5, neg: -5}}
```

## Caster

To convert "special" structs a caster can be specified. A caster function has to return the
converted value in a tuple `{:ok, value}` or an `:error`.

```elixir
iex> defmodule UrisSchema do
...> use Xema
...>
...> def caster(string) when is_binary(string), do: {:ok, URI.parse(string)}
...>
...> def caster(%URI{} = uri), do: {:ok, uri}
...>
...> def caster(_), do: :error
...>
...> xema do
...> map(
...> keys: :atoms,
...> properties: %{
...> uris: list(
...> items: strux(URI, caster: &UrisSchema.caster/1)
...> )
...> }
...> )
...> end
...> end
iex> UrisSchema.cast(%{uris: ["https://hexdocs.pm/elixir/Kernel.html"]})
{:ok, %{uris: [URI.parse("https://hexdocs.pm/elixir/Kernel.html")]}}
```

The caster can also be a tuple of module and function name or an mfa tuple.

Using `Caster` behaviour is also supported.

```elixir
iex> defmodule UriCaster do
...> @behaviour Xema.Caster
...>
...> @impl true
...> def cast(%URI{} = uri), do: {:ok, uri}
...>
...> def cast(string) when is_binary(string), do: {:ok, URI.parse(string)}
...>
...> def cast(_), do: :error
...> end
iex>
iex> defmodule UriSchema do
...> use Xema
...>
...> xema do
...> map(
...> keys: :strings,
...> properties: %{
...> "uri" => strux(URI, caster: UriCaster)
...> }
...> )
...> end
...> end
iex>
iex> UriSchema.cast(%{uri: "https://elixir-lang.org/docs.html"})
{:ok, %{"uri" => URI.parse("https://elixir-lang.org/docs.html")}}
```

0 comments on commit 80693ff

Please sign in to comment.