Skip to content

Instantly share code, notes, and snippets.

@paulfioravanti
Last active October 3, 2021 01:44
Show Gist options
  • Save paulfioravanti/76483826b2e58bb8f1e3f5ab33692882 to your computer and use it in GitHub Desktop.
Save paulfioravanti/76483826b2e58bb8f1e3f5ab33692882 to your computer and use it in GitHub Desktop.
Example of doing a GraphQL inline fragment in Elm (contactListSpec) against a Union type for paginated objects in Phoenix. Ref: https://github.com/paulfioravanti/phoenix-and-elm/tree/graphql
module ContactList.Request exposing (fetchContactList)
import Contact.Request
import ContactList.Model exposing (ContactList)
import GraphQL.Request.Builder as Builder
exposing
( Document
, NonNull
, ObjectType
, Request
, Query
, ValueSpec
, field
, int
, list
, object
, onType
, string
, with
)
import GraphQL.Request.Builder.Arg as Arg
import GraphQL.Request.Builder.Variable as Var
{-|
query($searchQuery: String, $pageNumber: Int) {
contacts(search: $searchQuery, page: $pageNumber) {
entries {
... on Contact {
id
firstName
lastName
gender
birthDate
location
phoneNumber
email
headline
picture
}
},
pageNumber,
pageSize,
totalPages,
totalEntries
}
}
-}
fetchContactList : Int -> String -> Request Query ContactList
fetchContactList page search =
let
pageNumber =
Arg.variable (Var.required "pageNumber" .pageNumber Var.int)
searchQuery =
Arg.variable (Var.required "searchQuery" .searchQuery Var.string)
contactsField =
field
"contacts"
[ ( "page", pageNumber ), ( "search", searchQuery ) ]
contactListSpec
params =
{ pageNumber = page
, searchQuery = search
}
in
contactsField
|> Builder.extract
|> Builder.queryDocument
|> Builder.request params
contactListSpec : ValueSpec NonNull ObjectType ContactList vars
contactListSpec =
let
contact =
(Builder.extract
(Builder.assume
(Builder.inlineFragment
(Just (onType "Contact"))
Contact.Request.contactSpec
)
)
)
in
ContactList
|> object
|> with (field "entries" [] (list contact))
|> with (field "pageNumber" [] int)
|> with (field "totalEntries" [] int)
|> with (field "totalPages" [] int)
defmodule PhoenixAndElmWeb.Schema.Types do
@moduledoc false
use Absinthe.Schema.Notation
alias PhoenixAndElm.AddressBook.Contact
import_types(Absinthe.Type.Custom)
@desc "A paginated set of entries from a database"
union :entries do
@desc "Union object for all paginated things."
types([:contact])
resolve_type(fn %Contact{}, _ -> :contact end)
end
@desc "A set of paginated items, including pagination metadata"
object :paginated do
@desc "The total number of entries"
field(:total_entries, :integer)
@desc "The total number of paginated pages"
field(:total_pages, :integer)
@desc "The current page number"
field(:page_number, :integer)
@desc "The number of paginated items per page"
field(:page_size, :integer)
@desc "The list of paginated items"
field(:entries, list_of(:entries))
end
@desc "An address book contact"
object :contact do
@desc "Contact identifier"
field(:id, :integer)
@desc "Contact first name"
field(:first_name, :string)
@desc "Contact last name"
field(:last_name, :string)
@desc "Contact gender"
field(:gender, :integer)
@desc "Contact birth date"
field(:birth_date, :date)
@desc "Contact current location"
field(:location, :string)
@desc "Contact phone number"
field(:phone_number, :string)
@desc "Contact email"
field(:email, :string)
@desc "Contact headline"
field(:headline, :string)
@desc "Contact picture"
field(:picture, :string)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment