JP Silvashy
JP Silvashy

Reputation: 48545

Geokit and Authlogic, geocoding the users ip address when they create a user

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

Answers (3)

Sean McCleary
Sean McCleary

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

cakeforcerberus
cakeforcerberus

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

timbo
timbo

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

Related Questions