ruby-on-railsrubygeoipfreegeoip

Autofilling a form with visitor's country using IP address


This is the first time I'm doing this. I have a form for new users (Investor model) and I want it to be that once the form is loaded, based on the visitor's IP, the country field is already filled with the country. I heard of geoip gem. Don't know how to use it. This is what I tried to do. I downloaded GeoIP.dat.gz from http://www.maxmind.com/app/geolitecountry, extracted it and put it into the db folder of my app. I am not sure if I am on the right path.

Gemfile

source 'https://rubygems.org'
gem 'rails', '4.2.1'
gem 'pg'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'

gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'foundation-rails', '~> 5.5.2.1'
gem 'foundation-icons-sass-rails'
gem 'geoip', '~> 1.5.0'

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem 'rails_12factor', group: :production

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
end

environment.rb

# Load the Rails application.
require File.expand_path('../application', __FILE__)

# Initialize the Rails application.
Rails.application.initialize!

config.gem 'geoip'

The following steps shows cannot load such file -- geoip error in the browser. And I can't even move on with trying to interpolate the user's country in the form. Any help will be appreciated. investors_controller.rb

require 'geoip'

class InvestorsController < ApplicationController

  @geoip ||= GeoIP.new("/db/GeoIP.dat")    
  remote_ip = request.remote_ip 
  if remote_ip != "127.0.0.1" #todo: check for other local addresses or set default value
    location_location = @geoip.country(remote_ip)
    if location_location != nil     
      @investor.country = location_location[2]
    end
  end


  def new
    @investor = Investor.new
  end

  def create
    @investor = Investor.new(user_params)
    if @investor.save
        flash.now[:success] = "Welcome, you're now on your way to success!"
        render "/static_pages/welcome"
      InvestorMailer.welcome_email(@investor).deliver_now
    else
        render 'new'
    end
  end

  def update
    if @investor.update_attributes(user_params)
        flash[:success] = "Updated"
    else
        render 'edit'
    end
  end

  private

    def user_params
      params.require(:investor).permit(:name, :email, :country,
                                   :phone)
    end
end

Solution

  • I've had a lot of success with the Geocoder gem. It works almost right out of the box:

    In your Gemfile, add:

    gem geocoder

    Once you bundle install, you can do queries against FreeGeoIP (up to 10,000 per hour) right in your app. Here's an example from console, using Google's DNS IP:

    013 > results = Geocoder.search("8.8.4.4")
    => [#<Geocoder::Result::Freegeoip:0x007fa285fddfc0 @data={"ip"=>"8.8.4.4", "country_code"=>"US", "country_name"=>"United States", "region_code"=>"", "region_name"=>"", "city"=>"", "zip_code"=>"", "time_zone"=>"", "latitude"=>38, "longitude"=>-97, "metro_code"=>0}, @cache_hit=false>]
    
    014 > results.first.data["country_name"]
    => "United States"
    

    There is a lot of other useful data that the Geocoder gem provides as well, as you can see. :)

    I strongly recommend you read the entire Geocoder readme as it will give you tips, suggestions on services you can configure to do address lookup if you wish, as well as practices for testing, etc.

    I'd also suggest once you narrow down which services you want to look at, reading the terms of services for those services (e.g. Google Maps, Bing, etc.) as the readme for the Geocoder gem isn't always up to date with those policies.