Help us understand the problem. What is going on with this article?

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

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を導入している中でハマってしまった方のお役に立てれば嬉しいです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした