diff --git a/lib/geocoder.rb b/lib/geocoder.rb index 120cffbfd72f6bd7e6e3215ab47e82973790e9b2..23f67ab0b8e9820db9a0d675cceda74a273cdf7c 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 0000000000000000000000000000000000000000..93a1aa03cd51ee408090fa48799ee185a9e715da --- /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 0000000000000000000000000000000000000000..f5f9e14b6bb5bd7c0a832800d1442d00eb8a7f5f --- /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 0000000000000000000000000000000000000000..7592108f632044d0f00c47806337d8ba867a6649 --- /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 0000000000000000000000000000000000000000..e30a039fba88883803fe807dad7223e257603581 --- /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 0000000000000000000000000000000000000000..85001ff7c007c534087f3384279d365ffa21c197 --- /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 4c62ec1f3a28b9c35178da7fcb9104f8dada5c2a..3b45bd1b283716f2948ed8b5208115155122c398 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 38de15d0e38c05ac103c7f4f4f578fd581ca36cf..92c0681b35f24e0129e86560b6d95c9e7f8c027b 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)