Decoupling Location from Users and Rails Geocoder

69 Views Asked by At

In our app we originally had User records with latitude/longitude and that worked fine. As we've gotten bigger and have more people using it, the number of location updates/checks has gotten large and I thought we could lighten the load by decoupling location from the User record: can update and check location independently of the User record without blowing away serializer cache on User data every X seconds we update location...

However this has led to an interesting problem: When trying to find Users near a certain location we're now slightly screwed. When latitude/longitude are coupled to User, you can simply do User.near(@geocoded_record) and have a distance sorted list of Users. With Location being independent it gets harder and I'm looking for advice on how to properly query this.

I tried User.some_scopes.joins(:location).merge(Location.near(@geocoded_record)) but that returns an ActiveRecord_Relation with "User records" that only contain a nil id, latitude, and longitude... This DOES NOT happen when applying any other sort of scope/query to the Location merge for some reason.

So... Anyone have a suggestion on the best way to fetch User records sorted by distance to a geocoded record through the association without going back to having latitude/longitude directly on User?

2

There are 2 best solutions below

1
dtakeshta On BEST ANSWER

joins and near with Geocoder produce some unexpected results.

We faced the same issue, and created a scope and that seems to be working fine for us.

https://github.com/alexreisner/geocoder/issues/627

dkniffin provides the scopes below.

1
Ernesto G On

I had the same problem recently, in my case I have a Travel model and a Destination model which contains the lat and long values for the travel.I finally got it working like that, probably not the best in terms of optimization:

The scope for Travel:

scope :near_of, ->(target_lat, target_lng) { joins(:destination).merge(Destination.near([target_lat, target_lng], 3)) }

And the controller:

travels = Travel.includes(:destination).near_of(params[:destination_latitude], params[:destination_longitude])