Skip to content

Commit

Permalink
Merge pull request alexreisner#573 from phallstrom/master
Browse files Browse the repository at this point in the history
Allow passing optional :min_radius value to 'near' searches.
  • Loading branch information
alexreisner committed Dec 28, 2013
2 parents 0ff69b4 + 8c000fd commit 50609ba
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ When querying for objects (if you're using ActiveRecord) you can also look withi

This can also dramatically improve query performance, especially when used in conjunction with indexes on the latitude/longitude columns. Note, however, that returned results do not include `distance` and `bearing` attributes. Note that `#near` performs both bounding box and radius queries for speed.

You can also specify a minimum radius (if you're using ActiveRecord and not Sqlite) to constrain the
lower bound (ie. think of a donut, or ring) by using the `:min_radius` option:

box = Geocoder::Calculations.bounding_box(center_point, distance, :min_radius => 10.5)


Advanced Geocoding
------------------
Expand Down
6 changes: 5 additions & 1 deletion lib/geocoder/stores/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def distance_from_sql(location, *args)
# * +:exclude+ - an object to exclude (used by the +nearbys+ method)
# * +:distance_column+ - used to set the column name of the calculated distance.
# * +:bearing_column+ - used to set the column name of the calculated bearing.
# * +:min_radius+ - the value to use as the minimum radius.
# ignored if database is sqlite.
# default is 0.0
#
def near_scope_options(latitude, longitude, radius = 20, options = {})
if options[:units]
Expand All @@ -131,7 +134,8 @@ def near_scope_options(latitude, longitude, radius = 20, options = {})
if using_sqlite?
conditions = bounding_box_conditions
else
conditions = [bounding_box_conditions + " AND #{distance} <= ?", radius]
min_radius = options.fetch(:min_radius, 0).to_f
conditions = [bounding_box_conditions + " AND (#{distance}) BETWEEN ? AND ?", min_radius, radius]
end
{
:select => select_clause(options[:select],
Expand Down
27 changes: 27 additions & 0 deletions test/near_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,33 @@ def test_near_scope_options_without_sqlite_includes_bounding_box_condition
result[:conditions][0]
end

def test_near_scope_options_without_sqlite_includes_radius_condition
result = Event.send(:near_scope_options, 1.0, 2.0, 5)

assert_match /BETWEEN \? AND \?$/, result[:conditions][0]
end

def test_near_scope_options_without_sqlite_includes_radius_default_min_radius
result = Event.send(:near_scope_options, 1.0, 2.0, 5)

assert_equal 0, result[:conditions][1]
assert_equal 5, result[:conditions][2]
end

def test_near_scope_options_without_sqlite_includes_radius_custom_min_radius
result = Event.send(:near_scope_options, 1.0, 2.0, 5, :min_radius => 3)

assert_equal 3, result[:conditions][1]
assert_equal 5, result[:conditions][2]
end

def test_near_scope_options_without_sqlite_includes_radius_bogus_min_radius
result = Event.send(:near_scope_options, 1.0, 2.0, 5, :min_radius => 'bogus')

assert_equal 0, result[:conditions][1]
assert_equal 5, result[:conditions][2]
end

def test_near_scope_options_with_defaults
result = PlaceWithCustomResultsHandling.send(:near_scope_options, 1.0, 2.0, 5)

Expand Down

0 comments on commit 50609ba

Please sign in to comment.