diff --git a/README.rdoc b/README.rdoc index 551c363e422e1603231b7b90703a2e460aaf561f..4c50d8822ec4d1dd40bbe1403d341afe3218ef2f 100644 --- a/README.rdoc +++ b/README.rdoc @@ -233,6 +233,7 @@ Note that the result objects returned by different geocoding services all implem * Google: http://code.google.com/apis/maps/documentation/geocoding/#JSON * Yahoo: http://developer.yahoo.com/geo/placefinder/guide/responses.html * Geocoder.ca: (???) +* Yandex: http://api.yandex.ru/maps/geocoder/doc/desc/concepts/response_structure.xml * FreeGeoIP: http://github.com/fiorix/freegeoip/blob/master/README.rst === API Keys @@ -241,10 +242,11 @@ To use your Google API key or Yahoo app ID: Geocoder::Configuration.api_key = "..." -To obtain an API key (not required): +To obtain an API key: -* Yahoo: https://developer.apps.yahoo.com/wsregapp -* Google: http://code.google.com/apis/maps/signup.html +* Yahoo: https://developer.apps.yahoo.com/wsregapp (not required) +* Google: http://code.google.com/apis/maps/signup.html (not required) +* Yandex: http://api.yandex.ru/maps/intro/concepts/intro.xml#apikey (required) === Timeout diff --git a/lib/geocoder.rb b/lib/geocoder.rb index ddca673d0165edb14444c5e60c36f0b99386f7f3..33715dc065d230b071b511ad0eb9f833d02a0bb6 100644 --- a/lib/geocoder.rb +++ b/lib/geocoder.rb @@ -125,7 +125,7 @@ module Geocoder # Array of valid Lookup names. # def valid_lookups - [:google, :yahoo, :geocoder_ca, :freegeoip] + [:google, :yahoo, :geocoder_ca, :yandex, :freegeoip] end ## diff --git a/lib/geocoder/lookups/yandex.rb b/lib/geocoder/lookups/yandex.rb new file mode 100644 index 0000000000000000000000000000000000000000..66d14f5cbdd6d2e66d634c45964edd60c7b2373c --- /dev/null +++ b/lib/geocoder/lookups/yandex.rb @@ -0,0 +1,30 @@ +require 'geocoder/lookups/base' +require "geocoder/results/yandex" + +module Geocoder::Lookup + class Yandex < Base + + private # --------------------------------------------------------------- + + def results(query, reverse = false) + return [] unless doc = fetch_data(query, reverse) + if doc = doc['response']['GeoObjectCollection'] + meta = doc['metaDataProperty']['GeocoderResponseMetaData'] + return meta['found'].to_i > 0 ? doc['featureMember'] : [] + else + warn "Yandex Geocoding API error: unexpected response format." + return [] + end + end + + def query_url(query, reverse = false) + params = { + :geocode => query, + :format => "json", + :plng => "#{Geocoder::Configuration.language}", # supports ru, uk, be + :key => Geocoder::Configuration.api_key + } + "http://geocode-maps.yandex.ru/1.x/?" + hash_to_query(params) + end + end +end diff --git a/lib/geocoder/results/yandex.rb b/lib/geocoder/results/yandex.rb new file mode 100644 index 0000000000000000000000000000000000000000..7f6f3281b7cec49e845cda992a566007ebd80720 --- /dev/null +++ b/lib/geocoder/results/yandex.rb @@ -0,0 +1,40 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Yandex < Base + + def coordinates + @data['GeoObject']['Point']['pos'].split(' ').map(&:to_f) + end + + def address(format = :full) + @data['GeoObject']['metaDataProperty']['GeocoderMetaData']['text'] + end + + def city + address_details['Locality']['LocalityName'] + end + + def country + address_details['CountryName'] + end + + def country_code + address_details['CountryNameCode'] + end + + def postal_code + "" + end + + def premise_name + address_details['Locality']['Premise']['PremiseName'] + end + + private # ---------------------------------------------------------------- + + def address_details + @data['GeoObject']['metaDataProperty']['GeocoderMetaData']['AddressDetails']['Country'] + end + end +end diff --git a/test/fixtures/yandex_kremlin.json b/test/fixtures/yandex_kremlin.json new file mode 100644 index 0000000000000000000000000000000000000000..f08b6ea3aae3d1332657df2150a23cbbe4ec5678 --- /dev/null +++ b/test/fixtures/yandex_kremlin.json @@ -0,0 +1,48 @@ +{ + "response": { + "GeoObjectCollection": { + "metaDataProperty": { + "GeocoderResponseMetaData": { + "request": "Кремль, Moscow, Russia", + "found": "1", + "results": "10" + } + }, + "featureMember": [ + { + "GeoObject": { + "metaDataProperty": { + "GeocoderMetaData": { + "kind": "vegetation", + "text": "РоÑÑиÑ, МоÑква, МоÑковÑкий Кремль", + "precision": "other", + "AddressDetails": { + "Country": { + "CountryNameCode": "RU", + "CountryName": "РоÑÑиÑ", + "Locality": { + "LocalityName": "МоÑква", + "Premise": { + "PremiseName": "МоÑковÑкий Кремль" + } + } + } + } + } + }, + "name": "МоÑковÑкий Кремль", + "boundedBy": { + "Envelope": { + "lowerCorner": "37.584182 55.733361", + "upperCorner": "37.650064 55.770517" + } + }, + "Point": { + "pos": "37.617123 55.751943" + } + } + } + ] + } + } +} diff --git a/test/fixtures/yandex_no_results.json b/test/fixtures/yandex_no_results.json new file mode 100644 index 0000000000000000000000000000000000000000..6645611563a2262f38799dc527ad59284894d8af --- /dev/null +++ b/test/fixtures/yandex_no_results.json @@ -0,0 +1,16 @@ +{ + "response": { + "GeoObjectCollection": { + "metaDataProperty": { + "GeocoderResponseMetaData": { + "request": "blah", + "found": "0", + "results": "10" + } + }, + "featureMember": [ + + ] + } + } +} diff --git a/test/test_helper.rb b/test/test_helper.rb index d2a6e51b26f42d4875884b9796ff4c757f5f61bc..9e48f988360a5e31c1495ff4def79a303f74a3de 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -80,6 +80,15 @@ module Geocoder end end + class Yandex < Base + private #----------------------------------------------------------------- + def fetch_raw_data(query, reverse = false) + raise TimeoutError if query == "timeout" + file = query == "no results" ? :no_results : :kremlin + read_fixture "yandex_#{file}.json" + end + end + class GeocoderCa < Base private #----------------------------------------------------------------- def fetch_raw_data(query, reverse = false)