Search code examples
ruby-on-railsrubyrails-geocoder

Rails: Valid addresses using Geocoder


I have a rails app and i've installed the geocoder gem.

I have the company class:

class Company < ActiveRecord::Base
  geocoded_by :address
  validates :address, presence: true
  after_validation :geocode, :if => :address_changed?
end

The problem is that i want the user fill the complete address of the company... but if the user write something like

Miami, FL, United States

It is allowed... but this is a problem because i want the complete address, with the street and height.

How can i achieve that?


Solution

  • What you are defining is not a geocoder issue, but a data-model issue: you require your users to input full addresses, so your app needs to understand and handle that. The geocoding service will try to geocode any string you pass it, no matter the resolution of the query.

    Build a validation for address so you can decide whether or not call :geocode. I can see two approaches depending on whether you want to allow the user to store addresses like "Miami, FL, United States" and not geocode that, or if you want to forbid the user to input partial addresses. I'll go for the latter, you'll see that the first can be derived with little modifications.

    In any case, considering that there is no standard address format (you can't or will find difficult build a Regex to test that, for instance), you need to handle the different parts separately and add the required attributes to your model and form for a full address to be stored.

    class ExtendAddress < ActiveRecord::Migration
      def change
        add_column :companies, :country, :string
        add_column :companies, :state, :string
        add_column :companies, :city, :string
        add_column :companies, :street, :string
        add_column :companies, :street_number, :string
        add_column :companies, :zipcode, :string
    
        remove_column :companies, :address # if you have data you want to reuse, you'd need to build a method for that before removing the column
      end
    end
    

    In your model, if you want only full addresses in your DB, then you can use validations for that:

    class Company < ActiveRecord::Base
      validates :street, :street_number, :zipcode, :city, :state, :country, presence: true
    
      geocoded_by :address
      after_validation :geocode, :if => :address_changed?
    
      def address
        # or whatever format you prefer
        [street, street_number, zipcode, city, state, country].join(',')
      end
    end
    

    I'm not writing here the form code, I'm sure you know how to build that. Also, an Address may have different number of attributes for you, take this just as a suggestion. Also, in the long run, you should consider turning Address into a first level citizen and have a separate AR model for that.