ruby 382 lines · 3 tabs

GraphQL APIs with graphql-ruby gem

Sarah Mitchell Feb 2026
3 tabs
# Gemfile
gem 'graphql'

# Installation
# rails generate graphql:install

# app/graphql/types/user_type.rb
module Types
  class UserType < Types::BaseObject
    field :id, ID, null: false
    field :name, String, null: false
    field :email, String, null: false
    field :bio, String, null: true
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false

    # Association
    field :posts, [Types::PostType], null: false

    # Computed field
    field :posts_count, Integer, null: false do
      description "Total number of posts by user"
    end

    def posts_count
      object.posts.count
    end

    # Field with arguments
    field :recent_posts, [Types::PostType], null: false do
      argument :limit, Integer, required: false, default_value: 10
    end

    def recent_posts(limit:)
      object.posts.order(created_at: :desc).limit(limit)
    end

    # Authorized field
    field :private_data, String, null: true do
      description "Visible only to user themselves"
    end

    def private_data
      return nil unless context[:current_user]&.id == object.id

      object.private_data
    end
  end
end

# app/graphql/types/post_type.rb
module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false
    field :title, String, null: false
    field :content, String, null: false
    field :published, Boolean, null: false
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false

    field :user, Types::UserType, null: false
    field :comments, [Types::CommentType], null: false

    # Custom resolver
    field :excerpt, String, null: false

    def excerpt
      object.content.truncate(100)
    end
  end
end

# app/graphql/types/query_type.rb
module Types
  class QueryType < Types::BaseObject
    # Fetch single user
    field :user, Types::UserType, null: true do
      description "Find a user by ID"
      argument :id, ID, required: true
    end

    def user(id:)
      User.find(id)
    end

    # Fetch all users with filtering
    field :users, [Types::UserType], null: false do
      argument :role, String, required: false
      argument :search, String, required: false
    end

    def users(role: nil, search: nil)
      users = User.all
      users = users.where(role: role) if role.present?
      users = users.where("name ILIKE ?", "%#{search}%") if search.present?
      users
    end

    # Current user
    field :current_user, Types::UserType, null: true

    def current_user
      context[:current_user]
    end

    # Posts with pagination
    field :posts, Types::PostType.connection_type, null: false do
      argument :published_only, Boolean, required: false, default_value: false
    end

    def posts(published_only:)
      posts = Post.all
      posts = posts.where(published: true) if published_only
      posts
    end
  end
end
3 files · ruby Explain with highlit

GraphQL enables clients to request exactly the data they need. The graphql-ruby gem implements GraphQL servers in Rails. Types define data structures—ObjectTypes for models, InputTypes for mutations. Queries fetch data; mutations modify data. Resolvers contain business logic for field resolution. I use GraphQL for flexible APIs—mobile apps request different fields than web. DataLoader batches and caches database queries, preventing N+1s. GraphQL introspection enables GraphiQL playground for testing. Subscriptions push real-time updates via ActionCable. Understanding GraphQL's query language and type system is essential. GraphQL reduces API versioning needs—add fields without breaking clients. Testing uses GraphQL execution with mocked contexts.


Related snips

Share this code

Here's the card — post it anywhere.

GraphQL APIs with graphql-ruby gem — share card
Link copied