Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Ruby Geocoder return just the street name on reverse_geocode calls?

The geocoder gem will automatically reverse geocode on save if the line after_validation :reverse_geocode is included in the model. This results in a long string of text being saved as the address, though - the format is something like "Street Name, City Name, County Name, State Name, Zip Code, Country Name".

I'm only interested in the street name for this particular project, so I'm wondering if there's a way to modify the after_validation call to only save that information.

If I do the reverse geocoding manually, I can access the road value in the result:

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

I could set up my own custom after_validation that does just this, but I'd rather not duplicate functionality if geocoder already provides this.

Alternatively, if there's an entirely different way that I can convert latitude/longitude to street name I'd be interested in hearing about it. It would be OK if this option included the address number or address range as well.

like image 950
James Chevalier Avatar asked Mar 19 '13 00:03

James Chevalier


People also ask

How do you use geocoder gems?

Implementing the Geocoder Gem The gem is simple to install and use, and within about 2 minutes we were calculating real-time ride estimates. To install the gem, simply add gem 'geocoder', '~> 1.3', '>= 1.3. 7' to your Gemfile and then run gem install geocoder -v 1.3. 7 in your terminal.

What is geocoder location?

Geocoding is the process of transforming a street address or other description of a location into a (latitude, longitude) coordinate. Reverse geocoding is the process of transforming a (latitude, longitude) coordinate into a (partial) address.

What is geocoding api?

The Geocoding API is a service that provides geocoding and reverse geocoding of addresses. This service is also available as part of the client-side Google Maps JavaScript API, or for server-side use with the Java Client, Python Client, Go Client and Node. js Client for Google Maps Services.

What is geocoding mapbox?

Geocoding is the process of taking an address or name of a place and converting it into latitude and longitude values. The Mapbox Geocoding API allows you to performs two types of geocoding: forward geocoding and reverse geocoding. Forward geocoding converts text into geographic coordinates.


2 Answers

You can customize the reverse_geocode method by providing a block which takes the object to be geocoded and an array of Geocoder::Result objects.

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

after_validation :reverse_geocode

Every Geocoder::Result object, result, provides the following data:

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

More information can be found in the geocode docs. You might even be able to find more fields that you can pull off of the Geocoder::Result object.

like image 116
rocket scientist Avatar answered Nov 09 '22 18:11

rocket scientist


You can access all the attributes from the selected geocoding service that you are using by using the :data method.

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

if (result) 
   all_attributes = result.data
end

This will return a JSON response of all the available keys and values for your particular coordinates. If you are using Google to reverse geocode then you would get a response similar to this:

{
         "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" ]
      }

So just drill down through the JSON to get what you desire:

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

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

end

Please note the formatting will be different for each geocoding service that you use: Here is another example using Yandex:

street = result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["AddressDetails"]["Country"]["AdministrativeArea"]["SubAdministrativeArea"]["Locality"]["Thoroughfare"]["ThoroughfareName"]
like image 31
heading_to_tahiti Avatar answered Nov 09 '22 16:11

heading_to_tahiti