Write a named scope to fetch the data sorted by distance using Geokit

Recently I had to work on a feature "As a User ISBAT see the Business sorted by distance". We are using Geokit gem for manipulating the location. And we have the models 'Business' has many 'Location's.

I had to fetch the businesses in the order of the distance of the locations from the origin. The origin is the point which we will pass to the method. Since this method should be part of a chained named scope, I had to implement this as a named scope.

After done some searching I found a useful link from pivotallabs. At the end there is one comment from Keith:

named_scope :within, lambda{|o, d|
 origin = o
 distance_sql = self.distance_sql(origin)
 within = d
 {:select => "*, #{distance_sql} as distance",
  :conditions => "#{distance_sql} <= #{within}", 
  :order => 'distance asc'}}


This code helped me to create a named scope which will fetch the businesses in the order of the distance.

The test also passed for this named scope. But in the controller, where I am using this named scope along with other named scopes i,e, chained named scope, the named scope was not working as expected. It was throwing MySql Error with message "distance is undefined".

After done with some searching I found the link which explains that in chain named_scopes only conditions will get added, and selects will get ignored.

Then I tried by changing the 'distance' variable with the distance_sql as the order value. And it worked:

named_scope :by_location, lambda{|origin, within|
 distance_sql = Location.distance_sql(origin)
 {:select => "*",
  :conditions => "#{distance_sql} <= #{within}", 
  :order => '#{distance_sql}', :joins => :locations }}


blog comments powered by Disqus
marked for destruction →
← acts_as_taggable_on gem hav...