ActiveRecord extension for MySQL Spatial Data.

Installation

gem 'active_record_mysql_spatial'

Migration

This extension provides some data type methods for ActiveRecord migration and also register those types to the schema.

# frozen_string_literal: true

class CreatePositions < ActiveRecord::Migration[7.2]
  def change
    create_table :positions do |t|
      t.linestring :ls
      t.multilinestring :mls
      t.point :pt

      t.column :tls, :linestring
      t.column :tmls, :multilinestring
      t.column :tpt, :point

      t.timestamps
    end
  end
end

Without this extension, even you use t.column to define the column for the table, you will receive the error message in the schema.rb

# Could not dump table "positions" because of following StandardError
#   Unknown type 'linestring' for column 'tls'

Usage

Point

position = Position.create!(pt: { x: 1, y: 2 })

position = Position.create!(pt: [1, 2])

p position.pt.x # puts x
p position.pt.y # puts y

Linestring

position = Position.create!(ls: [[1, 2], [2, 3]])

p position.ls.coordinates # puts all points
p position.ls.coordinates.first.x # puts x of first point
p position.ls.coordinates.last.y # puts y of last point

Multilinestring

position = Position.create!(mls: [[[1, 2], [2, 3]]])

p position.mls.items # puts all linestrings
p position.mls.items.first.coordinates.first.x # puts x of first point of first linestring
p position.mls.items.last.coordinates.last.y # puts y of last point of last linestring

Custom result class

In your business, you may need to use spatial data for a purpose. To load data and map to the semantic data for your business, create a class and override the method cast_value.

class YourClass < ActiveRecordMysqlSpatial::ActiveRecord::MySQL::Linestring
  attr_reader :sum_x, :sum_y

  private

  def cast_value(value)
    super

    @sum_x, @sum_y = @coordinates.reduce([0, 0]) do |sum, point|
      sum[0] += point.x.to_i
      sum[1] += point.y.to_i
      sum
    end

    self
  end
end

# models/position.rb
class Position < ApplicationRecord
  include ActiveRecordMysqlSpatial::ActsAsSpatial

  acts_as_linestring :ls, serializer: YourClass
end