Fetching External Data
Introduction
In this lesson, we will learn how to fetch data from external APIs and integrate it with our GraphQL server. This skill is crucial when building real-world applications, as data often resides in different places. By combining GraphQL with external APIs, you can create a more robust and comprehensive data layer in your applications.
Previously, you learned how to handle GraphQL mutations, manage complex queries, and set up real-time subscriptions. This lesson will build on those skills, focusing on fetching external data.
Defining the Schema
A GraphQL schema defines the types and the structure of queries. In Ruby, we define types as classes that inherit from GraphQL::Schema::Object. Here's the schema we'll use in this lesson:
Here, we define a BookType class with fields id, title, and author. Each field is defined using the field method, specifying the field name, type, and whether it can be null.
Next, we define our query type:
In the QueryType class, we define two fields: books and external_books. Each field has a corresponding resolver method that returns the data.
Notice that we define the field in Ruby using snake_case (external_books), which follows Ruby naming conventions. However, graphql-ruby automatically converts snake_case field names to camelCase when exposing them in the GraphQL schema. This means that when clients write queries, they'll use externalBooks (camelCase), even though the Ruby code uses external_books (snake_case). This automatic conversion applies to all field names throughout your schema — you always write Ruby-style snake_case in your code, and clients always use GraphQL-style camelCase in their queries.
Creating Resolvers
Resolvers define how to fetch data for each type in the GraphQL schema. We've learned about resolvers in previous lessons, but here's a quick reminder of their purpose.
In the code above, we've already defined our resolvers as methods within the QueryType class:
- The
booksmethod returns a hardcoded array of book hashes. - The
external_booksmethod performs an HTTP request usingNet::HTTPto get data from an external URL and then parses the JSON response usingJSON.parse.
Let's look at the external_books resolver in more detail:
This method:
- Creates a
URIobject from the external API URL. - Uses
Net::HTTP.getto fetch the data from the URL. - Parses the JSON response using
JSON.parseand returns the result.
Setting Up the GraphQL Schema and Server
Now we need to create our GraphQL schema and set up a Sinatra server to handle requests.
First, let's create our schema:
This schema class ties together our query type and makes it available for execution.
Next, we'll set up our Sinatra server:
This code:
- Sets up a POST endpoint at
/graphqlto handle GraphQL queries. - Parses the incoming JSON request to extract the query and variables.
- Executes the query using our schema.
- Returns the result as JSON.
- Configures the server to run on port
4000.
To start the server, run:
Once running, you should see:
Fetching Data from the Server
To test our server and fetch both local and external book data, we will write a simple Ruby script using Net::HTTP.
This script:
- Defines a GraphQL query to fetch
booksandexternalBooks. Remember, we useexternalBooks(camelCase) here becausegraphql-rubyautomatically exposes the Ruby-sideexternal_booksfield asexternalBooksin the GraphQL schema. - Creates an HTTP POST request to our running server.
- Sends the query in the request body as JSON.
- Parses and pretty-prints the response.
To run the client script:
Execution Output
If everything is set up correctly, running this script should produce an output similar to:
Lesson Summary
In this lesson, you learned how to define a schema using Ruby classes, create resolvers for both local and external data sources, set up a GraphQL server with Sinatra and graphql-ruby, and query the server. Here are the key points:
- Defining GraphQL types as Ruby classes inheriting from
GraphQL::Schema::Object. - Creating resolver methods within query type classes.
- Fetching data from external APIs using
Net::HTTP. - Integrating external APIs into your Sinatra GraphQL server.
- Using Ruby's
JSONmodule for parsing JSON responses. - Understanding that
graphql-rubyautomatically converts snake_case field names (Ruby convention) to camelCase (GraphQL convention) when exposing them in the schema.
Next, you will apply these concepts in hands-on practice exercises. Experiment with querying different external APIs and consolidating your knowledge.
Congratulations on making it this far. You're now well-equipped to handle external data in your GraphQL applications. Keep practicing to master these skills!
