Queries
Controlling Queries
Section titled “Controlling Queries”class ArticleResource include Quail::Resource
attributes :id, :title
skip_queries :list # only expose find, not the collectionendCustom Query Override
Section titled “Custom Query Override”Override a query with a custom resolver:
class ArticleResource include Quail::Resource
attributes :id, :title, :body
skip_queries :listendclass SearchArticles < Quail::Query type [:article], null: false
argument :term, String, required: true
def resolve(term:) Article.where("title ILIKE ?", "%#{term}%") endendQuail::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.
Connection Types (Cursor Pagination)
Section titled “Connection Types (Cursor Pagination)”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:
class MyArticles < Quail::Query type :article, connection: true, null: false
def resolve context[:current_user].articles.order(created_at: :desc) endendThis 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.
Autoloading
Section titled “Autoloading”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.