Permalink
Browse files

Avoid crashes during calculations

Geocoder.coordinates sometimes returns nil which causes crashes in the distance
and bearing calculations. By returning a point array of [ NaN, NaN ] this
distances will be also NaN which seems to be a sensible result. If the argument
to extract_coordinates has an unexpected form, also return [ NaN, NaN ].
  • Loading branch information...
1 parent f5cbf27 commit d81b08b2ca43732601ddd3883db06a6977afb51a @flori flori committed Apr 12, 2012
Showing with 50 additions and 3 deletions.
  1. +21 −3 lib/geocoder/calculations.rb
  2. +29 −0 test/calculations_test.rb
@@ -21,6 +21,9 @@ module Calculations
#
KM_IN_MI = 0.621371192
+ # Not a number constant
+ NAN = defined?(::Float::NAN) ? ::Float::NAN : 0 / 0.0
+
##
# Distance spanned by one degree of latitude in the given units.
#
@@ -270,10 +273,25 @@ def mi_in_km
#
def extract_coordinates(point)
case point
- when Array; point
- when String; Geocoder.coordinates(point)
- else point.to_coordinates
+ when Array
+ if point.size == 2
+ lat, lon = point
+ if !lat.nil? && lat.respond_to?(:to_f) and
+ !lon.nil? && lon.respond_to?(:to_f)
+ then
+ return [ lat.to_f, lon.to_f ]
+ end
+ end
+ when String
+ point = Geocoder.coordinates(point) and return point
+ else
+ if point.respond_to?(:to_coordinates)
+ if Array === array = point.to_coordinates
+ return extract_coordinates(array)
+ end
+ end
end
+ [ NAN, NAN ]
end
end
end
View
@@ -144,4 +144,33 @@ def test_linear_bearing_from_and_to_are_exactly_opposite
l = Landmark.new(*landmark_params(:msg))
assert_equal l.bearing_from([50,-86.1]), l.bearing_to([50,-86.1]) - 180
end
+
+ def test_extract_coordinates
+ result = Geocoder::Calculations.extract_coordinates([ nil, nil ])
+ assert_equal [ Geocoder::Calculations::NAN ] * 2, result
+
+ result = Geocoder::Calculations.extract_coordinates([ 1.0 / 3, 2.0 / 3 ])
+ assert_in_delta 1.0 / 3, result.first, 1E-5
+ assert_in_delta 2.0 / 3, result.last, 1E-5
+
+ result = Geocoder::Calculations.extract_coordinates(nil)
+ assert_equal [ Geocoder::Calculations::NAN ] * 2, result
+
+ result = Geocoder::Calculations.extract_coordinates('')
+ assert_equal [ Geocoder::Calculations::NAN ] * 2, result
+
+ result = Geocoder::Calculations.extract_coordinates([ 'nix' ])
+ assert_equal [ Geocoder::Calculations::NAN ] * 2, result
+
+ o = Object.new
+ result = Geocoder::Calculations.extract_coordinates(o)
+ assert_equal [ Geocoder::Calculations::NAN ] * 2, result
+
+ def o.to_coordinates
+ [ 1.0 / 3, 2.0 / 3 ]
+ end
+ result = Geocoder::Calculations.extract_coordinates(o)
+ assert_in_delta 1.0 / 3, result.first, 1E-5
+ assert_in_delta 2.0 / 3, result.last, 1E-5
+ end
end

0 comments on commit d81b08b

Please sign in to comment.