Может ли Ruby Geocoder возвращать только название улицы при вызовах reverse_geocode?

Гем geocoder автоматически реверсирует геокодирование при сохранении, если в модель включена линия after_validation :reverse_geocode. Это приводит к тому, что в качестве адреса сохраняется длинная строка текста — формат примерно такой: «Название улицы, название города, название округа, название штата, почтовый индекс, название страны».

Меня интересует только название улицы для этого конкретного проекта, поэтому мне интересно, есть ли способ изменить вызов after_validation, чтобы сохранить только эту информацию.

Если я выполняю обратное геокодирование вручную, я могу получить доступ к значению road в результате:

  place = Place.first
  result = Geocoder.search("#{place.latitude},#{place.longitude}")
  street = result[0].data['address']['road']

Я мог бы настроить свой собственный after_validation, который делает именно это, но я бы не хотел дублировать функциональность, если geocoder уже предоставляет это.

В качестве альтернативы, если есть совершенно другой способ преобразования широты/долготы в название улицы, мне было бы интересно узнать об этом. Было бы нормально, если бы эта опция также включала номер адреса или диапазон адресов.


person James Chevalier    schedule 19.03.2013    source источник


Ответы (2)


Вы можете настроить метод reverse_geocode, предоставив блок, который берет объект для геокодирования и массив объектов Geocoder::Result.

reverse_geocoded_by :latitude, :longitude do |obj,results|
  if geo = results.first
    obj.street = geo.address
  end
end

after_validation :reverse_geocode

Каждый объект Geocoder::Result, результат, предоставляет следующие данные:

result.latitude - float
result.longitude - float
result.coordinates - array of the above two
result.address - string
result.city - string
result.state - string
result.state_code - string
result.postal_code - string
result.country - string
result.country_code - string

Дополнительную информацию можно найти в документах по геокодированию. Возможно, вы даже сможете найти больше полей, которые вы можете извлечь из объекта Geocoder::Result.

person rocket scientist    schedule 19.03.2013

Вы можете получить доступ ко всем атрибутам выбранного вами сервиса геокодирования, используя метод :data.

query = "45.679, -45.567"
result = Geocoder.search(query).first 

if (result) 
   all_attributes = result.data
end

Это вернет ответ JSON со всеми доступными ключами и значениями для ваших конкретных координат. Если вы используете Google для обратного геокодирования, вы получите ответ, подобный этому:

{
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Amphitheatre Pkwy",
               "short_name" : "Amphitheatre Pkwy",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Mountain View",
               "short_name" : "Mountain View",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Santa Clara County",
               "short_name" : "Santa Clara County",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "California",
               "short_name" : "CA",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "94043",
               "short_name" : "94043",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
         "geometry" : {
            "location" : {
               "lat" : 37.4224764,
               "lng" : -122.0842499
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.4238253802915,
                  "lng" : -122.0829009197085
               },
               "southwest" : {
                  "lat" : 37.4211274197085,
                  "lng" : -122.0855988802915
               }
            }
         },
         "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
         "types" : [ "street_address" ]
      }

Так что просто разверните JSON, чтобы получить то, что вы хотите:

result.data["address_components"].each do |component|

  if component["types"].include?("route")
    street = component["long_name"]
  end

end

Обратите внимание, форматирование будет отличаться для каждого используемого вами сервиса геокодирования: Вот еще один пример с использованием Яндекса:

street = result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["AddressDetails"]["Country"]["AdministrativeArea"]["SubAdministrativeArea"]["Locality"]["Thoroughfare"]["ThoroughfareName"]
person heading_to_tahiti    schedule 15.05.2015