Geek Culture
Published in

Geek Culture

With GraphQL you can query a single endpoint and get back exactly the data you need. Nothing more, nothing less. Sounds nice right? It gets better! If you are currently consuming a regular ‘ol REST API and they also happen to have a GraphQL API available, you can massively reduce the amount of data being requested and speed up your application. I’m sure that the lower data usage would also be a welcome change, especially if you are developing for mobile.

In my current project, I use the Yelp API pretty heavily. Well, it turns out that Yelp also offers a GraphQL API. After doing a little research and seeing the benefits of using GraphQL, I have decided to do a little refactoring on my project. My goal is to utilize the Yelp GraphQL API and return only the information that I need for a faster and less data intensive application. I want to accomplish this as simply as possible without the use of libraries like graphql-client.

Let’s get started!

In my application, I am querying the Yelp API search endpoint for restaurants near the user’s location. Here is what the response for one restaurant looks like 👇

{"id"=>"5XGfUuqGZXud1sHAhitOEA",
"alias"=>"ellijay-coffeehouse-ellijay-3",
"name"=>"Ellijay Coffeehouse",
"image_url"=>"https://s3- media4.fl.yelpcdn.com/bphoto/SLHqFW1C9abqp5gJNepnzQ/o.jpg",
"is_closed"=>false,
"url"=>"https://www.yelp.com/biz/ellijay-coffeehouse-ellijay-3?adjust_creative=rkr10mVcIwdrPCTR1lAhwA&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=rkr10mVcIwdrPCTR1lAhwA",
"review_count"=>137,
"categories"=>
[{"alias"=>"coffee", "title"=>"Coffee & Tea"},
{"alias"=>"breakfast_brunch", "title"=>"Breakfast & Brunch"},
{"alias"=>"juicebars", "title"=>"Juice Bars & Smoothies"}],
"rating"=>4.5,
"coordinates"=>{"latitude"=>34.6961891549605, "longitude"=>-84.4807845952454},
"transactions"=>[],
"price"=>"$$",
"location"=>
{"address1"=>"131 N Main St",
"address2"=>"",
"address3"=>"",
"city"=>"Ellijay",
"zip_code"=>"30540",
"country"=>"US",
"state"=>"GA",
"display_address"=>["131 N Main St", "Ellijay, GA 30540"]},
"phone"=>"+17066355565",
"display_phone"=>"(706) 635-5565",
"distance"=>2036.765952031534}
}

Lots of good info, but I don’t really need ALL of this information.

Lets take a look at GraphQL. A GraphQL query looks something like this.

{
search(location: "san francisco", limit: 1) {
business {
name
}
}
}

And this query’s response…

{
"data": {
"search": {
"business": [
{
"name": "Bi-Rite Creamery"
}
]
}
}
}

With GraphQL, we have access to all of the same information as we would with the REST API, but we specify in the query what we want retuned and that is exactly what we get. In this case, we are just returning the name of a single business in San Francisco. What if you want to get the names of 50 or even 100 businesses? By using GraphQL and only retuning the names, rather than the entire business object, you are consuming significantly less data!

So how do we go about refactoring the application to make GraphQL queries rather than hitting the REST endpoints and returning those huge restaurant objects? Let’s take a look at the current state of the application.

NOTE: I am using the HTTParty gem to make the API calls. I would like to maintain this functionality with GraphQL if possible.

Alright, so let’s tackle location_restaurants first. GraphQL only uses one endpoint, so I guess the first thing we should do is change @search_url . Let’s go ahead and make it a class variable since we will be using the same endpoint for all of our queries from here on out. Let’s also take note of the information we are looking for based on @search_url . It looks like we want the location to be the user’s location, category should be “restaurants”, limit is 20 and we want to sort by “best_match”. We will use this information to build our GraphQL query.

Now, let’s add a continent type to the headers just to be sure that the API understands what kind of information we are sending. Let’s also go ahead and move the headers inside of the method while leaving our @@headers class variable, so we don’t break the rest of our API calls. We can abstract the headers back out to a class variable later when we have the rest of the methods refactored to use GraphQL.

Now, with GraphQL, we use a POST request rather than a GET request, and we need to declare the query in the body of the request. So let’s change the request type, decide what information we need and build out the body.

Alright, so I think this would be a good place to use a heredoc. This way we keep the formatting and we can use string interpolation to pass in the location. We know from the notes we made earlier what our location, categories, limit and sort_by are going to look like and, based on the information we are using in our application, it looks like we want to grab the id, name, price, rating, address, categories, phone number, yelp url, and review count. We also want to know whether or not the restaurant is currently closed.

NOTE: We can build a test query in Yelps GraphQL docs. Then we just copy and paste our working query into the heredoc.

IT WORKS!

We are now querying the Yelp GraphQL API and getting back exactly the information we need! We will make a very similar query in the katchup_restaurants method, so let’s just clean things up a bit and make our query re-useable. We will just take out the chunk that we will need in our other methods and abstract it out into a class variable. We will use another heredoc to maintain formatting.

Much better! Since single is getting a different set of information and will be refactored later, we will leave @@headers alone for the time being.

So, without any libraries, we were able to consume a GraphQl API in Ruby. We are now getting back EXACTLY the information we need. Nothing more Nothing less. I hope this article was informative and gives you a good starting point for refactoring your own API calls. Have fun and Happy coding!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store