Quantcast
Channel: Ruby – My Programming Blog
Viewing all articles
Browse latest Browse all 12

Tutorial: How to get data from external API ? PART 2: Sending Request, Parsing Output [Ruby, JSON, REST]

$
0
0

Here we are with Part 2 of our tutorial. Who missed the first part – it’s here. Also if you missed it please take a look at the Github Movies-CLI app, which I am taking my examples from.

In this part we will discuss two things:

1. Making HTTP request to the API Path
2. Parsing response

I know your time is precious so lets start.

 Making HTTP request to the API Path

By this time you should already have all  your  API configurations loaded into @config of RottenTomatoes::API class, if they are not please check out Part 1 .

To send request to the third party API (RottenTomatoes in our case) we will need to use a gem. I am using  RestClient gem. (Note: You can if you want use net/http built in Ruby functionality, but I find RestClient easier to use).

In regards to gem installation – of course you can manually install gem but I prefer to use a Gemfile.

After installing you will need to require RestClient with:


require 'restclient'

Now all we need to do is put together our configuration into a URL, that RestClient will call.

I am doing this within a separate method:

# Constructs base url used for API calls from api_paths configuraiton file
#
# @return [String] base url
  def base_url
	if @config.has_key?('rottentomatoes')
	  @config['rottentomatoes']['protocol'] + @config['rottentomatoes']['host'] + @config['rottentomatoes']['api_path']
	else
	  raise StandardError, 'api_paths.yml must have rottentomatoes information such as host, protocol and api_path'
	 end
  end

This method is pretty straightforward. It can be enhanced to check if @config has every part of the URL,or you can even create ‘initializer’ that won’t even go to this method if @config is not fully populated with information, but for the purpose of this tutorial I left it straightforward.

So we check if there is ‘rottentomatoes’ key in the @config, and if there is we build URL, otherwise we raise an exception.

Now lets go to the part where we call this URL:

# Receives String, makes call to RottenTomatoes and returns JSON object with movies information from RottenTomatoes
#
# @param [String] title movie title to get more info about
#
# @return [HashMap] JSON with movie information
def get_movie_by_title(title)
# using RestClient make call to restful API with api_ley title and max_movies_per_output
  RestClient.get(base_url,
    {:params =>
      {
        :apikey => @config['rottentomatoes']['api_key'],
        :q => title,
        :page_limit => @config['rottentomatoes']['max_movies_per_output']
      }
  # act on response result
   }) { |response, request, result, &block|
      case response.code
      # if success connection start acting on result
	when 200
	  json_result = JSON.parse(response.body)
	  if json_result.has_key?('movies')
	    put_json_into_movie_obj(json_result['movies'])
	  end
      # if not succesfull just raise an exception
	else
	  raise StandardError, "Cannot connect to RottenTomatoes API, please check config/api_paths.yml for valid api_key"
	end
  }
end

The sole purpose of this method is to call the RottenTomatoes API based on the ‘title’ passed to this method. I am using RestClient.get because current API path expects GET Http request. I am using base_url that we seen earlier and 3 parameters, two of which are taken from the @config and one supplied by user.

So my URL looks the same the an example we seen in RottenTomatoes docs :

 http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[your_api_key]&q=Toy+Story+3&page_limit=1

Parsing response

After sending request via RestClient, I am checking response.code, if it is not 200 which means successful with body, I am raising an exceptions, otherwise I use built in Ruby JSON functionality to parse JSON object I receive back and call my own function

 put_json_into_movie_obj(json_result['movies'])

to put information from JSON into my custom class RottenTomatoes::Movie .

Note: JSON.parse allows to transform response.body which is string into a JSON string which allows access to different its parts (HashMap).

Last Part of this equation is:


private

  # Puts JSON object into a RottenTomatoes::Movie object
  # @param [HashMap] movie_json JSON object with movie information
  #
  # @return [Array] array of RottenTomatoes::Movie objects
  def put_json_into_movie_obj(movie_json)
    movie_json.map { |movie| RottenTomatoes::Movie.new(movie['id'], movie['year'], movie['gernes'],																												 
                                                       movie['title'], movie['release_dates'], movie['ratings'],																											
                                                       movie['synopsis'], movie['posters'], movie['abridged_cast'],																												  
                                                       movie['runtime']) }
  end

This piece of code is super straightforward, what it does it maps and saves different parts of JSON into RottenTomatoes::Movie .

After this we have our RottenTomatoes::Movie, populated with information from RottenTomatoes API, and we can do anything we want with it!

Pretty straightforward right ?

In the next tutorial I will show you how to prettify your command line output and show your movie information.

If you can’t wait just:

1. pull movie-cli app
2. rename config file from ‘.sample’ to ‘.yml’
3. put your api_key’ into config
4. in movie-cli do bundle update
5. run ruby movie_info.rb ‘Unbroken’

That’s it. You want to call another API ? Create new entry into config, get your API Key, modify RottenTomatoes::API class to parse information you want – and you are good to go.

If you have any questions regarding this, put it in the comments or shoot me an email!

Thanks for reading!

Anatoly


Tagged: api, call API, external API, parse API, RESTfull, Ruby

Viewing all articles
Browse latest Browse all 12

Trending Articles