Define a Graphql Enum Type in Ash
Here's how to define an enum type in Ash that's exposed in Graphql.
Adhoc enum
Adhoc enums are great, because they're easy and quick to define, and the constraints are enforced. Here's what that definition looks like:
defmodule MyLibrary.Shelves.BookReview do
use Ash.Resource,
domain: MyLibrary.Shelves,
data_layer: AshPostgres.DataLayer,
extensions: [AshGraphql.Resource]
attributes do
# ...
attribute :rating, :atom do
constraints one_of: [:one, :two, :three, :four, :five]
public? true
end
end
end
When you create such a book review in graphql, for instance (ash_graphql integration not shown above), the mutation would look something like this:
mutation rateBook($rating: String!) {
rateBook(input: {
rating: $rating
}) {
result {
rating
}
}
}Note the type here. It's a string. This means that it's not necessarily clear from graphql introspection what the possible values for rating are, even though we've constrained them on the back end.
One way to make this more explicit and clear is to create an enum.
Expose Ash Enum Type in Graphql
This enum, when used instead of a plain-jane atom, will also be visible via graphql introspection. Let's adjust our rating attribute from above, in part:
attributes do
attribute :rating, MyLibrary.Shelves.Stars do
public? true
end
end
Note that the type is not :atom now. It's a new custom module. Importantly, this module must exist either before this module definition or in a separate file so that it's available at compile time. Otherwise, you'll get a compiler error.
Here's an enum:
defmodule MyLibrary.Shelves.Stars do
use Ash.Type.Enum, values: [:one, :two, :three, :four, :five]
def graphql_type(_), do: :star
end
Pretty straightforward. Now when you mutate, you'll use a new Star! type, like this:
mutation rateBook($rating: Star!) {
rateBook(input: {
rating: $rating
}) {
result {
rating
}
}
}And now Star can be introspected to see that only the values of 'one', 'two', 'three', 'four' or 'five' are allowed. It's helpful.
There are other optional functions that can be implemented from Ash.Type.Enum for translating valid enum values or providing documentation. Those are not pictured.
But picture your next API with some beautiful enums. Oooooo...