Skip to content

Queries

class ArticleResource
include Quail::Resource
attributes :id, :title
skip_queries :list # only expose find, not the collection
end

Override a query with a custom resolver:

class ArticleResource
include Quail::Resource
attributes :id, :title, :body
skip_queries :list
end
app/graphql/queries/search_articles.rb
class SearchArticles < Quail::Query
type [:article], null: false
argument :term, String, required: true
def resolve(term:)
Article.where("title ILIKE ?", "%#{term}%")
end
end

Quail::Query supports symbol-based type references — :article resolves to ArticleResource.graphql_type automatically. Classes in app/graphql/queries/ that inherit from Quail::Query are discovered and added to the schema.

By default, type [:article] returns a plain array. If you want Relay-style cursor pagination on a custom query, pass connection: true to return a connection type instead:

app/graphql/queries/my_articles.rb
class MyArticles < Quail::Query
type :article, connection: true, null: false
def resolve
context[:current_user].articles.order(created_at: :desc)
end
end

This exposes the query with first, after, before, and last arguments and returns an ArticleTypeConnection with edges, nodes, and pageInfo — the same connection type that Quail auto-generates for resource list queries. Return an ActiveRecord relation from resolve and graphql-ruby handles the cursor slicing automatically.

A typical client query looks like:

query MyArticles($first: Int!, $after: String) {
myArticles(first: $first, after: $after) {
edges {
cursor
node {
id
title
}
}
pageInfo {
endCursor
hasNextPage
}
}
}

Use connection: true whenever a query could return a large or unbounded result set. Plain array types (type [:article]) are still fine for small, bounded collections.

The Quail railtie registers app/graphql/resources/, app/graphql/queries/, app/graphql/mutations/, and app/graphql/subscriptions/ as Zeitwerk autoload roots. This means classes in those directories must be top-level — do not wrap them in a Queries::, Mutations::, Subscriptions::, or Resources:: module.

For example, app/graphql/queries/search_articles.rb should define SearchArticles, not Queries::SearchArticles. The app/graphql/types/ directory is excluded from this and retains the Types:: namespace as usual.