From 4b4a686d3f1fd1520e51376839d1696684c8f8a6 Mon Sep 17 00:00:00 2001 From: Alex Reisner <alex@alexreisner.com> Date: Thu, 3 Feb 2011 22:49:50 -0500 Subject: [PATCH] Add Geocoder::Result and Geocoder.search. --- README.rdoc | 2 -- lib/geocoder.rb | 19 +++++++++++++++++++ lib/geocoder/lookup.rb | 8 ++++++-- lib/geocoder/result.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ test/geocoder_test.rb | 6 ++++++ 5 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 lib/geocoder/result.rb diff --git a/README.rdoc b/README.rdoc index 426dc407..9e6e0d69 100644 --- a/README.rdoc +++ b/README.rdoc @@ -178,8 +178,6 @@ If anyone has a more elegant solution to this problem I am very interested in se * also need to make sure 'mysql2' is supported * make 'near' scope work with AR associations * http://stackoverflow.com/questions/3266358/geocoder-rails-plugin-near-search-problem-with-activerecord -* unobtrusively add ability to get a result with more data (Geocoder object?) - * the default usage should remain dead simple Copyright (c) 2009-11 Alex Reisner, released under the MIT license diff --git a/lib/geocoder.rb b/lib/geocoder.rb index fee7fabb..918163cc 100644 --- a/lib/geocoder.rb +++ b/lib/geocoder.rb @@ -1,7 +1,26 @@ require "geocoder/calculations" require "geocoder/lookup" +require "geocoder/result" require "geocoder/active_record" +module Geocoder + extend self + + ## + # Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS") for + # geocoding, or coordinates (latitude, longitude) for reverse geocoding. + # Returns a Geocoder::Result object. + # + def search(*args) + if args.size == 2 + Lookup.search(args[0], args[1], true) + else + Lookup.search(args[0], false) + end + end +end + + ## # Add geocoded_by method to ActiveRecord::Base so Geocoder is accessible. # diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index fd2ae65f..96b8d16e 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -29,10 +29,14 @@ module Geocoder ## # Query Google for geographic information about the given phrase. - # Returns a Result object containing all data returned by Google. + # Returns an array of Geocoder::Result objects. # def search(query, reverse = false) - # TODO + [].tap do |results| + if doc = parsed_response(query, reverse) + doc['results'].each{ |r| results << Result.new(r) } + end + end end diff --git a/lib/geocoder/result.rb b/lib/geocoder/result.rb new file mode 100644 index 00000000..e63f2263 --- /dev/null +++ b/lib/geocoder/result.rb @@ -0,0 +1,42 @@ +module Geocoder + class Result + attr_accessor :data + + ## + # Takes a hash of result data from a parsed Google result document. + # + def initialize(data) + @data = data + end + + def types + @data['types'] + end + + def formatted_address + @data['formatted_address'] + end + + def address_components + @data['address_components'] + end + + ## + # Get address components of a given type. Valid types are defined in + # Google's Geocoding API documentation and include (among others): + # + # :street_number + # :locality + # :neighborhood + # :route + # :postal_code + # + def address_components_of_type(type) + address_components.select{ |c| c['types'].include?(type.to_s) } + end + + def geometry + @data['geometry'] + end + end +end diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb index 83b4c51a..7b8c0ff5 100644 --- a/test/geocoder_test.rb +++ b/test/geocoder_test.rb @@ -27,4 +27,10 @@ class GeocoderTest < Test::Unit::TestCase l.fetch_coordinates end end + + def test_result_address_components_of_type + results = Geocoder::Lookup.search("Madison Square Garden, New York, NY") + assert_equal "Manhattan", + results.first.address_components_of_type(:sublocality).first['long_name'] + end end -- GitLab