MVCs, SQLs, APIs…oh my!

Integrating a simple API into your Rails app

Step into the tech world and prepare to be inundated with acronyms. Half of your daily conversations will be conducted in 3–4 letter bursts: DOM, MVC, SQL, CSS, HTML, and the list goes on. One of the most beloved, and at the same time, feared, acronyms is API. Beloved because an API can bring added functionality to your program…feared because it can bring added headaches and sleepless nights to your program as well.

So what is an API?

from https://www.howtogeek.com/343877/what-is-an-api/

The acronym itself stand for Application Programming Interface. In the broadest sense, an API is the way in which a client interacts with an application. It allows programs to interact with other programs without having to know (or even understand completely) what specific implementations are going on behind the scenes. One of the most common types of metaphors for an API is restaurant-related: when you are given a menu at a restaurant, you are presented with a variety of information about food and drink options, including things like names and descriptions. You can pick and choose your options, provide the requests for those options, the kitchen receives those requests, expends all the effort in making those options, and provides you with the final product. You do not have to know each step that went into making your options. Similarly, you can make requests to an API and get back data that you can use in your own application without necessarily knowing how that data was built. One of the enormous benefits of using an API, for developers at every level of the professional ladder, is a reduction in the amount of code that needs to be created for a particular app. APIs ensure that developers do not constantly have to reinvent the wheel for a number of operations, from creating dialogue boxes, to embedding web browsers, to fingerprint authentication and so on.

Because of the ubiquity and usefulness of APIs, I thought it would be a good idea to tackle integrating one into my Rails project for Flatiron School, the coding bootcamp that I am attending. Thankfully, my partner agreed. I also really wanted to try my hand at using an API because, frankly, I was terrified of it and knew that the longer I put it off, the more painful it would be to learn down the road.

While I definitely encourage people to face their fears (in coding and in life), I am a CALCULATED risk taker and decided to work with a fairly friendly API…the Google API for books, found at:

https://www.googleapis.com/books/v1/volumes?q=search+terms

(I had also seen this API used earlier in the bootcamp, so I had a general idea of how the data was formatted).

Before we write any bit of code to process a response from an API, we obviously need a way to make an actual request to an API. Because I am working with a Rails app, I went to my Gemfile and included the gem “rest_client”. This isn’t the only gem that can be used for making requests to an API (httparty and excon are two others), but it is the one that I had been introduced to early on in the bootcamp(thanks Eric!), so that’s what I stuck with.

Place this in your Gemfile

Obviously, since I said we are working with the Google API for BOOKS, our app is going to be book-related. It’s a simple app where users can search for books by title, write reviews of books, see other users’ reviews about books, and create a list of favorite authors…just your run-of-the mill Rails CRUD app using RESTful routes. It was our idea to have the users of our app query the Google books API directly through our app and then be able to save the results to our database to work with those results….which meant we needed some kind of search form. In the views/books/index.html.erb file (though this can go anywhere you want the search to show up), I created a form_with that looked like this:

views/books/index.html.erb

The path specified on line 1 is the views/books/search.html.path, which calls on the search action in the Books Controller (we’ll get to that in a second)…which is where the search results will be displayed. Again, you can make this whatever works for your app. When you run the server and go to the index page, this is what you see:

Fire up local host and this is what you see on /books

Before getting to the Controller and writing the meat-and-potatoes of the code to process the query, I went into config/routes.rb to create the paths necessary to display the results.

config/routes.rb

Ok, so now in the Books Controller (app/controllers/books_controller.rb).

class BooksController < ApplicationControllerdef index
@books = Book.all
end
def show
@book = Book.find(params[:id])
end
def search
@books = find_book(params[:title])
books.each do |book_hash|
book_title = book_hash["volumeInfo"]["title"]
book_author = book_hash["volumeInfo"]["authors"]
Book.save_it(book_title, book_author)
end
end

private
def find_book(title)
url = "https://www.googleapis.com/books/v1/volumes?q=#{(params[:title])}"
restClientResponseObject = RestClient.get(url)
jsonButItsAString = restClientResponseObject.body
workable_hash = JSON.parse(jsonButItsAString)
end
end

The way to query the Google books API is fairly straightforward and unique to this API…so while it can’t be easily generalized to other APIs, it’s still a useful exercise to ease into API work. In any case, for the Google books API, your search term follows the ‘q’ in the url…which makes the search easily customizable with some kind of user input. That form_with that I made above, in the index.html.erb file, takes in the user input of a ‘title”…and it is this input, using params[:title], that I passed in as an argument to my find_book helper method, which was responsible for turning the response from the API into something workable.

Let’s look at that find_book helper method. To remind you, we’re using the rest-client gem to interact with the API. The class method .get allows you to pass in a url to which rest client makes a request, and the return value of that request is information sent back by the API. I saved that information as the variable restClientResponseObject. That information is not incredibly useful, so we call .body on it but that still doesn’t make things incredibly useful…resClientResponseObject.body (saved as the variable jsonButItsAString) is what a web browser is accustomed to seeing, but it’s a string (hence the name). The problem with a string is that there isn’t a convenient way to manipulate the information…certainly we don’t have an easy way to access the key, value pairs that we want to work with. Thankfully Ruby has a built in class called JSON, which has a method called .parse that can take in a response.body and return a hash that now is much easier to work with.

A workable hash.

Finally. the .save_it method that is called on the Book class was defined under the Book model. This allowed us to actually save the results of our search to our database.

app/models/book.rb

And voila! The final product on local host looks like this:

Fire up that local host and do a search…after following the steps above, this is where you’re taken to.

Obviously, more can be done with this structure…exactly what you do with it depends on what you want to achieve with your app.

I want to thank my coding partner, Melody Soriano, and one of the many fantastic instructors at Flatiron School, Eric Kim, for the wonderful explanation of rest-client and APIs.

Resources: