Ruby Geocoder可以在reverse_geocode调用中返回街道名称吗?

时间:2013-03-19 00:23:57

标签: ruby-on-rails rails-geocoder

如果模型中包含行after_validation :reverse_geocodegeocoder gem将自动反转地理编码。这导致一长串文本被保存为地址,但格式类似于“街道名称,城市名称,县名,州名,邮政编码,国家名称”。

我只对这个特定项目的街道名称感兴趣,所以我想知道是否有办法修改after_validation调用以仅保存该信息。

如果我手动执行反向地理编码,我可以访问结果中的road值:

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

我可以设置我自己的自定义after_validation,但是如果geocoder已经提供此功能,我宁愿不重复功能。

或者,如果有一种完全不同的方式可以将纬度/经度转换成街道名称,我会有兴趣听到它。如果此选项也包含地址编号或地址范围,则可以。

2 个答案:

答案 0 :(得分:9)

您可以通过提供一个使对象进行地理编码的块和一个Geocoder :: Result对象数组来自定义reverse_geocode方法。

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都提供以下数据:

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

可以在geocode docs中找到更多信息。您甚至可以找到更多可以从Geocoder::Result对象中删除的字段。

答案 1 :(得分:3)

您可以使用:数据方法访问所选地理编码服务中的所有属性。

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

请注意您使用的每种地理编码服务的格式都不同:以下是使用Yandex的另一个示例:

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