Skip to content

Instantly share code, notes, and snippets.

@jch
Created July 24, 2013 22:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jch/6075370 to your computer and use it in GitHub Desktop.
Save jch/6075370 to your computer and use it in GitHub Desktop.
Simple Google Geocoding API V3 client. All I needed was a state name given a postal code. Might be interesting to build this out, but felt I'd share the basics first.
require 'uri'
require 'multi_json'
require 'net/http'
# Simple client wrapper around Google Geocoding API V3
# https://developers.google.com/maps/documentation/geocoding
#
# geo = Geocoding::Google.geocode('91106')
# geo.state
#
module Geocoding
module Google
API_URI = URI("https://maps.googleapis.com/maps/api/geocode/json")
def geocode(address)
req = Request.new(address)
req.run
end
module_function :geocode
class Request
def initialize(address)
@address = address
end
def uri
uri = Geocoding::Google::API_URI.clone
uri.query = URI.encode_www_form(:address => @address, :sensor => false)
uri
end
def run
get = Net::HTTP::Get.new([uri.path, uri.query].join('?'))
req = Net::HTTP.new(uri.host, uri.port)
req.use_ssl = true
res = req.start { |http| http.request(get) }
case res
when Net::HTTPSuccess
json = MultiJson.decode(res.body)
Result.new(json)
else
nil
end
end
end
class Result
def initialize(attrs)
@attrs = attrs
end
def state
return nil unless ok?
components = results.fetch('address_components')
c = components.detect { |ac|
ac['types'].include?("administrative_area_level_1")
}
c['short_name']
rescue
nil
end
def ok?
status == 'OK'
end
def status
@status ||= @attrs['status']
end
def results
@results ||= @attrs.fetch('results').first
end
end
end
end
require 'test_helper'
class Geocoding::GoogleTest < Test::Unit::TestCase
def test_url
req = Geocoding::Google::Request.new('91106')
uri = URI("https://maps.googleapis.com/maps/api/geocode/json?address=91106&sensor=false")
assert_equal uri, req.uri
end
def test_state
geo = Geocoding::Google.geocode('91106')
assert_equal 'CA', geo.state
end
def test_status
res = Geocoding::Google::Result.new("results" => [], "status" => "REQUEST_DENIED")
refute res.ok?
assert_equal 'REQUEST_DENIED', res.status
end
end
@speric
Copy link

speric commented Jul 25, 2013

Any plans to build this out? If so, I will contribute.

@jch
Copy link
Author

jch commented Jul 26, 2013

I might do a bit more with it, but I don't think I'll ever build it into a full scale geocoding suite that the bigger gems do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment