HandbookOther integrationsSubservice languagesRuby

Ruby subservices

This example demonstrates Ruby subservices within a stitched schema. Their GraphQL implementations use:

Local setup

Clone the GitHub repo.

cd examples/subservice-languages/ruby
bundle install
 
yarn install
yarn start-services

Then in a new terminal tab:

yarn start-gateway

The following services are available for interactive queries:

Summary

Try fetching some data:

query {
  users(ids: ["1", "2"]) {
    id
    name
    username
    reviews {
      body
      product {
        name
      }
    }
  }
}

Unique to this example is that the subservices are Ruby applications. Their GraphQL implementations use graphql-ruby paired with graphql-ruby-schema-directives to generate schema stitching SDLs.

This example demonstrates both schemas built with a code-first approach (as Ruby classes), and by parsing a type definitions string into a schema. Either approach works fine for providing an annotated SDL to schema stitching.

Class-based schemas

The Accounts and Review services are implemented using class-based schema definitions:

class BaseField < GraphQL::Schema::Field
  include GraphQL::SchemaDirectives::Field
end
 
class BaseObject < GraphQL::Schema::Object
  include GraphQL::SchemaDirectives::Object
  field_class BaseField
end
 
class User < BaseObject
  add_directive :key, { selectionSet: '{ id }' }
 
  field :id, ID, null: false
  field :name, String, null: true
  field :username, String, null: true
end
 
class Query < BaseObject
  field :users, [User, null: true], null: false, directives: { merge: { keyField: 'id' } } do
    argument :ids, [ID], required: true
  end
  field :_sdl, String, null: false
end

The GraphQL::SchemaDirectives gem provides API extensions for applying custom schema directives to types and fields.

Schemas from type definitions

The Products service is implemented with a parsed type definitions string:

type_defs = %(
  type Product @key(selectionSet: "{ upc }") {
    upc: String!
    name: String
    price: Int
    weight: Int
  }
 
  type Query {
    products(upcs: [ID!]!): [Product]! @merge(keyField: "upc")
    _sdl: String!
  }
)
 
schema = GraphQL::SchemaDirectives.from_definition(type_defs, default_resolve: ...)

You’ll need to build your own default resolver for this approach. It’s more of a self-service effort, although you remain in control of the complete resolution process.