LearnIt's Time To HTTParty!

Treehouse
writes on July 7, 2011

When you’re developing with Ruby, it’s pretty inevitable that at some point you come across an HTTP API that doesn’t have a gem available. While writing Hopefully Sunny I ran into just that situation with World Weather Online’s weather API. It’s often really tempting to go searching for a different API to use instead, but it’s actually not so hard to just write your own wrapper library. Let’s take a look at one of my favorite libraries for working with HTTP APIs, HTTParty, and in the process we’ll figure out how to write our own simple API wrapper libraries.

Getting Set Up

You’re using Bundler, right? If so, it’s a piece of cake to get started with HTTParty. Just add gem httparty to your Gemfile, run bundle from the command line, and you’re on your way. If you want more info about Bundler, they’ve got a great site with all sorts of helpful information about how to get up and running at http://gembundler.com.

If you’re not using Bundler, you can run gem install httparty to get HTTParty installed. You’ll want to add require 'httparty' where appropriate to include it into your scripts.

Really Basic Integration

At its core, HTTParty encapsulates HTTP. The HTTParty module exposes all of the normal HTTP request methods, like GET, POST, PUT, and DELETE. So, for example, you can make a GET request to a URL with the following code:

response =
  HTTParty.get("http://rubygems.org/api/v1/versions/httparty.json")

The URL that we’re accessing above is from the RubyGems API, and will return a bit of JSON representing the versions of the httparty gem, as an array of objects containing information about each version. Here’s a sample of what that JSON looks like:

[
  {
    "number":"0.7.8",
    "built_at":"2011-06-07T00:00:00Z",
    "prerelease":false,
    "downloads_count":22720,
    ...
  },
  ...
]

The object returned from HTTParty.get is an HTTParty::Response object containing the JSON that was returned from the site, along with its headers and other methods relating to the HTTP protocol, like the protocol version. One of the coolest features of HTTParty is that it automatically parses JSON and XML responses, based on the Content-Type of the response, so as soon as your response comes back it’s ready for you to work with it:

puts response[0]["number"]

> 0.7.8

If I’m integrating with something really simple, where really all I need is to GET or POST to a url and work with the response, this is usually the technique that I use. I went with this basic strategy when writing my World Weather Online code for Hopefully Sunny, because I really only had one API call that I needed to access with their service. That’s not normally the case, though, so HTTParty also makes it really easy to wrap your APIs in classes.

Wrapping The Entity In A Class

Let’s continue writing a library against the RubyGems API. If we’re going to look at versions we should probably also be able to look at the base details for any particular RubyGem, like its name and authors, and then it will probably be helpful to look up the versions directly from that result. We’ll wrap all of this functionality into a RemoteGem class.

class RemoteGem
  include HTTParty

  base_uri "rubygems.org/api/v1"

  attr_accessor :name, :info, :version, :authors, :downloads

  def initialize(name, info, version, authors, downloads)
    self.name = name
    self.info = info
    self.version = version
    self.authors = authors
    self.downloads = downloads
  end

  # Returns the versions for this particular RemoteGem
  def versions
    response = self.class.get("/versions/#{name}.json")
    if response.success?
      response
    else
      raise response.response
    end
  end

  # Find a particular gem, based on its name
  def self.find(name)
    response = get("/gems/#{name}.json")
    if response.success?
      self.new(response["name"], response["info"], response["version"],
         response["authors"], response["downloads"])
    else
      # this just raises the net/http response that was raised
      raise response.response
    end
  end
end

This gives us a RemoteGem class with a find method that will let us find gems by name. Once a gem is loaded we can also get an array of its versions by calling the versions method. Here’s a quick example of using the wrapper class:

httparty = RemoteGem.find("httparty")
puts httparty

> 

’’

’’’

’’’’’’

“'”

©