2

I use geocode to get country, state and city via IP, but Freegeoip hasn't a good accuracy. I configured geocoder to use google. example:

geocoder.rb

Geocoder.configure do |config|
  config.lookup = :google
  config.api_key = "API_KEY"
  config.timeout = 5
  config.units = :km
end

But geocoder uses Freegeoip and not google. I don't know if I can use google to get country, state and city via IP. Which geocoder provider can uses GEOIP?

my_controller.rb

@result = request.location.to_yaml

view

--- !ruby/object:Geocoder::Result::Freegeoip cache_hit: data: city: Caxias Do Sul region_code: "23" region_name: Rio Grande do Sul metrocode: "" zipcode: "" longitude: "-51.1833" latitude: "-29.1667" country_code: BR ip: 201.22.227.49 country_name: Brazil
Nielsen Rechia
  • 649
  • 1
  • 10
  • 20
  • When you made the change in your initializer, did you restart your web server? – Jesse Wolgamott Jul 04 '12 at 19:45
  • OK... well FWIW: Geocoder uses whatever you tell it to. So if you correctly configure it to use google, it will. – Jesse Wolgamott Jul 05 '12 at 01:43
  • OK...well, So is my configuration wrong? because it's not working, and if it's configured wrong, please tell me where – Nielsen Rechia Jul 05 '12 at 14:11
  • Is geocoder.rb in config/initializers/geocoder.rb ? It's either not there, or you haven't restarted the server (which you said you did). other than that, no clue. if you can publicize the repo, go for that and I'll try to reproduce. – Jesse Wolgamott Jul 05 '12 at 15:10

1 Answers1

4

Nielsen,

While it is great for address geocoding using the configured 'lookup' service, unfortunately the geocoder gem is hardcoded to use only Freegeoip for all IP address lookups. And I agree with you that Freeogeoip has fairly poor accuracy (not good enough for my use case).

From geocoder.rb:

def lookup(query)
if ip_address?(query)
  get_lookup(ip_lookups.first)
else
  get_lookup(Configuration.lookup || street_lookups.first)
end
end

 ##
 # All IP address lookups, default first.
 #
 def ip_lookups
   [:freegeoip]
end

I think that a better solution would be to use the geoip gem (http://geoip.rubyforge.org/) with the free MaxMind GeoCityLite database, or if you need even more accuracy you can get the premium version. I am getting significantly more accuracy with GeoCityLite then Freegeoip, even though Freegeoip claims to be derived from the same original database...

I am using the following GeoIP call to resolve the location for an IP address:

@geoip_city = GeoIP.new('lib/GeoLiteCity.dat').city(request.remote_ip)

There are two things to keep in mind:

  1. This will only work accurately on live requests, as your local network/loopback adapter will not provide an IP that works for the request.remote_ip call.

  2. The flat file lookup is very fast, but I am still not sure if there is any potential for memory leaks or other scalability problems. I am still testing this solution so I will update response if I find anything significant.

kgx
  • 1,195
  • 3
  • 15
  • 26
  • Thanks, freegeoip was down today. This is much better. About your first thing to "keep in mind" there is a question on here about spoofing your ip address for local development. I do it now, it works. In `development.rb` i added #fake ip address for development config.middleware.use('SpoofIp', '209.17.115.61'). And i have a class `spoof_ip.rb` – wuliwong Jun 13 '13 at 19:35
  • `spoof_id.rb` class SpoofIp def initialize(app, ip) @app = app @ip = ip end def call(env) #env['HTTP_X_FORWARDED_FOR'] = nil env['REMOTE_ADDR'] = env['action_dispatch.remote_ip'] = @ip @status, @headers, @response = @app.call(env) [@status, @headers, @response] end end – wuliwong Jun 13 '13 at 19:36
  • I edited my solution based on the comments but you can see the explanation here http://stackoverflow.com/questions/6115589/geocoder-how-to-test-locally-when-ip-is-127-0-0-1 – wuliwong Jun 13 '13 at 19:38