Class: Google4R::Maps::Geocoder

Inherits:
Object
  • Object
show all
Defined in:
lib/google4r/maps.rb

Overview

Allows to geocode a location.

Uses the Google Maps API to find information about locations specified by strings. You need a Google Maps API key to use the Geocoder.

The result has the same format as documented in [1] (within <kml>) if it is directly converted into Ruby: A value consisting of nested Hashes and Arrays.

After querying, you can access the last server response code using #last_status_code.

Notice that you can also use Google’s geolocator service to locate ZIPs by querying for the ZIP and country name.

Usage Example:

api_key = 'abcdefg'
geocoder = Google4R::Maps::Geocoder.new(api_key)
result = geocoder.query("1 Infinite Loop, Cupertino")
puts result["Placemark"][0]["address"] # => "1 Infinite Loop, Cupertino, CA 95014"
1

www.google.de/apis/maps/documentation/#Geocoding_Structured

Constant Summary collapse

GET_URL =

The hardcoded URL of Google’s geolocator API.

'http://maps.google.com/maps/geo?q=%s&output=%s&key=%s'.freeze
G_GEO_SUCCESS =

Response code constants.

200
G_GEO_SERVER_ERROR =
500
G_GEO_MISSING_ADDRESS =
601
G_GEO_UNKNOWN_ADDRESS =
602
G_UNAVAILABLE_ADDRESS =
603
G_GEO_BAD_KEY =
610

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, client = nil) ⇒ Geocoder

Creates a new Geocoder object. You have to supply a valid Google Maps API key.

Parameters

key::The Google Maps API key. client::Your Google Maps client ID (this is only required for enterprise keys).



703
704
705
706
# File 'lib/google4r/maps.rb', line 703

def initialize(key, client=nil)
  @api_key = key
  @client = client
end

Instance Attribute Details

#last_status_codeObject (readonly)

Returns the last status code returned by the server.



683
684
685
# File 'lib/google4r/maps.rb', line 683

def last_status_code
  @last_status_code
end

Instance Method Details

#query(query) ⇒ Object

Parameters

query

The place to locate.

Exceptions

Throws a KeyException if the key for this Geocoder instance is invalid and throws a ConnectionException if the Geocoder instance could not connect to Google’s server or an server error occured.

Return Values

Returns data in the same format as documented in [1]

Example of returned values:

{
  "name": "1600 Amphitheatre Parkway, Mountain View, CA, USA",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [
    {
      "address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
      "AddressDetails": {
        "Country": {
          "CountryNameCode": "US",
          "AdministrativeArea": {
            "AdministrativeAreaName": "CA",
            "SubAdministrativeArea": {
              "SubAdministrativeAreaName": "Santa Clara",
              "Locality": {
                "LocalityName": "Mountain View",
                "Thoroughfare": {
                  "ThoroughfareName": "1600 Amphitheatre Pkwy"
                },
                "PostalCode": {
                  "PostalCodeNumber": "94043"
                }
              }
            }
          }
        },
        "Accuracy": 8
      },
      "Point": {
        "coordinates": [-122.083739, 37.423021, 0]
      }
    }
  ]
}
1

www.google.de/apis/maps/documentation/#Geocoding_Structured

++ TODO: Remove the workaround below once this ticket is cleared and the change widely distributed: code.whytheluckystiff.net/syck/ticket/27

Raises:



765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
# File 'lib/google4r/maps.rb', line 765

def query(query)
  # Check that a Google Maps key has been specified.
  raise KeyException.new("Cannot use Google geocoder without an API key.") if @api_key.nil?

  # Compute the URL to send a GET query to.
  url = URI.escape(GET_URL % [ query, 'json', @api_key.to_s ])
  url += "&client=#{@client}" unless @client.nil?
  
  # Perform the query via HTTP.
  response = 
    begin
      Net::HTTP.get_response(URI.parse(url))
    rescue Exception => e
      raise ConnectionException.new("Could not connect to '#{url}': #{e.message}")
    end
  body = response.body

  # Parse the response JSON. We can simply use YAML::load here. I discovered this
  # on why's page: http://redhanded.hobix.com/inspect/yamlIsJson.html
  #
  # We need a workaround to parse the ultra compact JSON from Google, however, because
  # of this bug: http://code.whytheluckystiff.net/syck/ticket/27
  result = YAML::load(body.gsub(/([:,])([^\s])/, '\1 \2'))
  
  @last_status_code = result['Status']['code']

  # Check that the query was successful.
  if @last_status_code == G_GEO_BAD_KEY then
    raise KeyException.new("Invalid API key: '#{@api_key}'.")
  elsif @last_status_code == G_GEO_SERVER_ERROR then
    raise ConnectionException.new("There was an error when connecting to the server. Result code was: #{status}.") 
  elsif [ G_GEO_MISSING_ADDRESS, G_GEO_UNKNOWN_ADDRESS, G_UNAVAILABLE_ADDRESS ].include?(@last_status_code) then
    return nil
  end

  return result
end