Blog

Best practices: Async Reverse Geocoding with Ruby and Geocoder

Placeholder Avatar
Lucas Caton
January 5, 2018

Today I will share with you how I approach reverse geocoding using the Geocoder gem.

As you may know, the Ruby gem Geocoder allows you to do reverse geocoding “automatically” in the model by doing

reverse_geocoded_by :latitude, :longitude

That is cool, but I found a better way…

First, the Geocoder gem makes a request to the Google maps API. That takes time, making my response a little slow. So I decided to do the reverse geocoding in an async process after my record detected a change in my latitude and longitude fields.

app/models/location.rb

class Location < ApplicationRecord ... after_commit -> { ReverseGeocodingWorker.perform_async(id) }, if: :coordinates_changed? private def coordinates_changed? latitude_changed? && longitude_changed? end ... end

Now, let’s see the ReverseGeocodingWorker class in charge of updating the location record with the results of the Google Maps API:

app/workers/reverse_geocoding_worker.rb

``` class ReverseGeocodingWorker include Sidekiq::Worker sidekiq_options retry: true

def perform(location_id) location = Location.find(location_id) results = Geocoder.search([location.latitude, location.longitude]) if results result = result.first location.update_attributes( street_address: result.street_address, city: result.city, state: result.state, postal_code: result.postal_code ) end end end ```

This will speed up your response time since you are delegating the reverse geocoding process to the worker.

Lastly, I want to share one bonus tip for the Geocoder setup which will further increase the response time and will also save your Google Maps quota, simply by enabling the cache option:

config/initializers/geocoder.rb

Geocoder.configure( # Geocoding options lookup: :google, ip_lookup: :freegeoip, use_https: false, cache: Redis.new )

Good luck with your reverse geocoding feature.

Please let me know if you have questions or want me to write new posts about best practices for Ruby apps.

Cheers!