diff --git a/lib/geocoder/stores/active_record.rb b/lib/geocoder/stores/active_record.rb index 7c99e055344794a29b0a0e737e6da05a9068243d..0f2187a07f6d6e8c1ed02e49c41a831d9c577525 100644 --- a/lib/geocoder/stores/active_record.rb +++ b/lib/geocoder/stores/active_record.rb @@ -131,7 +131,11 @@ module Geocoder::Store distance_column = options.fetch(:distance_column) { 'distance' } bearing_column = options.fetch(:bearing_column) { 'bearing' } - b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options) + # If radius is a DB column name, bounding box should include + # all rows within the maximum radius appearing in that column. + # Note: performance is dependent on variability of radii. + bb_radius = radius.is_a?(Symbol) ? maximum(radius) : radius + b = Geocoder::Calculations.bounding_box([latitude, longitude], bb_radius, options) args = b + [ full_column_name(latitude_attribute), full_column_name(longitude_attribute) @@ -142,7 +146,16 @@ module Geocoder::Store conditions = bounding_box_conditions else min_radius = options.fetch(:min_radius, 0).to_f - conditions = [bounding_box_conditions + " AND (#{distance}) BETWEEN ? AND ?", min_radius, radius] + # if radius is a DB column name, + # find rows between min_radius and value in column + if radius.is_a?(Symbol) + c = "BETWEEN ? AND #{radius}" + a = [min_radius] + else + c = "BETWEEN ? AND ?" + a = [min_radius, radius] + end + conditions = [bounding_box_conditions + " AND (#{distance}) " + c] + a end { :select => select_clause(options[:select], diff --git a/test/db/migrate/001_create_test_schema.rb b/test/db/migrate/001_create_test_schema.rb index 649f99b81ce7ce8931ecdc915e351eb239b4b748..dfbf7b8e69262d8e850f9059f33fd76d07fa1fc3 100644 --- a/test/db/migrate/001_create_test_schema.rb +++ b/test/db/migrate/001_create_test_schema.rb @@ -15,6 +15,7 @@ class CreateTestSchema < superclass t.column :address, :string t.column :latitude, :decimal, :precision => 16, :scale => 6 t.column :longitude, :decimal, :precision => 16, :scale => 6 + t.column :radius_column, :decimal, :precision => 16, :scale => 6 end end diff --git a/test/test_helper.rb b/test/test_helper.rb index e9667f5f34694912fa959cbbfdd4e4c3ab883402..b51b77ea9053748a04a8cb7f6d84afcc557b06c3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -75,6 +75,10 @@ else def primary_key :id end + + def maximum(_field) + 1.0 + end end end end diff --git a/test/unit/near_test.rb b/test/unit/near_test.rb index 53401f4b0e50f133d66db189bd0b76e42c8320df..7ba3506b317a95631634b68fd0558eb57558c979 100644 --- a/test/unit/near_test.rb +++ b/test/unit/near_test.rb @@ -18,6 +18,13 @@ class NearTest < GeocoderTestCase assert_match(/BETWEEN \? AND \?$/, result[:conditions][0]) end + def test_near_scope_options_includes_radius_column_max_radius + omit("Not applicable to unextended SQLite") if using_unextended_sqlite? + + result = Place.send(:near_scope_options, 1.0, 2.0, :radius_column) + assert_match(/BETWEEN \? AND radius_column$/, result[:conditions][0]) + end + def test_near_scope_options_includes_radius_default_min_radius omit("Not applicable to unextended SQLite") if using_unextended_sqlite?