diff --git a/lib/geocoder/stores/active_record.rb b/lib/geocoder/stores/active_record.rb index 8a886b79f09e960ad4d280a8c9d58e6870ec3ce0..4153e6ae461df1a1e88c78be1549f0d5cc383e56 100644 --- a/lib/geocoder/stores/active_record.rb +++ b/lib/geocoder/stores/active_record.rb @@ -133,12 +133,12 @@ module Geocoder::Store "POWER(SIN((#{latitude} - #{lat_attr}) * PI() / 180 / 2), 2) + " + "COS(#{latitude} * PI() / 180) * COS(#{lat_attr} * PI() / 180) * " + "POWER(SIN((#{longitude} - #{lon_attr}) * PI() / 180 / 2), 2) ))" - options[:order] ||= "#{distance} ASC" + conditions = ["#{distance} <= ?", radius] default_near_scope_options(latitude, longitude, radius, options).merge( :select => "#{options[:select] || "#{table_name}.*"}, " + "#{distance} AS distance" + (bearing ? ", #{bearing} AS bearing" : ""), - :having => "#{distance} <= #{radius}" + :conditions => add_exclude_condition(conditions, options[:exclude]) ) end @@ -174,11 +174,16 @@ module Geocoder::Store distance = "(#{dy} * ABS(#{lat_attr} - #{latitude}) * #{factor}) + " + "(#{dx} * ABS(#{lon_attr} - #{longitude}) * #{factor})" + b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options) + conditions = [ + "#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] + + [b[0], b[2], b[1], b[3] + ] default_near_scope_options(latitude, longitude, radius, options).merge( :select => "#{options[:select] || "#{table_name}.*"}, " + "#{distance} AS distance" + (bearing ? ", #{bearing} AS bearing" : ""), - :order => distance + :conditions => add_exclude_condition(conditions, options[:exclude]) ) end @@ -186,24 +191,24 @@ module Geocoder::Store # Options used for any near-like scope. # def default_near_scope_options(latitude, longitude, radius, options) - lat_attr = geocoder_options[:latitude] - lon_attr = geocoder_options[:longitude] - b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options) - conditions = \ - ["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] + - [b[0], b[2], b[1], b[3]] - if obj = options[:exclude] - conditions[0] << " AND #{table_name}.id != ?" - conditions << obj.id - end { - :group => columns.map{ |c| "#{table_name}.#{c.name}" }.join(','), - :order => options[:order], + :order => options[:order] || "distance", :limit => options[:limit], - :offset => options[:offset], - :conditions => conditions + :offset => options[:offset] } end + + ## + # Adds a condition to exclude a given object by ID. + # The given conditions MUST be an array. + # + def add_exclude_condition(conditions, exclude) + if exclude + conditions[0] << " AND #{table_name}.id != ?" + conditions << exclude.id + end + conditions + end end ##