LoginSignup
2
2

More than 3 years have passed since last update.

gem ulid-railsはmysql5.7以上じゃないと構文エラーとなる

Last updated at Posted at 2019-09-26

Rails で、 Deviseusers テーブルに ulid を実装するところでハマったので同じ方がいれば。

ULID について - https://qiita.com/kai_kou/items/b4ac2d316920e08ac75a
ulid-rails - https://github.com/k2nr/ulid-rails

バージョン

  • rails: 5.2
  • ruby: 2.6
  • mysql: 5.6 => 5.7

忙しい方

Mysqlのバージョンを 5.7 にすればオッケーです。
結論はこちら

気づくまでの流れ

コード解説

ULID はタイムスタンプ部とランダム部でできているため、時刻情報を持っています。
その情報を created_atGeneratedColumn とすることで変換しいれたいです。

ulid-rails では lib/ulid/rails/patch.rb でその実装がしてあります。

lib/ulid/rails/patch.rb
module ULID
  module Rails
    module Patch
      module Migrations
        def virtual_ulid_timestamp(timestamp_column_name, ulid_column_name)
                  virtual timestamp_column_name,
                  type: :datetime,
                  as: "FROM_UNIXTIME(CONV(HEX(#{ulid_column_name} >> 80), 16, 10) / 1000.0)"
        end
      end
    end
  end
end

コードをざっくり解説すると、
created_atvirtual型 とし、入力( AS の部分)は ulid である id カラムをMysqlHEX 関数で右に 80bit シフトしたのを 16進数 に変換し、それをまた 10進数 に変換し、1000 で割ったのが UNIXTIME となっているのでそれを FROM_UNIXTIME 関数で直しています。

原因

ただし、エラー文がこの AS の部分で構文エラーとなってしまいます。

StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS (FROM_UNIXTIME(CONV(HEX(id >> 80), 16, 10) / 1000.0)))' at line 1: CREATE TABLE `users` (`id` varbinary(16) NOT NULL PRIMARY KEY, `email` varchar(255) DEFAULT '' NOT NULL, `encrypted_password` varchar(255) DEFAULT '' NOT NULL, `reset_password_token` varchar(255), `reset_password_sent_at` datetime, `remember_created_at` datetime, `sign_in_count` int DEFAULT 0 NOT NULL, `current_sign_in_at` datetime, `last_sign_in_at` datetime, `current_sign_in_ip` varchar(255), `last_sign_in_ip` varchar(255), `updated_at` datetime, `deleted_at` datetime, `created_at` datetime AS (FROM_UNIXTIME(CONV(HEX(id >> 80), 16, 10) / 1000.0)))

のうちの

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS (FROM_UNIXTIME(CONV(HEX(id >> 80), 16, 10) / 1000.0)))' at line 1

ここより、「Mysqlのバージョンによって構文のエラー起きとるよ」ってことがわかります。

mysql --version では 5.7 と表示されており、MYSQLドキュメントを確認しても 5.7 では全ての関数が存在しており問題ありません。

ActiveRecordvirtual型 の構文がおかしいのかなとも思い、

db/migrate/add_created_at_to_users.rb
class AddCreatedAtToUsers < ActiveRecord::Migration[5.2]
  def up
    execute "ALTER TABLE users ADD COLUMN created_at datetime AS (
      from_unixtime(conv(hex(`id` >> 80),16,10) / 1000.0)
    )"
  end

  def down
    remove_column :users, :created_at
  end
end

このように直打ちのSQLも試してみましたがうまくいかず・・・・。

気付いたきっかけは SequelPro でアプリのDatabaseに接続してみたら上のタブ部分に( MYSQL5.6~~ )と表示されていたからでした。
このプロジェクトだけなぜかMYSQL5.6が参照されているという・・・・。

結論

以下のコマンドを打って MYSQL のバージョンを 5.7 に変更することで解決します。

$ brew uninstall mysql
$ brew install mysql@5.7
$ mysql.server start
$ mysql --version
$ gem uninstall mysql
$ bundle
$ rails db:migrate

(自動立ち上げの設定はこちら - https://qiita.com/rinkun/items/c1649bcbe9a79bf2b07e)

以上です、自分と同じようにrailsにULIDを導入している中でハマってしまった方のお役に立てれば嬉しいです。

2
2
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
2