Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/cookpad/armg

Add MySQL geometry type to Active Record.
https://github.com/cookpad/armg

activerecord geometry hacktoberfest mysql rails rails5 ruby

Last synced: 10 days ago
JSON representation

Add MySQL geometry type to Active Record.

Awesome Lists containing this project

README

        

# Armg

Add MySQL geometry type to Active Record.

[![Gem Version](https://badge.fury.io/rb/armg.svg)](https://badge.fury.io/rb/armg)
[![Build Status](https://github.com/cookpad/armg/workflows/test/badge.svg?branch=master)](https://github.com/cookpad/armg/actions)

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'armg'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install armg

## Usage

```ruby
require 'active_record'
require 'armg'

ActiveRecord::Base.establish_connection(adapter: 'mysql2', database: 'my_db')

ActiveRecord::Migration.create_table :geoms, options: 'ENGINE=MyISAM' do |t|
t.geometry 'location', null: false
t.index ['location'], name: 'idx_location', type: :spatial
end

class Geom < ActiveRecord::Base; end

wkt_parser = RGeo::WKRep::WKTParser.new(nil, support_ewkt: true)
point = wkt_parser.parse('SRID=4326;Point(-122.1 47.3)')
Geom.create!(location: point)

Geom.first
#=> #>
```

## Using WKT

```ruby
Armg.deserializer = Armg::WktDeserializer.new
Armg.serializer = Armg::WktSerializer.new

Geom.create!(location: 'Point(-122.1 47.3)')

Geom.first
#=> #
```

## Using custom deserializer

```ruby
class CustomDeserializer
def initialize
factory = RGeo::Geographic.spherical_factory(srid: 0)
@wkb_parser = RGeo::WKRep::WKBParser.new(factory, support_ewkb: true)
end

def deserialize(wkb)
wkb_without_srid = wkb.b.slice(4..-1)
@wkb_parser.parse(wkb_without_srid)
end
end

Armg.deserializer = CustomDeserializer.new

Geom.take
#=> #>
```

## Using custom serializer

```ruby
class CustomSerializer
def initialize
@wkt_parser = RGeo::WKRep::WKTParser.new(nil, support_ewkt: true)
@wkb_generator = RGeo::WKRep::WKBGenerator.new(type_format: :ewkb, little_endian: true)
end

def serialize(value)
if value.is_a?(String)
value = @wkt_parser.parse(value)
end

srid = "\x00\x00\x00\x00"
srid + @wkb_generator.generate(value)
end
end

Armg.serializer = CustomSerializer.new

Geom.create!(id: 4, location: 'Point(-122.1 47.3)')
```

## Running tests

```sh
docker-compose up -d
bundle install
bundle exec appraisal install
bundle exec appraisal ar61 rake
# bundle exec appraisal ar60 rake
# ARMG_TEST_MYSQL_PORT=10057 bundle exec appraisal ar61 rake # MySQL 5.7
# ARMG_TEST_MYSQL_PORT=10057 ARMG_TEST_MYSQL_ENGINE=InnoDB bundle exec appraisal ar61 rake
```

## Using with [Ridgepole](https://github.com/winebarrel/ridgepole)

You need to extend the TableDefinition class.

```ruby
# ridgepole-geo.rb
module TableDefinitionExtForGeometry
def geometry(*args)
options = args.extract_options!
column_names = args
column_names.each { |name| column(name, :geometry, options) }
end
end
Ridgepole::DSLParser::TableDefinition.prepend(TableDefinitionExtForGeometry)

module DiffExtForGeometry
def normalize_index_options!(opts)
super
opts.delete(:length) if opts[:type] == :spatial
end
end
Ridgepole::Diff.prepend(DiffExtForGeometry)
```

```sh
$ ridgepole -c 'mysql2://[email protected]:10057/armg_test' -r armg -e > Schemafile

$ cat Schemafile
# Export Schema
create_table "geoms", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.geometry "location", null: false
t.string "name"
t.index ["location"], name: "idx_location", length: 32, type: :spatial
t.index ["name"], name: "idx_name", length: 10
end

$ ridgepole -c 'mysql2://[email protected]:10057/armg_test' -r armg,ridgepole-geo -a
Apply `Schemafile`
No change
```

## Limitation on MySQL 8.0

At the moment, armg gem supports only SRIDs with long-lat axis order in MySQL 8.0.
e.g. SRID=3857 (WGS 84 / Pseudo-Mercator -- Spherical Mercator, Google Maps, OpenStreetMap, Bing, ArcGIS, ESRI)

That is, armg does not support SRIDs with lat-long axis order.
e.g. SRID=4326 (WGS 84 -- WGS84 - World Geodetic System 1984, used in GPS)

## Related links

* [rgeo/rgeo: Geospatial data library for Ruby](https://github.com/rgeo/rgeo)
* [MySQL :: MySQL 5.7 Reference Manual :: 11.5.3 Supported Spatial Data Formats](https://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html)