Geocoding Advanced Rails Recipes

Jan 13, 2008 by Andre

I have a geocoding recipe coming out in Pragmatic's Advanced Rails Recipes. The recipe is titled "Finding Things by Location," and it offers how-tos and best practices on using my GeoKit plugin to, well, Find Things by Location. The most recent PDF of the beta book includes my recipe along with over 30 other recipes by community leaders like Chris Wanstrath, Dan Benjamin, and Geoffrey Grosenbach, to name just a few.

Comments

1

Jörg Battermann on Feb 26

Hello there Andre!

long time no 'speak' ;) How's it going? Quick Q... I've been using GeoKit in the app I am currently putting together and I have one little problem:

Basically I have on Location model in the rails app, with the lat & lng fields + an address field.

The model is set to acts_as_mappable and everything works perfectly fine upon instance creation. However, when I edit & update the address-field, the lat & lng fields do not get updated by geokit to the new location. :-/

There are no other filters or anything in this model so I am somewhat confused.

Have you come across this behavior, too?

Cheers,
-J

2

Jörg Battermann on Feb 26

Here's an example:

>> l = Location.find :first
=> Location id: 1, user_id: 1, title: "Home", address: "Union Square, San Francisco, USA", zip: nil, lat: BigDecimal:2288820,'0.49589119E2',12(16), lng: BigDecimal:22887d0,'0.11026219E2',12(16), created_at: "2008-02-25 20:00:57", updated_at: "2008-02-25 23:47:35">
>> l.lat
=> BigDecimal:227fb1c,'0.49589119E2',12(16)
>> l.lng
=> BigDecimal:227edac,'0.11026219E2',12(16)
>> l.address = "93309 Kelheim, Germany"
=> "93309 Kelheim, Germany"
>> l.save
=> true
>> l.lat
=> BigDecimal:23ec914,'0.49589119E2',12(16)
>> l.lng
=> BigDecimal:23e2310,'0.11026219E2',12(16)
>> Location.inspect
=> "Location(id: integer, user_id: integer, title: string, address: string, zip: string, lat: decimal, lng: decimal, created_at: datetime, updated_at: datetime)"


3

Andre Lewis on Feb 26

Hey Jörg,

You're using the auto_geocode option on acts_as_mappable, right? Geocoding on create only (not update) is the correct functionality for auto_geocode. auto_geocode is meant to be a quick-and-easy way to geocode your models, but if you want more control you should roll your own callback. In your case, the below should work. The key is that it uses before_validation instead of before_validation_on create.

Note! This will re-geocode your address *anytime* you trigger validation. If you want to geocode only when the address field has changed, you'll need to manually detect when the address field has changed.

class Location << ActiveRecord::Base
  acts_as_mappable
  before_validation :geocode_address

private
def geocode_address
geo=GeoKit::Geocoders::MultiGeocoder.geocode (address)
errors.add(:address, "Could not Geocode address") if !geo.success
self.lat, self.lng = geo.lat,geo.lng if geo.success
end
end

4

Joerg Battermann on Feb 28

hey there,

yep - I just found it out, too right before checking back here ;)

I'll surely have to optimize the validation/(re-)geocoding behaviour upon validation...but thanks!

-j

5

Art on May 20

Didn't see your chapter in the listings on the book page. Sure it's there? I'd hate to buy the book and not find your recipe =(

6

Andre Lewis on Aug 06

Art: definitely there. There are a ton of great recipes in there, you won't be disappointed!

7

Sean Corbett on Aug 06

Hi Andre,

I patched GeoKit so that acts_as_mappable accepts a option :geo_model. Setting :geo_model to a symbol of an associated model causes distance based sql queries to use lat and lng columns from the associated model.

My specific case: Shift objects which belong_to Store objects. The stores are geocode'able but it would be kind of silly to keep location information for the shifts separately. This is still an open problem in geokit as far as I can tell?

The patch file is located at: http://commonthreadmediallc.com/files/geo_kit_joins.patch

I'm also emailing it to you. Please let me know what you think of the code. I tried to keep with the feel of the rest of acts_as_mappable. If you like it, I'd be happy to send in a few tests and more comments.

Post a comment

 
This is so filters can reject the spam-bots. Thanks!