私の現在のプロジェクトの1つで、私はあなたがやろうとしていることと非常によく似た何かを成し遂げました。考慮すべき重要な点は、モデルが保存されるたびに新しいジオコーディング要求を実行したくないということです。毎回新しい地理座標を取得する必要がない場合は、かなり時間がかかり、非効率的です。
また、IPアドレスから取得したジオコーディングの結果は非常に不正確です。まともな結果が得られることもありますが、多くの場合、近くの別の町にあるデータセンターの座標を取得します。地域の精度を求めている場合、IPジオコーディングの精度は、実行しようとしていることに対して十分である可能性があります。
これは、属性が変更されていない場合にジオコーディングを再要求しないという問題に取り組んだ方法です。
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