LoginSignup
2
1

[Rails,位置情報] activerecord-mysql2spatial-adapterの使い方

Last updated at Posted at 2020-01-17

静岡市でフリーランスでWeb開発しているkazuomatzです。

Rails + MySQLで位置情報を扱う需要は、少なからずあるかと思います。

Rails + MySQLで位置情報を扱う場合、activerecord-mysql2spatial-adapterが定番のGemかと思うのですが、このGemの開発が止まっていて、Railsのバージョンアップのたびに、有志の開発者の方が本家からBranchしたバージョンを独自リリースしている状態というエントリーを記事にしたのですが、あまり反響がなかったので、そういう需要はもはやないのかなと思っておりました。

そんな中、この記事を見た方から、そもそもactiverecord-mysql2spatial-adapterの使い方がまとめれているところがあまりないという問い合わせがあったので、簡単に書き留めておきます。

こちらの記事に、Rails 4.2, 5.0, 5.1, 6.0に対応したGemfileの書き方を記述してあります(Rails6.0の対応については、僕がやりました)。こちらを参照にGemfileを記述して、bundle installします。

config/database.yml

adapterをmysql2spatialにする。ここがポイントです。

config/database.yml
default: &default
  adapter: mysql2spatial
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: xxxx
  password: xxxxx
  socket: /tmp/mysql.sock
 :
 :
 :

マイグレーションファイル

位置情報を含むモデルを作成するためのマイグレーションファイルです。
t.point (t.geometry でもOK)型として宣言します。nullは許容しないようにします。
また、インデックスを作成する場合は、spatial: trueとします。

MySQL 5.6以前の場合、spatial: trueの指定をする場合は、ストレージエンジンがMyISAMである必要があります。MySQL 5.7以降であればInnoDBでOKです。

db/migrate/xxxxxxxxxxxxx.rb
class CreateLocations < ActiveRecord::Migration[6.0]
    def change
	    create_table :locations do |t|
        t.string :name, comment: 'スポット名称'
        t.point :geom, null: false, comment: '緯度経度'
    end
    add_index :locations, :geom, spatial: true
end

Pointクラスを作る

Geometry型に緯度経度を設定するために便利なPointクラスを作っておきます。

Point.rb
# Geometry型に緯度経度を設定するためのPointクラス
class Point
	def self.from_x_y(x, y)
		x.present? && y.present? ? "POINT(#{x} #{y})" : nil
	end
end

緯度経度の設定と参照

あとは、以下のようにすれば、設定と参照が可能になります。

location.rb
location = Location.new
location.name = '東京駅'
location.geom = Point.from_x_y( 139.767125, 35.681236 )
location.save!

# 緯度経度参照
p location.geom.x   # -> 139.767125
p location.geom.y   # -> 35.681236

2023年9月更新

ことの発端は、AWSのRDSがMySQL5.7を年内にサポートを打ち切りにするという話から。
これまで、いろいろなWebサービスをactiverecord-mysql2spatial-adapterを使って開発してきましたが、MySQL5.7をいよいよMySQL8.0に移行する必要が出てきました。

Rails6.0については、こちらに書きましたが、本家からforkさらたリポジトリをさらにforkして何とか対応した経緯があります。

今回、Rails4.2、Rails5.0、Rails5.1で開発されたプロジェクトのデータベースをMySQL8.0に移行して検証したら、位置情報系のカラムの参照や更新でエラーが発生することが判明しました。

Mysql2::Error: FUNCTION some_scheme.GeomFromWKB does not exist.

この件についてはこちらに詳しく書きました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1