Skip to content

Commit

Permalink
Add conversion methods to ease usage (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
teckwan committed Sep 16, 2021
1 parent bee0133 commit e5de86e
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 0 deletions.
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -2,6 +2,7 @@

* Delegation to inner geometry for a feature (#53)
* MultiJson rather than JSON (#46)
* Conversion methods for better integration with core (#56)

### 2.1.1 / 2018-11-27

Expand Down
1 change: 1 addition & 0 deletions lib/rgeo/geo_json.rb
Expand Up @@ -2,6 +2,7 @@

require "rgeo"
require_relative "geo_json/version"
require_relative "geo_json/conversion_methods"
require_relative "geo_json/entities"
require_relative "geo_json/coder"
require_relative "geo_json/interface"
Expand Down
50 changes: 50 additions & 0 deletions lib/rgeo/geo_json/conversion_methods.rb
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module RGeo
# This module serves to provide handy methods when using GeoJSON. The methods
# provided eases the passage between entities and GeoJSON String/Hash.
module GeoJSON::ConversionMethods
# Convert a geometry to a GeoJSON Hash
def as_geojson
GeoJSON.encode(self)
end
alias as_json as_geojson

# Convert a geometry to a GeoJSON String
def to_geojson
::MultiJson.dump(as_geojson)
end
alias to_json to_geojson
end

# These convenience methods are added directly into the module rather than
# including the module above into the Feature::Instance module which is in
# every geometry implementation. This is due to a behavior in ruby versions
# <3.0.2 where dynamically included modules will not be included automatically
# in the ancestor tree.
# See https://bugs.ruby-lang.org/issues/9573 for more information.
module Feature
module Instance
# Convert a geometry to a GeoJSON Hash
def as_geojson
GeoJSON.encode(self)
end
alias as_json as_geojson

# Convert a geometry to a GeoJSON String
def to_geojson
::MultiJson.dump(as_geojson)
end
alias to_json to_geojson
end

module Factory::Instance
# Parses a GeoJSON String/Hash, or an IO object from which
# the JSON string is read and returns the corresponding
# feature. Returns nil if unable to parse.
def parse_geojson(input)
GeoJSON.decode(input, geo_factory: self)
end
end
end
end
3 changes: 3 additions & 0 deletions lib/rgeo/geo_json/entities.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require_relative "collection_methods"
require_relative "conversion_methods"

module RGeo
module CastOverlay
Expand Down Expand Up @@ -45,6 +46,7 @@ module DelegateToGeometry
# engine and features.
class Feature
include DelegateToGeometry
include ConversionMethods

# Create a feature wrapping the given geometry, with the given ID
# and properties.
Expand Down Expand Up @@ -123,6 +125,7 @@ def keys
class FeatureCollection
include Enumerable
include CollectionMethods
include ConversionMethods

# Create a new FeatureCollection with the given features, which must
# be provided as an Enumerable.
Expand Down
45 changes: 45 additions & 0 deletions test/basic_test.rb
Expand Up @@ -283,4 +283,49 @@ def test_feature_cast
point_feature = RGeo::GeoJSON::Feature.new(factory.point(1, 1))
assert poly.contains?(point_feature)
end

def test_feature_to_geojson
json = {
"type" => "Feature",
"geometry" => {
"type" => "Polygon",
"coordinates" => [[[10.0, 20.0], [12.0, 22.0], [-3.0, 24.0], [10.0, 20.0]]]
},
"properties" => {}
}
feature = RGeo::GeoJSON.decode(json)
assert_equal(
json,
feature.as_geojson
)
assert_equal(
'{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[10.0,20.0],[12.0,22.0],[-3.0,24.0],[10.0,20.0]]]},"properties":{}}',
feature.to_geojson
)
end

def test_feature_collection_to_geojson
json = {
"type" => "FeatureCollection",
"features" => [
{
"type" => "Feature",
"geometry" => {
"type" => "Point",
"coordinates" => [10.0, 20.0],
},
"properties" => {}
}
]
}
feature_collection = RGeo::GeoJSON.decode(json)
assert_equal(
json,
feature_collection.as_geojson
)
assert_equal(
'{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[10.0,20.0]},"properties":{}}]}',
feature_collection.to_geojson
)
end
end
29 changes: 29 additions & 0 deletions test/common/conversion_test.rb
@@ -0,0 +1,29 @@
# frozen_string_literal: true

module RGeo
module GeoJSON # :nodoc:
module Tests # :nodoc:
module Common # :nodoc:
module ConversionTests # :nodoc:
def test_geometry_to_geojson
pt = @factory.point(1, 2)
assert_equal(
{ "type" => "Point", "coordinates" => [1.0, 2.0] },
pt.as_geojson
)
assert_equal(
'{"type":"Point","coordinates":[1.0,2.0]}',
pt.to_geojson
)
end

def test_parse_geojson
pt = @factory.point(1, 2)
assert_equal(pt, @factory.parse_geojson(pt.as_geojson))
assert_equal(pt, @factory.parse_geojson(pt.to_geojson))
end
end
end
end
end
end
13 changes: 13 additions & 0 deletions test/geos_capi/conversion_test.rb
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require "minitest/autorun"
require_relative "../../lib/rgeo-geojson"
require_relative "../common/conversion_test"

class GeosConversionTest < Minitest::Test # :nodoc:
include RGeo::GeoJSON::Tests::Common::ConversionTests

def setup
@factory = RGeo::Geos.factory
end
end
13 changes: 13 additions & 0 deletions test/geos_ffi/conversion_test.rb
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require "minitest/autorun"
require_relative "../../lib/rgeo-geojson"
require_relative "../common/conversion_test"

class GeosFFIConversionTest < Minitest::Test # :nodoc:
include RGeo::GeoJSON::Tests::Common::ConversionTests

def setup
@factory = RGeo::Geos.factory(native_interface: :ffi)
end
end
13 changes: 13 additions & 0 deletions test/simple_cartesian/conversion_test.rb
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require "minitest/autorun"
require_relative "../../lib/rgeo-geojson"
require_relative "../common/conversion_test"

class CartesianConversionTest < Minitest::Test # :nodoc:
include RGeo::GeoJSON::Tests::Common::ConversionTests

def setup
@factory = RGeo::Cartesian.simple_factory
end
end
13 changes: 13 additions & 0 deletions test/simple_mercator/conversion_test.rb
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require "minitest/autorun"
require_relative "../../lib/rgeo-geojson"
require_relative "../common/conversion_test"

class MercatorConversionTest < Minitest::Test # :nodoc:
include RGeo::GeoJSON::Tests::Common::ConversionTests

def setup
@factory = RGeo::Geographic.simple_mercator_factory
end
end

0 comments on commit e5de86e

Please sign in to comment.