module Geocoder::Lookup

def address(latitude, longitude)


Query Google for the address of the given coordinates.
#
def address(latitude, longitude)
  if (results = search(latitude, longitude)).size > 0
    results.first.formatted_address
  end
end

def coordinates(address)


Query Google for the coordinates of the given address.
#
def coordinates(address)
  if (results = search(address)).size > 0
    place = results.first.geometry['location']
    ['lat', 'lng'].map{ |i| place[i] }
  end
end

def fetch_data(query, reverse = false)


Fetches a raw Google geocoder search result (JSON string).
#
def fetch_data(query, reverse = false)
  return nil if query.blank?
  url = query_url(query, reverse)
  timeout(Geocoder::Configuration.timeout) do
    Net::HTTP.get_response(URI.parse(url)).body
  end
end

def parsed_response(query, reverse = false)


Returns nil if non-200 HTTP response, timeout, or other error.
Returns a parsed Google geocoder search result (hash).
#
def parsed_response(query, reverse = false)
  begin
    doc = ActiveSupport::JSON.decode(fetch_data(query, reverse))
  rescue SocketError
    warn "Google Geocoding API connection cannot be established."
  rescue TimeoutError
    warn "Google Geocoding API not responding fast enough " +
      "(see Geocoder::Configuration.timeout to set limit)."
  end
  case doc['status']; when "OK"
    doc
  when "OVER_QUERY_LIMIT"
    warn "Google Geocoding API error: over query limit."
  when "REQUEST_DENIED"
    warn "Google Geocoding API error: request denied."
  when "INVALID_REQUEST"
    warn "Google Geocoding API error: invalid request."
  end
end

def query_url(query, reverse = false)

def query_url(query, reverse = false)
  params = {
    (reverse ? :latlng : :address) => query,
    :sensor => "false"
  }
  "http://maps.google.com/maps/api/geocode/json?" + params.to_query
end

def search(*args)


or nil if not found or if network error.
Returns an array of Geocoder::Result objects,
geocoding, or coordinates (latitude, longitude) for reverse geocoding.
Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS") for
#
def search(*args)
  return nil if args[0].blank?
  doc = parsed_response(args.join(","), args.size == 2)
  [].tap do |results|
    if doc
      doc['results'].each{ |r| results << Result.new(r) }
    end
  end
end