Packages
ash_graphql
1.7.13
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.5
1.0.0-rc.4
retired
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.9
0.26.8
0.26.7
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.0
0.25.13
0.25.12
0.25.10
0.25.9
0.25.8
0.25.7
0.25.6
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.13
0.22.12
0.22.11
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
retired
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0-rc.3
0.20.0-rc.2
0.20.0-rc.1
0.20.0-rc.0
0.19.0
0.18.0-rc0
0.17.5
0.17.5-rc0
0.17.4
0.17.2
0.17.1
0.17.0
0.16.28
0.16.27
0.16.26
0.16.25
0.16.24
0.16.23
0.16.22
0.16.21
0.16.20
0.16.18-rc5
0.16.18-rc4
0.16.18-rc3
0.16.18-rc2
0.16.18-rc1
0.16.18-rc0
0.16.17
0.16.16
0.16.15
0.16.14
0.16.13
0.16.12
0.16.11
0.16.10
0.16.9
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.1
0.12.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
The extension for building GraphQL APIs with Ash
Current section
Files
Jump to
Current section
Files
documentation/topics/graphql-generation.md
# GraphQL Query Generation
Following where we left off from [Getting Started with GraphQL](/documentation/tutorials/getting-started-with-graphql.md), this guide explores what the GraphQL requests and responses look like for different queries defined with the AshGraphql DSL.
All of the following examples apply to queries & mutations places on the domain as well.
## Fetch Data by ID
```elixir
defmodule Helpdesk.Support.Ticket do
use Ash.Resource,
...,
extensions: [
AshGraphql.Resource
]
attributes do
# Add an autogenerated UUID primary key called `:id`.
uuid_primary_key :id
# Add a string type attribute called `:subject`
attribute :subject, :string
end
actions do
# Add a set of simple actions. You'll customize these later.
defaults [:read, :update, :destroy]
end
graphql do
type :ticket
queries do
# create a field called `get_ticket` that uses the `read` read action to fetch a single ticket
get :get_ticket, :read
end
end
end
```
For the `get_ticket` query defined above, the corresponding GraphQL would look like this:
```graphql
query ($id: ID!) {
getTicket(id: $id) {
id
subject
}
}
```
And the response would look similar to this:
```json
{
"data": {
"getTicket": {
"id": "",
"subject": ""
}
}
}
```
Let's look at an example of querying a list of things.
```elixir
graphql do
type :ticket
queries do
# create a field called `get_ticket` that uses the `read` read action to fetch a single ticket
get :get_ticket, :read
# create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets
list :list_tickets, :read
end
end
```
This time, we've added `list :list_tickets, :read`, to generate a GraphQL query for listing tickets.
The request would look something like this:
```graphql
query {
listTickets {
id
subject
}
}
```
And the response would look similar to this:
```json
{
"data": {
"listTickets": [
{
"id": "",
"subject": ""
}
]
}
}
```
## Filter Data With Arguments
Now, let's say we want to add query parameters to `listTickets`. How do we do that?
Consider `list :list_tickets, :read` and the `actions` section:
```elixir
actions do
# Add a set of simple actions. You'll customize these later.
defaults [:read, :update, :destroy]
end
graphql do
type :ticket
queries do
# create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets
list :list_tickets, :read
end
end
```
The second argument to `list :list_tickets, :read` is the action that will be called when the query is run.
In the current example, the action is `:read`, which is the generic Read action.
Let's create a custom action in order to define query parameters for the `listTickets` query.
We'll call this action `:query_tickets`:
```elixir
actions do
defaults [:read, :update, :destroy]
read :query_tickets do
argument :representative_id, :uuid
filter(
expr do
is_nil(^arg(:representative_id)) or representative_id == ^arg(:representative_id)
end
)
end
end
graphql do
type :ticket
queries do
# create a field called `list_tickets` that uses the `:query_tickets` read action to fetch a list of tickets
list :list_tickets, :query_tickets
end
end
```
In the `graphql` section, the `list/2` call has been changed, replacing the `:read` action with `:query_tickets`.
The GraphQL request would look something like this:
```graphql
query ($representative_id: ID) {
list_tickets(representative_id: $representative_id) {
id
representative_id
subject
}
}
```
## Mutations and Enums
Now, let's look at how to create a ticket by using a GraphQL mutation.
Let's say you have a Resource that defines an enum-like attribute:
```elixir
defmodule Helpdesk.Support.Ticket do
use Ash.Resource,
...,
extensions: [
AshGraphql.Resource
]
attributes do
uuid_primary_key :id
attribute :subject, :string
attribute :status, :atom, constraints: [one_of: [:open, :closed]]
end
actions do
defaults [:create, :read, :update, :destroy]
end
graphql do
type :ticket
queries do
get :get_ticket, :read
end
mutations do
create :create_ticket, :create
end
end
end
```
Above, the following changes have been added:
1. In the `attributes` section, the `:status` attribute has been added.
2. In the `actions` section, the `:create` action has been added.
3. The `:create_ticket` mutation has been defined in the new `graphql.mutations` section.
The `:status` attribute is an enum that is constrained to the values `[:open, :closed]`.
When used in conjunction with AshGraphql, a GraphQL enum type called `TicketStatus` will be generated for this attribute.
The possible GraphQL values for `TicketStatus` are `OPEN` and `CLOSED`.
See [Use Enums with GraphQL](/documentation/guides/use-enums-with-graphql.md) for more information.
We can now create a ticket with the `createTicket` mutation:
```graphql
mutation ($input: CreateTicketInput!) {
createTicket(input: $input) {
result {
id
subject
status
}
errors {
code
fields
message
shortMessage
vars
}
}
}
```
**Note**
- The resulting ticket data is wrapped in AshGraphql's `result` object.
- Validation errors are wrapped in a list of error objects under `errors`, also specified in the query.
AshGraphql does this by default instead of exposing errors in GraphQL's standard `errors` array.
This behavior can be changed by setting `root_level_errors? true` in the `graphql` section
of your Ash domain module:
```elixir
defmodule Helpdesk.Support do
use Ash.Domain, extensions: [AshGraphql.Domain]
graphql do
root_level_errors? true
end
end
```
If we were to run this mutation in a test, it would look something like this:
```elixir
input = %{
subject: "My Ticket",
status: "OPEN"
}
resp_body =
post(conn, "/api/graphql", %{
query: query,
variables: %{input: input}
})
|> json_response(200)
```
Notice that the `status` attribute is set to `"OPEN"` and not `"open"`. It is important that the value of the `status` be uppercase.
This is required by GraphQL enums. AshGraphql will automatically convert the value to the correct case.
The response will look something like this:
```json
{
"data": {
"createTicket": {
"result": {
"id": "b771e433-0979-4d07-a280-4d12373849aa",
"subject": "My Ticket",
"status": "OPEN"
}
}
}
}
```
Again, AshGraphql will automatically convert the `status` value from `:open` to `"OPEN"`.
## More GraphQL Docs
If you haven't already, please turn on the documentation tag for AshGraphql. Tags can be controlled
at the top of the left navigation menu, under "Including Libraries:".
- [Getting Started With GraphQL](/documentation/tutorials/getting-started-with-graphql.md)
- `AshGraphql.Domain`