Sunlight Labs API Gem

NOTE: This file is formatted in Textile and best viewed on GitHub.

Description

A little gem that integrates with the Sunlight Labs API. From the official site:

The Sunlight Labs API provides methods for obtaining basic information on Members of Congress, legislator IDs used by various websites, and lookups between places and the politicians that represent them. The primary purpose of the API is to facilitate mashups involving politicians and the various other APIs that are out there.

Full API documentation available here.

Also, the Sunlight gem integrates with the Google Maps API for street address geocoding. Because some zip codes overlap two or more congressional districts, passing in a latitude/longitude will give users the most accurate information. Since it’s highly unlikely a user would know their exact lat/long, the Google Maps API is used to translate a street address string into a lat/long pair.

Installation

The following gems are required:

  • json
  • ym4r

$ sudo gem install json ym4r

Then, install the stable Sunlight gem:

$ sudo gem install sunlight

Or, if you’re adventurous, the latest dev version (which should be quite stable):

$ sudo gem install luigi-sunlight --source=http://gems.github.com

Set Up

First, register for an API key here.

Then, you’ll want to stick the following lines somewhere in your Ruby environment.


  require 'rubygems'
  require 'sunlight'
  include Sunlight
  Sunlight.api_key = 'yourapikeyfromtheurlabove'

If you’re testing this out in IRB, you’ll run them one at a time. If you’re using Rails 2.1, stick them in a file called sunlight.rb in RAILS_ROOT/config/initializers. They’ll load on app startup.

Usage

Now, it’s time to get to the good stuff. The most useful method is Legislator#all_for:


  congresspeople = Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
  senior_senator = congresspeople[:senior_senator]
  junior_senator = congresspeople[:junior_senator]
  representative = congresspeople[:representative]

  junior_senator.firstname          # returns "Hillary" 
  junior_senator.lastname           # returns "Clinton"   
  junior_senator.congress_office    # returns "476 Russell Senate Office Building"
  junior_senator.phone              # returns "202-224-4451"  

Note that you should make the best attempt to get a full street address, as that is geocoded behind the scenes into a lat/long pair. A five-digit zip code alone won’t cut it, as there may be multiple congressional districts in a single zip code (there are ways to deal with this below). If you pass in a zip+4, then you’ll get much better geocoding results.

So Legislator#all_for returns a hash of Legislator objects, and the keys are :senior_senator, :junior_senator, and :representative. Make sure to review all the available fields from the Sunlight Labs API. You can also pass in a lat/long pair:


  congresspeople = Legislator.all_for(:latitude => 33.876145, :longitude => -84.453789)

This bypasses the geocoding necessary by the Google Maps API. For social networks and other applications with a User object, it makes sense to geocode the user’s address up front and save the lat/long data in the local database. Then, use the lat/long pair instead of address, which cuts a substantial bit of time from the Legislator#all_for request since the Google Maps API Geocoding function doesn’t have to be called.

You can also use the Legislator#all_where method for searching based on available fields. You’ll get back an array of Legislator objects:


  johns = Legislator.all_where(:firstname => "John")
  floridians = Legislator.all_where(:state => "FL")
  dudes = Legislator.all_where(:gender => "M")

  johns.each do |john|
    # do stuff
  end

There’s also the District object. District#get takes in either lat/long or an address and does it’s best to return the correct Congressional District:


  district = District.get(:latitude => 33.876145, :longitude => -84.453789)
  district.state            # returns "GA"
  district.number           # returns "6"
  
  district = District.get(:address => "123 Fifth Ave New York, NY") 

Finally, two more methods, District.all_from_zipcode and District.zipcodes_in, help you out when all you have is a five-digit zip code and want to make sure you account for all the districts in a zip code, or if you want to get back all zipcodes in a given district.


  districts = District.all_from_zipcode(90210)    # returns array of District objects
  zipcodes = District.zipcodes_in("NY", "10")     # returns array of zip codes as strings  ["11201", "11202", "11203",...]

License

See the terms of usage for the Sunlight Labs API and the Google Maps API.

Copyright © 2008 by Luigi Montanez under the MIT License.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.