Reputation: 48545
Has anyone done this? I'm confused at how I can make this work, first off I have my user model
Geocoding with it works fine in IRB, just can't figure out how to get it to work in my project.
Trying to use some examples from the readme here: http://github.com/andre/geokit-rails/tree/master.
Anyhow here is what I have:
class User < ActiveRecord::Base
# geokit
acts_as_mappable
after_save :locate
def locate
location = Geokit::Geocoders::MultiGeocoder.geocode("12.12.12.12")
end
end
This corresponds with my save action in my userController
, I need to do this after save because authlogic provides the IP after it saves the user or session. I think eventually I'll make it a background process, but till then how can I get this to work? I have a location column in the user model that I'll store the results of geocode()
Also right now I just have some arbitrary IP address "12.12.12.12" but it should actually be current_login_ip
Upvotes: 2
Views: 3162
Reputation: 3820
For one of my current projects I accomplished something very similar to what you are trying to do. The big thing to consider is that you do not want to do a new geocoding request every time a model is saved. It is rather time consuming and inefficient to do if you do not need to get new geocoordinates every time.
Also geocoding results obtained from IP addresses are highly inaccurate. Sometimes you will get decent results, but many time you will get coordinates of some data center in another nearby town. If you are looking for regional accuracy, IP geocoding accuracy may be good enough for what you're trying to do.
This is how I tackled the problem of not rerequesting geocoding if the attributes had not changed:
require 'us_states' # this is just an array of states and abbreviations
include Geokit::Geocoders
class Location < ActiveRecord::Base
acts_as_mappable
validates_presence_of :name, :address_1, :city, :state, :zip
validates_format_of :zip, :with => /^([0-9]{5})(-[0-9]{4})?$/
validates_inclusion_of :state, :in => US_STATES_ABRS
before_save :get_geo_coords
# request_geocoding attribute is intended to help with unit testing
attr_accessor_with_default :request_geocoding, true
private
def get_geo_coords
# if lat and lng are already defined
if self.lat && self.lng && self.id
# find existing location
l = Location.find(self.id)
# and if location params are the same as existing location
# then we do not need to request geocords again
loc_attrs = %w{address_1 address_2 city state zip}
if loc_attrs.all? {|attr| self.attribute_for_inspect(attr) == l.attribute_for_inspect(attr)}
self.request_geocoding = false
end
end
if self.request_geocoding
# Request new geocoding
loc = MultiGeocoder.geocode("#{self.address_1}, #{self.city}, #{self.state}, #{self.zip}")
if loc.success
self.lat = loc.lat
self.lng = loc.lng
else
errors.add_to_base("Unable to geocode your location. Are you sure your address information is correct?")
end
end
end
end
Upvotes: 4
Reputation: 4657
Check out this site:
http://geokit.rubyforge.org/readme.html
Scroll down to the IP Geocoding and IP Geocoding Helper sections.
"You can obtain the location for an IP at any time using the geocoder as in the following example:"
location = IpGeocoder.geocode('12.215.42.19')
"where Location is a GeoLoc instance containing the latitude, longitude, city, state, and country code. Also, the success value is true."
Once you get your GeoLoc, just pull your User model, set its long/lat columns and save it.
GeoLoc doc: http://geokit.rubyforge.org/api/geokit-gem/Geokit/GeoLoc.html
Am I missing something?
Upvotes: 2
Reputation: 14354
Haven't used geokit myself so can't comment. But thought that I should mention that HTML 5 supporting browsers (e.g. Firefox 3.5) support the geolocation API in case you weren't aware.
Upvotes: 2