# 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. ## 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`