diff --git a/app/models/concerns/geojson_format_validator.rb b/app/models/concerns/geojson_format_validator.rb index d3a7dc58d..42950c1e2 100644 --- a/app/models/concerns/geojson_format_validator.rb +++ b/app/models/concerns/geojson_format_validator.rb @@ -80,10 +80,14 @@ class GeojsonFormatValidator < ActiveModel::EachValidator when "Point" valid_wgs84_coordinates?(coordinates) when "LineString" - coordinates.many? && valid_coordinates_array?(coordinates) + valid_linestring_coordinates?(coordinates) when "MultiPoint" valid_coordinates_array?(coordinates) - when "Polygon", "MultiLineString" + when "MultiLineString" + coordinates.all? do |linestring_coordinates| + valid_linestring_coordinates?(linestring_coordinates) + end + when "Polygon" valid_polygon_coordinates?(coordinates) when "MultiPolygon" coordinates.all? do |polygon_coordinates| @@ -102,7 +106,12 @@ class GeojsonFormatValidator < ActiveModel::EachValidator end def valid_coordinates_array?(coordinates_array) - coordinates_array.all? { |coordinates| valid_wgs84_coordinates?(coordinates) } + coordinates_array.is_a?(Array) && + coordinates_array.all? { |coordinates| valid_wgs84_coordinates?(coordinates) } + end + + def valid_linestring_coordinates?(coordinates) + valid_coordinates_array?(coordinates) && coordinates.many? end def valid_polygon_coordinates?(polygon_coordinates) diff --git a/spec/models/geojson_format_validator_spec.rb b/spec/models/geojson_format_validator_spec.rb index f05aa5b74..c4b4780f9 100644 --- a/spec/models/geojson_format_validator_spec.rb +++ b/spec/models/geojson_format_validator_spec.rb @@ -159,6 +159,64 @@ describe GeojsonFormatValidator do end end + context "Polygon or MultiLineString geometry" do + it "is not valid with a one-dimensional array of coordinates" do + record.geojson = '{ "type": "MultiLineString", "coordinates": [1.23, 4.56] }' + + expect(record).not_to be_valid + + record.geojson = '{ "type": "Polygon", "coordinates": [1.23, 4.56] }' + + expect(record).not_to be_valid + end + + it "is not valid with a two-dimensional array of coordinates" do + record.geojson = '{ "type": "MultiLineString", "coordinates": [[1.23, 4.56], [7.89, 4.56]] }' + + expect(record).not_to be_valid + + record.geojson = '{ "type": "Polygon", "coordinates": [[1.23, 4.56], [7.89, 4.56]] }' + + expect(record).not_to be_valid + end + end + + context "MultiLineString geometry" do + it "is valid with just one line" do + record.geojson = '{ "type": "MultiLineString", "coordinates": [[[1.23, 4.56], [7.89, 4.56]]] }' + + expect(record).to be_valid + end + + it "is valid with multiple valid lines" do + record.geojson = <<~JSON + { + "type": "MultiLineString", + "coordinates": [ + [[1.23, 4.56], [7.89, 4.56]], + [[10.11, 12.13], [14.15, 16.17]] + ] + } + JSON + + expect(record).to be_valid + end + + it "is not valid if some lines are invalid" do + record.geojson = <<~JSON + { + "type": "MultiLineString", + "coordinates": [ + [[1.23, 4.56], [7.89, 4.56]], + [[10.11, 12.13]] + ] + } + JSON + + expect(record).not_to be_valid + end + end + context "GeometryCollection" do it "is not valid if it doesn't contain geometries" do record.geojson = '{ "type": "GeometryCollection" }'