Skip to content

Resources DSL

Generate a resource for an existing model:

Terminal window
rails generate quail:resource Article

Or write one by hand in app/graphql/resources/:

class ArticleResource
include Quail::Resource
attributes :id, :title, :body, :published_at
has_many :comments
belongs_to :author
writable_attributes :title, :body
end

That single file gives you:

  • A ArticleType GraphQL type with all declared fields and associations
  • article(id: ID!) and articles queries (with Relay connection pagination)
  • articleCreate, articleUpdate, articleDelete mutations
  • Writable attributes scoped to only what you allow
Terminal window
rails generate quail:resource Article \
--attributes=id title body \
--skip-mutations=delete \
--subscribe-on=create update
class ArticleResource
include Quail::Resource
attributes :id, :title
has_many :comments
has_one :featured_image
belongs_to :author, resource: AuthorResource
end

Associations resolve through the Quail resource registry. If a resource exists for the associated model, the type is wired up automatically.

Rails polymorphic belongs_to associations are supported. Since GraphQL requires a concrete type, you declare the possible resource types explicitly and Quail generates a union type:

class CommentResource
include Quail::Resource
attributes :id, :body
belongs_to :commentable, polymorphic: { types: [PostResource, ImageResource] }
end

This generates a CommentableUnion GraphQL union type that resolves to PostType or ImageType at runtime based on the record’s commentable_type column. You can customize the union name:

belongs_to :commentable, polymorphic: {
types: [PostResource, ImageResource],
union_name: "CommentableTarget"
}

Delegated types work without any special configuration since each delegate maps to a concrete ActiveRecord class.

class ArticleResource
include Quail::Resource
attributes :id, :title
attribute :excerpt, type: GraphQL::Types::String, null: true do |article|
article.body&.truncate(200)
end
end