views:

145

answers:

1

I'm using the Geokit plugin to calculate the distance between the current_user and other users (geocoding actually stored in Profile model).

For testing purpose, I created two Users, one in Minneapolis, MN and one in St. Paul, MN. I used the Geokit gem to geocode the Profiles' lat/lng pair in an IRB session.

I changed the Index view to list each Profile's name, location, and lat/lng pair. These values match the values in the database.

I changed the Index view to display the current_user's lat/lng pair. I authenticated as each User to ensure that the current_user's lat/lng pair matched expectations. It did.

I added an instance method to the Profile model, named ll, to return the lat/lng fields as LatLng object:

def ll
  #if lat and lng fields aren't empty
  LatLng.new(self.lat,self.lng) if (!self.lat.nil? && !self.lng.nil?)
end

I changed the query in the ProfileController's Index action to calculate distances between each user and the current_user:

@profiles = Profile.find(:all,
  :conditions => conditions,  # set WHERE clause
  :order => order_by, # set ORDER BY clause
  :origin => current_user.profile.ll,  # calculate distance based on current_user's location
  :units => :miles  # use miles

Finally, I changed the Index view to display the distance between the current_user and each individual user:

<%=h profile.location %> (<%= profile.ll %>) -
<%= profile.distance.to_f.round(1) %> mi

When I authenticated as user A (44.9799654,-93.2638361), the distance calculations were correct:

A (44.9799654,-93.2638361) - 0.0 mi B (44.9444101,-93.0932742) - 8.7 m

However, when I authenticated as user B (44.9444101,-93.0932742), the distance calculations were incorrect:

A (44.9799654,-93.2638361) - 32.8 mi B (44.9444101,-93.0932742) - 41.1 mi

I was able to verify the distance calculations between the 'raw' lat/lng pairs:

a = LatLng.new(44.9799654,-93.2638361)
=> #<Geokit::LatLng:0x1034af778 @lat=44.9799654, @lng=-93.2638361>
>> b = LatLng.new(44.9444101,-93.0932742)
=> #<Geokit::LatLng:0x1034aab88 @lat=44.9444101, @lng=-93.0932742>
>> a.distance_to(b)
=> 8.70261379563918
>> b.distance_to(a)
=> 8.70261379563918

I'm at a loss to explain what is happening. Any ideas would be appreciated.

+1  A: 

What happens if you do:

 @profiles = Profile.find(:all,
  :conditions => conditions,  # set WHERE clause
  :order => order_by, # set ORDER BY clause
  :origin => current_user.profile, # .ll # calculate distance based on current_user's location
  :units => :miles  # use miles

Your error makes me suspicious that there is data rounding/conversion issues going on and the :origin should be capable of picking up the lat and lng directly. You might also want to check (logger.debug) all the types involved right before calling Profile.find(...)

I haven't been able to come up with a simple conversion that gives those particular errors, but that is my suspicion. If that doesn't help, can you add your generated sql to the output? It might be possible to figure it out what's gone wrong based on that.

Edited to add:

Craig, to do debugging of types, give:

logger.debug("lat: #{current_user.profile.lat}  #{current_user.profile.lat.class.to_s} lng: #{current_user.profile.lng} #{current_user.profile.lng.class.to_s}")
logger.debug("lat: #{current_user.profile.ll.lat}  #{current_user.profile.ll.lat.class.to_s} lng: #{current_user.profile.ll.lng} #{current_user.profile.ll.lng.class.to_s}")

a try when you are actually experiencing the error and then look at your development.log. (note: there might be a bug in that code because i'm just typing it into the window, but you get the idea.) Otherwise, you probably should check out what's getting displayed in the SQL query as that would show the post-string conversion numbers.

corprew
THANK YOU! THANK YOU! THANK YOU! It appears to be a conversion issue, but I'll be damned if I can determine what it is. I would like to take a look at the types (logger.debug) and the generated sql. Could you tell me how to do so?
Craig