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.
- 0.1.x is for Rails versions less than 4.x
- 0.2.x is for Rails 4 and above
Add the following line to your Gemfile:
gem'my_zipcode_gem'Run:
rake bundle installGenerate 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 patientYou should now have three new tables and three new models, Zipcode, State, County.
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', dittozipcode.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# => 963state.cities# gives you a sorted array of all cities for the statestate.zipcodes.count# => 1195
...
county=state.counties.firstcounty.cities.count# => 5county.cities# gives you a sorted array of all cities for the countycounty.zipcodes.count# => 5You 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: truef.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){varelem_id=$(this).attr("id");varbase_id=elem_id.substring(0,elem_id.lastIndexOf("_"));$.get("/mycontrollername/get_zip_data/"+this.value,{},function(data){varzipcode=$.parseJSON(data);varcity=$('#'+base_id+'_city');varstate=$('#'+base_id+'_state');varcounty=$('#'+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:
defget_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}rendertext: data.to_jsonelseifparams[:code].blank?returntrueelseifparams[: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."}elsedata={'err'=>"[#{params[:code]}] is not a valid Zipcode."}endrendertext: data.to_jsonendendendAnd 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.
Initial Release