chore: test enums, add a guide

This commit is contained in:
Zach Daniel 2021-03-28 15:46:23 -04:00
parent e8797f80da
commit c59658b1ff
6 changed files with 168 additions and 0 deletions

View file

@ -0,0 +1,75 @@
# Enums
## Automatically created enums
Enums are implemented automatically for any `atom` attribute with a `one_of` constraint. For example:
```elixir
# On the resource of type `:ticket`
attribute :type, :atom, one_of: [:foo, :bar, :baz]
```
This would produce an enum called `:ticket_type`/`TicketType`.
## Custom enums
You can implement a custom enum by first adding the enum type to your absinthe schema (more [here](https://hexdocs.pm/absinthe/Absinthe.Type.Enum.html)). Then you can define a custom Ash type that refers to that absinthe enum type.
```elixir
# In your absinthe schema:
enum :status do
value(:open, description: "The post is open")
value(:closed, description: "The post is closed")
end
```
```elixir
# Your cusotm Ash Type
defmodule AshGraphql.Test.Status do
use Ash.Type
@values [:open, :closed]
@string_values Enum.map(@values, &to_string/1)
def graphql_input_type(_), do: :status
def graphql_type(_), do: :status
@impl true
def storage_type, do: :string
@impl true
def cast_input(value, _) when value in @values do
{:ok, value}
end
def cast_input(value, _) when is_binary(value) do
value = String.downcase(value)
if value in @string_values do
{:ok, String.to_existing_atom(value)}
else
:error
end
end
@impl true
def cast_stored(value, _) when value in @values do
{:ok, value}
end
def cast_stored(value, _) when value in @string_values do
{:ok, String.to_existing_atom(value)}
rescue
ArgumentError ->
:error
end
@impl true
def dump_to_native(value, _) when is_atom(value) do
{:ok, to_string(value)}
end
def dump_to_native(_, _), do: :error
end
```

View file

@ -158,4 +158,42 @@ defmodule AshGraphql.CreateTest do
}
} = result
end
test "custom enums are used" do
resp =
"""
mutation CreatePost($input: CreatePostInput) {
createPost(input: $input) {
result{
text
status
}
errors{
message
}
}
}
"""
|> Absinthe.run(AshGraphql.Test.Schema,
variables: %{
"input" => %{
"text" => "foobar",
"confirmation" => "foobar",
"status" => "OPEN"
}
}
)
assert {:ok, result} = resp
refute Map.has_key?(result, :errors)
assert %{
data: %{
"createPost" => %{
"result" => %{"text" => "foobar", "status" => "OPEN"}
}
}
} = result
end
end

View file

@ -51,6 +51,7 @@ defmodule AshGraphql.Test.Post do
attribute(:text, :string)
attribute(:published, :boolean, default: false)
attribute(:foo, AshGraphql.Test.Foo)
attribute(:status, AshGraphql.Test.Status)
end
calculations do

View file

@ -17,6 +17,11 @@ defmodule AshGraphql.Test.Schema do
field(:bar, non_null(:string))
end
enum :status do
value(:open, description: "The post is open")
value(:closed, description: "The post is closed")
end
query do
end

View file

@ -1,4 +1,6 @@
defmodule AshGraphql.Test.Foo do
@moduledoc false
use Ash.Type
def graphql_type(_), do: :foo

View file

@ -0,0 +1,47 @@
defmodule AshGraphql.Test.Status do
@moduledoc false
use Ash.Type
@values [:open, :closed]
@string_values Enum.map(@values, &to_string/1)
def graphql_input_type(_), do: :status
def graphql_type(_), do: :status
@impl true
def storage_type, do: :string
@impl true
def cast_input(value, _) when value in @values do
{:ok, value}
end
def cast_input(value, _) when is_binary(value) do
value = String.downcase(value)
if value in @string_values do
{:ok, String.to_existing_atom(value)}
else
:error
end
end
@impl true
def cast_stored(value, _) when value in @values do
{:ok, value}
end
def cast_stored(value, _) when value in @string_values do
{:ok, String.to_existing_atom(value)}
rescue
ArgumentError ->
:error
end
@impl true
def dump_to_native(value, _) when is_atom(value) do
{:ok, to_string(value)}
end
def dump_to_native(_, _), do: :error
end