A Ruby gem to handle all things zipcode.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
features
lib
.gitignore
.hound.yml
.rubocop.yml
.travis.yml
Gemfile
MIT-LICENSE
README.md
Rakefile
my_zipcode_gem.gemspec
rails3_2.gemfile
rails4_0.gemfile
rails4_1.gemfile

README.md

My Zipcode Gem

MIT-LICENSE

Simple gem to handle zipcode lookups and related functionality. rake zipcodes:update will automatically download and update your local zipcode database. Generates three models for extended zipcode functionality.

Versions

  • 0.1.x is for Rails versions less than 4.x
  • 0.2.x is for Rails 4 and above

Installation

Add the following line to your Gemfile:

gem 'my_zipcode_gem'

Run:

rake bundle install

Generate the models and populate the data:

rails g my_zipcode_gem:models
# here you may need to run "bundle install" again for dependencies
rake db:migrate
rake zipcodes:update # this will take some time, be patient

You should now have three new tables and three new models, Zipcode, State, County.

Usage

zipcode = Zipcode.find_by_code '66206'
zipcode.state.abbr    # => 'KS'
zipcode.city          # => 'Shawnee Mission'
zipcode.county.name   # => 'Johnson'
zipcode.lat.to_s      # => '38.959356', it is actually a BigDecimal object converted to_s for documentation.
zipcode.lon.to_s      # => '-94.716155', ditto
zipcode.geocoded?  # => true, most if not all should be pre-geocoded.

You can also look for a zipcode from a city and state:

Zipcode.find_by_city_state "Shawnee Mission", "KS"

You can use State and County objects as follows:

state = State.find_by_abbr "MO"
state.cities.count    # => 963
state.cities          # gives you a sorted array of all cities for the state
state.zipcodes.count  # => 1195
...
county = state.counties.first
county.cities.count   # => 5
county.cities         # gives you a sorted array of all cities for the county
county.zipcodes.count # => 5

Automatic JQuery/AJAX lookup

You can have a user enter a zipcode and automatically lookup their city, state and county.

Put something like this in your view:

f.text_field :zip, size: 5, maxlength: 5, class: 'zipcode_interactive'
f.text_field :city, size: 20, maxlength: 60, readonly: true
f.text_field(:state, size: 2, maxlength: 2, readonly: true)
f.text_field(:county, size: 20, maxlength: 60, readonly: true)

Then add this to your application.js, but remember to replace mycontrollername with your own controller.

$(document).ready(function() {
  // Interactive Zipcodes
  $('input.zipcode_interactive').blur(function(data) {
    var elem_id = $(this).attr("id");
    var base_id = elem_id.substring(0, elem_id.lastIndexOf("_"));
    $.get("/mycontrollername/get_zip_data/" + this.value, {},
    function(data) {
      var zipcode = $.parseJSON(data);
      var city = $('#' + base_id + '_city');
      var state = $('#' + base_id + '_state');
      var county = $('#' + base_id + '_county');
      if (zipcode.err) {
        alert(zipcode.err);
      } else {
        city.val(zipcode.city);
        state.val(zipcode.state)
        county.val(zipcode.county)
      }
    })
  });
});

You will also need a controller method similar to this, which will return the data to your form:

def get_zip_data
  @zipcode = Zipcode.find_by_code(params[:code], include: [:county, :state])
  if @zipcode
    @counties = County.find(:all, conditions: [ "state_id = ?", @zipcode.county.state_id ])
    data = {
      'state' => @zipcode.state.abbr,
      'county' => @zipcode.county.name,
      'city' => @zipcode.city.titleize
    }
    render text: data.to_json
  else
    if params[:code].blank?
      return true
    else
      if params[:code].is_zipcode?
        data = {
          'err' => "Could not find Zipcode [#{params[:code]}].  If this is a valid zipcode please notify support <support@mydomain.com>, so we can update our database."
        }
      else
        data = {
          'err' => "[#{params[:code]}] is not a valid Zipcode."
        }
      end
      render text: data.to_json
    end
  end
end

And define a route for the AJAX function in routes.rb:

get 'mycontrollername/get_zip_data/:code', controller: 'mycontrollername', action: 'get_zip_data'

That's about it.

Please report any errors or issues.

LOG

05/03/2011:

Initial Release