From 2b473b45872dd101a7ad48ab618cd9b39406ea91 Mon Sep 17 00:00:00 2001 From: Alex Reisner <alex@alexreisner.com> Date: Tue, 15 Mar 2011 01:02:03 -0400 Subject: [PATCH] Add Geocoder.ca support. --- lib/geocoder.rb | 2 +- lib/geocoder/lookups/geocoder_ca.rb | 43 ++++++++++++++ lib/geocoder/results/geocoder_ca.rb | 58 +++++++++++++++++++ .../geocoder_ca_madison_square_garden.json | 1 + test/fixtures/geocoder_ca_no_results.json | 1 + test/fixtures/geocoder_ca_reverse.json | 34 +++++++++++ test/geocoder_test.rb | 10 ++++ test/test_helper.rb | 13 +++++ 8 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 lib/geocoder/lookups/geocoder_ca.rb create mode 100644 lib/geocoder/results/geocoder_ca.rb create mode 100644 test/fixtures/geocoder_ca_madison_square_garden.json create mode 100644 test/fixtures/geocoder_ca_no_results.json create mode 100644 test/fixtures/geocoder_ca_reverse.json diff --git a/lib/geocoder.rb b/lib/geocoder.rb index 120cffbf..23f67ab0 100644 --- a/lib/geocoder.rb +++ b/lib/geocoder.rb @@ -77,7 +77,7 @@ module Geocoder end def valid_lookups - [:google, :yahoo, :freegeoip] + [:google, :yahoo, :geocoder_ca, :freegeoip] end ## diff --git a/lib/geocoder/lookups/geocoder_ca.rb b/lib/geocoder/lookups/geocoder_ca.rb new file mode 100644 index 00000000..93a1aa03 --- /dev/null +++ b/lib/geocoder/lookups/geocoder_ca.rb @@ -0,0 +1,43 @@ +require 'geocoder/lookups/base' +require "geocoder/results/geocoder_ca" + +module Geocoder::Lookup + class GeocoderCa < Base + + private # --------------------------------------------------------------- + + def result(query, reverse = false) + return nil unless doc = fetch_data(query, reverse) + if doc['error'].nil? + doc + elsif doc['error']['code'] == "005" + nil # "Postal Code is not in the proper Format" => no results, just shut up + else + warn "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']})." + end + end + + def query_url(query, reverse = false) + params = { + :geoit => "xml", + :reverse => reverse ? "Reverse+GeoCode+it!" : nil, + :jsonp => 1, + :callback => "test" + } + if reverse + lat,lon = query.split(',') + params[:latt] = lat + params[:longt] = lon + params[:corner] = 1 + else + params[:locate] = query + end + "http://geocoder.ca/?" + hash_to_query(params) + end + + def parse_raw_data(raw_data) + super raw_data[/^test\((.*)\)\;\s*$/, 1] + end + end +end + diff --git a/lib/geocoder/results/geocoder_ca.rb b/lib/geocoder/results/geocoder_ca.rb new file mode 100644 index 00000000..f5f9e14b --- /dev/null +++ b/lib/geocoder/results/geocoder_ca.rb @@ -0,0 +1,58 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class GeocoderCa < Base + + def coordinates + [@data['latt'].to_f, @data['longt'].to_f] + end + + def address(format = :full) + "#{street_address}, #{city}, #{state} #{postal_code}, #{country}" + end + + def street_address + "#{@data['stnumber']} #{@data['staddress']}" + end + + def city + @data['city'] + end + + def state + @data['prov'] + end + + alias_method :province, :state + + def postal_code + @data['postal'] + end + + def country + country_code == 'CA' ? 'Canada' : 'United States' + end + + def country_code + prov = @data['prov'] + return nil if prov.nil? || prov == "" + canadian_province_abbreviations.include?(@data['prov']) ? "CA" : "US" + end + + def canadian_province_abbreviations + %w[ON QC NS NB MB BC PE SK AB NL] + end + + def self.response_attributes + %w[latt longt inlatt inlongt betweenRoad1 betweenRoad2 distance + stnumber staddress city prov postal + NearRoad NearRoadDistance intersection major_intersection] + end + + response_attributes.each do |a| + define_method a do + @data[a] + end + end + end +end diff --git a/test/fixtures/geocoder_ca_madison_square_garden.json b/test/fixtures/geocoder_ca_madison_square_garden.json new file mode 100644 index 00000000..7592108f --- /dev/null +++ b/test/fixtures/geocoder_ca_madison_square_garden.json @@ -0,0 +1 @@ +test({"longt":"-73.992006","latt":"40.749101"}); diff --git a/test/fixtures/geocoder_ca_no_results.json b/test/fixtures/geocoder_ca_no_results.json new file mode 100644 index 00000000..e30a039f --- /dev/null +++ b/test/fixtures/geocoder_ca_no_results.json @@ -0,0 +1 @@ +test({"longt":"-0.000000","error":{"description":"Postal Code is not in the proper Format.","code":"005"},"latt":"176946676.000000"}); diff --git a/test/fixtures/geocoder_ca_reverse.json b/test/fixtures/geocoder_ca_reverse.json new file mode 100644 index 00000000..85001ff7 --- /dev/null +++ b/test/fixtures/geocoder_ca_reverse.json @@ -0,0 +1,34 @@ +test({ + "latt":"45.423733", + "longt":"-75.676333", + "inlatt":"45.424035", + "inlongt":"-75.675941", + "betweenRoad1":"Chapel", + "betweenRoad2":"Russell", + "distance":"0.034", + "stnumber":"289", + "staddress":"Somerset ST E", + "city":"Ottawa", + "prov":"ON", + "postal":"K1N6W1", + "NearRoad":"Somerset ST E", + "NearRoadDistance":"0.013", + "intersection":{ + "lattx":"45.423733", + "longtx":"-75.676333", + "distance":"0.045", + "street1":"Somerset St E", + "street2":"Russell Ave", + "city":"OTTAWA", + "prov":"ON" + }, + "major_intersection":{ + "lattx":"45.4241623853", + "longtx":"-75.6753026518", + "distance":"0.052", + "street1":"Chapel St", + "street2":"Somerset St E", + "city":"OTTAWA", + "prov":"ON" + } +}); diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb index 4c62ec1f..3b45bd1b 100644 --- a/test/geocoder_test.rb +++ b/test/geocoder_test.rb @@ -170,6 +170,16 @@ class GeocoderTest < Test::Unit::TestCase end + # --- Geocoder.ca --- + + def test_geocoder_ca_result_components + Geocoder::Configuration.lookup = :geocoder_ca + result = Geocoder.search(45.423733, -75.676333) + assert_equal "CA", result.country_code + assert_equal "289 Somerset ST E, Ottawa, ON K1N6W1, Canada", result.address + end + + # --- FreeGeoIp --- def test_freegeoip_result_on_ip_address_search diff --git a/test/test_helper.rb b/test/test_helper.rb index 38de15d0..92c0681b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -72,6 +72,19 @@ module Geocoder end end + class GeocoderCa < Base + private #----------------------------------------------------------------- + def fetch_raw_data(query, reverse = false) + raise TimeoutError if query == "timeout" + if reverse + read_fixture "geocoder_ca_reverse.json" + else + file = query == "no results" ? :no_results : :madison_square_garden + read_fixture "geocoder_ca_#{file}.json" + end + end + end + class Freegeoip < Base private #----------------------------------------------------------------- def fetch_raw_data(query, reverse = false) -- GitLab