Skip to content

Commit

Permalink
geo search, reverse_geocode and place lookup, plus tests
Browse files Browse the repository at this point in the history
  • Loading branch information
stve authored and pengwynn committed Jun 22, 2010
1 parent a731dda commit 0e5aa20
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/twitter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,4 @@ def rubyify_keys!
require File.join(directory, "twitter", "base")
require File.join(directory, "twitter", "search")
require File.join(directory, "twitter", "trends")
require File.join(directory, "twitter", "geo")
25 changes: 25 additions & 0 deletions lib/twitter/geo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Twitter
class Geo
include HTTParty
base_uri "api.twitter.com/#{API_VERSION}/geo"
format :json

def self.place(place_id, query={})
Twitter.mash(get("/id/#{place_id}.json", :query => query))
end

def self.search(query={})
mashup(get("/search.json", :query => query))
end

def self.reverse_geocode(query={})
mashup(get("/reverse_geocode.json", :query => query))
end

private

def self.mashup(response)
response["result"].values.flatten.map{|t| Twitter.mash(t)}
end
end
end
1 change: 1 addition & 0 deletions test/fixtures/geo_place.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"country":"The United States of America","place_type":"neighborhood","country_code":"US","attributes":{"162834:id":"53228"},"contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Charlotte, NC","url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","name":"Charlotte","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]},"id":"512a8a4a4c4b4be0"}],"full_name":"Ballantyne West, Charlotte","url":"http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json","name":"Ballantyne West","geometry":{"type":"Polygon","coordinates":[[[-80.87219316,35.06571702],[-80.86735404,35.065773],[-80.86841388,35.06246001],[-80.86431816,35.06202],[-80.86356792,35.06029803],[-80.860968,35.061246],[-80.85807792,35.06548203],[-80.84569284,35.06514696],[-80.85025296,35.05508298],[-80.84654712,35.04180096],[-80.83437984,35.03659599],[-80.83440684,35.033346],[-80.83791216,35.03078298],[-80.83847808,35.02645101],[-80.846181,35.02217097],[-80.849034,35.02199196],[-80.85131496,35.01486999],[-80.87055516,35.03680002],[-80.86154508,35.04053502],[-80.87618808,35.05916097],[-80.875818,35.060526],[-80.87025816,35.060931],[-80.869662,35.06253102],[-80.87219316,35.06571702]]]},"polylines":["ww_uEdjrlNIg]tSrEvAqXvIuC}DgOmYaQ`AmlA|}@n[~qAcVn_@akAhSD`OzT`ZpBvYbo@b@xPnk@fMahChwBkViw@ksBnzAqGiAoAwa@_IwB}RxN"],"bounding_box":{"type":"Polygon","coordinates":[[[-80.87618808,35.01486999],[-80.83437984,35.01486999],[-80.83437984,35.065773],[-80.87618808,35.065773]]]},"id":"ea76a36c5bc2bdff"}
1 change: 1 addition & 0 deletions test/fixtures/geo_reverse_geocode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"neighborhood","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Charlotte, NC","url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","name":"Charlotte","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]},"id":"512a8a4a4c4b4be0"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json","full_name":"Ballantyne West, Charlotte","name":"Ballantyne West","id":"ea76a36c5bc2bdff","bounding_box":{"type":"Polygon","coordinates":[[[-80.87618808,35.01486999],[-80.83437984,35.01486999],[-80.83437984,35.065773],[-80.87618808,35.065773]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"North Carolina, US","url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","name":"North Carolina","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]},"id":"3b98b02fba3f9753"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","full_name":"Charlotte, NC","name":"Charlotte","id":"512a8a4a4c4b4be0","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]}},{"country":"The United States of America","place_type":"admin","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"country","country_code":"US","attributes":{},"full_name":"The United States of America","url":"http://api.twitter.com/1/geo/id/96683cc9126741d1.json","name":"The United States of America","bounding_box":null,"id":"96683cc9126741d1"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","full_name":"North Carolina, US","name":"North Carolina","id":"3b98b02fba3f9753","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]}},{"country":"The United States of America","place_type":"country","country_code":"US","contained_within":[],"attributes":{},"url":"http://api.twitter.com/1/geo/id/96683cc9126741d1.json","full_name":"The United States of America","name":"The United States of America","id":"96683cc9126741d1","bounding_box":null}]},"query":{"type":"reverse_geocode","url":"http://api.twitter.com/1/geo/reverse_geocode.json?granularity=neighborhood&accuracy=0&long=-80.854568&lat=35.061161","params":{"granularity":"neighborhood","accuracy":0,"coordinates":{"type":"Point","coordinates":[-80.854568,35.061161]}}}}
1 change: 1 addition & 0 deletions test/fixtures/geo_reverse_geocode_granularity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"North Carolina, US","url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","name":"North Carolina","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]},"id":"3b98b02fba3f9753"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","full_name":"Charlotte, NC","name":"Charlotte","id":"512a8a4a4c4b4be0","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]}},{"country":"The United States of America","place_type":"admin","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"country","country_code":"US","attributes":{},"full_name":"The United States of America","url":"http://api.twitter.com/1/geo/id/96683cc9126741d1.json","name":"The United States of America","bounding_box":null,"id":"96683cc9126741d1"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","full_name":"North Carolina, US","name":"North Carolina","id":"3b98b02fba3f9753","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]}},{"country":"The United States of America","place_type":"country","country_code":"US","contained_within":[],"attributes":{},"url":"http://api.twitter.com/1/geo/id/96683cc9126741d1.json","full_name":"The United States of America","name":"The United States of America","id":"96683cc9126741d1","bounding_box":null}]},"query":{"type":"reverse_geocode","url":"http://api.twitter.com/1/geo/reverse_geocode.json?granularity=city&accuracy=0&long=-80.854568&lat=35.061161","params":{"granularity":"city","accuracy":0,"coordinates":{"type":"Point","coordinates":[-80.854568,35.061161]}}}}
1 change: 1 addition & 0 deletions test/fixtures/geo_reverse_geocode_limit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"neighborhood","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Charlotte, NC","url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","name":"Charlotte","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]},"id":"512a8a4a4c4b4be0"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json","full_name":"Ballantyne West, Charlotte","name":"Ballantyne West","id":"ea76a36c5bc2bdff","bounding_box":{"type":"Polygon","coordinates":[[[-80.87618808,35.01486999],[-80.83437984,35.01486999],[-80.83437984,35.065773],[-80.87618808,35.065773]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"North Carolina, US","url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","name":"North Carolina","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]},"id":"3b98b02fba3f9753"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","full_name":"Charlotte, NC","name":"Charlotte","id":"512a8a4a4c4b4be0","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]}}]},"query":{"type":"reverse_geocode","url":"http://api.twitter.com/1/geo/reverse_geocode.json?granularity=neighborhood&accuracy=0&long=-80.854568&lat=35.061161","params":{"granularity":"neighborhood","accuracy":0,"coordinates":{"type":"Point","coordinates":[-80.854568,35.061161]}}}}
1 change: 1 addition & 0 deletions test/fixtures/geo_search.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"neighborhood","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Charlotte, NC","url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","name":"Charlotte","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]},"id":"512a8a4a4c4b4be0"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json","full_name":"Ballantyne West, Charlotte","name":"Ballantyne West","id":"ea76a36c5bc2bdff","bounding_box":{"type":"Polygon","coordinates":[[[-80.87618808,35.01486999],[-80.83437984,35.01486999],[-80.83437984,35.065773],[-80.87618808,35.065773]]]}},{"country":"The United States of America","place_type":"neighborhood","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Charlotte, NC","url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","name":"Charlotte","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]},"id":"512a8a4a4c4b4be0"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/0f2ebc6cdab74561.json","full_name":"Whiteoak, Charlotte","name":"Whiteoak","id":"0f2ebc6cdab74561","bounding_box":{"type":"Polygon","coordinates":[[[-80.85807792,35.06373603],[-80.82110592,35.06373603],[-80.82110592,35.07697602],[-80.85807792,35.07697602]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"North Carolina, US","url":"http://api.twitter.com/1/geo/id/3b98b02fba3f9753.json","name":"North Carolina","bounding_box":{"type":"Polygon","coordinates":[[[-84.321869,33.752878],[-75.400119,33.752878],[-75.400119,36.588157],[-84.321869,36.588157]]]},"id":"3b98b02fba3f9753"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/512a8a4a4c4b4be0.json","full_name":"Charlotte, NC","name":"Charlotte","id":"512a8a4a4c4b4be0","bounding_box":{"type":"Polygon","coordinates":[[[-81.001923,35.021524],[-80.670104,35.021524],[-80.670104,35.385542],[-81.001923,35.385542]]]}}]},"query":{"type":"search","url":"http://api.twitter.com/1/geo/search.json?granularity=neighborhood&accuracy=0&query=&long=-80.854568&autocomplete=false&lat=35.061161","params":{"granularity":"neighborhood","query":"","accuracy":0,"coordinates":{"type":"Point","coordinates":[-80.854568,35.061161]},"autocomplete":false}}}
1 change: 1 addition & 0 deletions test/fixtures/geo_search_ip_address.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"California, US","url":"http://api.twitter.com/1/geo/id/fbd6d2f5a4e4a15e.json","name":"California","bounding_box":{"type":"Polygon","coordinates":[[[-124.482003,32.528832],[-114.131211,32.528832],[-114.131211,42.009517],[-124.482003,42.009517]]]},"id":"fbd6d2f5a4e4a15e"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/b19a2cc5134b7e0a.json","full_name":"Mountain View, CA","name":"Mountain View","id":"b19a2cc5134b7e0a","bounding_box":{"type":"Polygon","coordinates":[[[-122.117852,37.35676],[-122.044473,37.35676],[-122.044473,37.469887],[-122.117852,37.469887]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"California, US","url":"http://api.twitter.com/1/geo/id/fbd6d2f5a4e4a15e.json","name":"California","bounding_box":{"type":"Polygon","coordinates":[[[-124.482003,32.528832],[-114.131211,32.528832],[-114.131211,42.009517],[-124.482003,42.009517]]]},"id":"fbd6d2f5a4e4a15e"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/45cadd6ef118ec9f.json","full_name":"Sunnyvale, CA","name":"Sunnyvale","id":"45cadd6ef118ec9f","bounding_box":{"type":"Polygon","coordinates":[[[-122.065265,37.329895],[-121.98242,37.329895],[-121.98242,37.464087],[-122.065265,37.464087]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"California, US","url":"http://api.twitter.com/1/geo/id/fbd6d2f5a4e4a15e.json","name":"California","bounding_box":{"type":"Polygon","coordinates":[[[-124.482003,32.528832],[-114.131211,32.528832],[-114.131211,42.009517],[-124.482003,42.009517]]]},"id":"fbd6d2f5a4e4a15e"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/7d62cffe6f98f349.json","full_name":"San Jose, CA","name":"San Jose","id":"7d62cffe6f98f349","bounding_box":{"type":"Polygon","coordinates":[[[-122.045572,37.124503],[-121.589153,37.124503],[-121.589153,37.469163],[-122.045572,37.469163]]]}},{"country":"The United States of America","place_type":"city","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"admin","country_code":"US","attributes":{},"full_name":"California, US","url":"http://api.twitter.com/1/geo/id/fbd6d2f5a4e4a15e.json","name":"California","bounding_box":{"type":"Polygon","coordinates":[[[-124.482003,32.528832],[-114.131211,32.528832],[-114.131211,42.009517],[-124.482003,42.009517]]]},"id":"fbd6d2f5a4e4a15e"}],"attributes":{},"url":"http://api.twitter.com/1/geo/id/30344aecffe6a491.json","full_name":"Fremont, CA","name":"Fremont","id":"30344aecffe6a491","bounding_box":{"type":"Polygon","coordinates":[[[-122.149175,37.454389],[-121.867979,37.454389],[-121.867979,37.604624],[-122.149175,37.604624]]]}}]},"query":{"type":"search","url":"http://api.twitter.com/1/geo/search.json?granularity=neighborhood&accuracy=0&query=&ip=74.125.19.104&autocomplete=false","params":{"granularity":"neighborhood","query":"","accuracy":0,"ip":"74.125.19.104","autocomplete":false}}}
1 change: 1 addition & 0 deletions test/fixtures/geo_search_query.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"places":[{"country":"The United States of America","place_type":"poi","country_code":"US","contained_within":[{"country":"The United States of America","place_type":"city","country_code":"US","attributes":{},"full_name":"Princeton, NJ","url":"http://api.twitter.com/1/geo/id/c833fbabba6fe48e.json","name":"Princeton","bounding_box":{"type":"Polygon","coordinates":[[[-74.681254,40.337932],[-74.63659,40.337932],[-74.63659,40.361323],[-74.681254,40.361323]]]},"id":"c833fbabba6fe48e"}],"attributes":{"street_address":"20 S Tulane St"},"url":"http://api.twitter.com/1/geo/id/64b54dbe6b9fb828.json","full_name":"Princeton Record Exchange, Princeton","name":"Princeton Record Exchange","id":"64b54dbe6b9fb828","bounding_box":{"type":"Polygon","coordinates":[[[-74.658733,40.351105],[-74.658733,40.351105],[-74.658733,40.351105],[-74.658733,40.351105]]]}}]},"query":{"type":"search","url":"http://api.twitter.com/1/geo/search.json?granularity=neighborhood&accuracy=0&query=princeton+record+exchange&autocomplete=false","params":{"granularity":"neighborhood","query":"princeton record exchange","accuracy":0,"autocomplete":false}}}
79 changes: 79 additions & 0 deletions test/twitter/geo_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
require 'test_helper'

class GeoTest < Test::Unit::TestCase
include Twitter

context "Geographic place lookup" do

should "work" do
stub_get 'http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json', 'geo_place.json'
place = Geo.place('ea76a36c5bc2bdff')
place.country.should == 'The United States of America'
place.full_name.should == 'Ballantyne West, Charlotte'
place.geometry.coordinates.should be_kind_of(Array)
end

end

context "Geographic search" do

should "work" do
stub_get 'http://api.twitter.com:80/1/geo/search.json?lat=35.061161&long=-80.854568', 'geo_search.json'
places = Geo.search(:lat => 35.061161, :long => -80.854568)
places.size.should == 3
places[0].full_name.should eql('Ballantyne West, Charlotte')
places[0].name.should eql('Ballantyne West')
end

should "be able to search with free form text" do
stub_get 'http://api.twitter.com/1/geo/search.json?query=princeton%20record%20exchange', 'geo_search_query.json'
places = Geo.search(:query => 'princeton record exchange')
places.size.should == 1
places[0].name.should eql('Princeton Record Exchange')
places[0].place_type.should eql('poi')
places[0].attributes.street_address.should eql('20 S Tulane St')
end

should "be able to search by ip address" do
stub_get 'http://api.twitter.com/1/geo/search.json?ip=74.125.19.104', 'geo_search_ip_address.json'
places = Geo.search(:ip => '74.125.19.104')
places.size.should == 4
places[0].full_name.should eql("Mountain View, CA")
places[0].name.should eql("Mountain View")
places[1].full_name.should eql("Sunnyvale, CA")
places[1].name.should eql('Sunnyvale')
end

end

context "Geographic reverse_geocode" do

should "work" do
stub_get 'http://api.twitter.com:80/1/geo/reverse_geocode.json?lat=35.061161&long=-80.854568', 'geo_reverse_geocode.json'
places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568)
places.size.should == 4
places[0].full_name.should eql('Ballantyne West, Charlotte')
places[0].name.should eql('Ballantyne West')
end

should "be able to limit the number of results returned" do
stub_get 'http://api.twitter.com/1/geo/reverse_geocode.json?lat=35.061161&max_results=2&long=-80.854568', 'geo_reverse_geocode_limit.json'
places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568, :max_results => 2)
places.size.should == 2
places[0].full_name.should eql('Ballantyne West, Charlotte')
places[0].name.should eql('Ballantyne West')
end

should "be able to lookup with granularity" do
stub_get 'http://api.twitter.com/1/geo/reverse_geocode.json?lat=35.061161&long=-80.854568&granularity=city', 'geo_reverse_geocode_granularity.json'
places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568, :granularity => 'city')
places.size.should == 3
places[0].full_name.should eql('Charlotte, NC')
places[0].name.should eql('Charlotte')
places[1].full_name.should eql('North Carolina, US')
places[1].name.should eql('North Carolina')
end

end

end

0 comments on commit 0e5aa20

Please sign in to comment.