Ruby Geocoder能否在反向地理编码调用中只返回街道名?

5
地理编码器 gem会在模型中包含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已经提供此功能,我宁愿不要重复实现。或者,如果有完全不同的方法可以将纬度/经度转换为街道名称,我会很感兴趣听到它。如果此选项还包括地址编号或地址范围,那也没问题。
2个回答

10
您可以通过提供一个块来定制 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对象中提取的字段。


3
: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

请注意,您使用的每个地理编码服务的格式都会有所不同:以下是使用Yandex的另一个示例:
street = result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["AddressDetails"]["Country"]["AdministrativeArea"]["SubAdministrativeArea"]["Locality"]["Thoroughfare"]["ThoroughfareName"]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接