読者です 読者をやめる 読者になる 読者になる

ClearDB に文字コード utf8mb4 で保存する

環境:

ruby: 2.2.0  
Rails: 4.1.8  
ClearDB(MySQL): 5.5.40  

Heroku の MySQL アドオン「ClearDB」で文字コードutf8mb4で保存する方法についてメモ。

Rails + MySQLutf8mb4を扱う方法は以前書いた。

ClearDB ではデフォルトのキャラクタセットは以下のように UTF8 になっている。

mysql> show create database heroku_1234567890abcde;
+------------------------+---------------------------------------------------------------------------------+
| Database               | Create Database                                                                 |
+------------------------+---------------------------------------------------------------------------------+
| heroku_1234567890abcde | CREATE DATABASE `heroku_1234567890abcde` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+------------------------+---------------------------------------------------------------------------------+

mysql> show variables like 'character\_set\_%';
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| character_set_client     | utf8   |
| character_set_connection | utf8   |
| character_set_database   | utf8   |
| character_set_filesystem | binary |
| character_set_results    | utf8   |
| character_set_server     | latin1 |
| character_set_system     | utf8   |
+--------------------------+--------+

絵文字を扱いたいのでutf8mb4に変更したい。
しかしmy.cnfは触れないし、RDS の DB パラメーターグループのようなもので変更できる手段もなさそう。

なので ActiveRecord が発行するテーブルの create 文にオプションでキャラクタセットを追加してテーブル単位にutf8mb4を設定するように、またクライアント側の接続 URL のキャラクタエンコーディングutf8mb4を追加して対応した。

ClearDB を使うまでの手順は以前書いたとおりに進める。

1. DBの接続URLを変更

Heroku 上の Rails アプリから DB に接続するための URL としてconfig/database.ymlに書かれた設定ではなく Heroku の環境変数DATABASE_URLが使用される。なのでこの URL にencoding=utf8mb4を追加する。

変更前:

$ heroku config | grep DATABASE_URL
CLEARDB_DATABASE_URL:  mysql://<username>:<password>@<host>/<database>?reconnect=true
DATABASE_URL:          mysql2://<username>:<password>@<host>/<database>?reconnect=true

変更:

$ heroku config:set DATABASE_URL="mysql2://<username>:<password>@<host>/<database>?reconnect=true&encoding=utf8mb4"

COLLATE も指定する場合

$ heroku config:set DATABASE_URL="mysql2://<username>:<password>@<host>/<database>?reconnect=true&encoding=utf8mb4&collation=utf8mb4_general_ci"

変更後:

$ heroku config | grep DATABASE_URL
CLEARDB_DATABASE_URL:  mysql://<username>:<password>@<host>/<database>?reconnect=true
DATABASE_URL:          mysql2://<username>:<password>@<host>/<database>?reconnect=true&encoding=utf8mb4

2. テーブル作成のマイグレーションファイルにオプション追加

以下のようにマイグレーションファイルのcreate_tableしている部分にオプションとして CHARSET を追加する。

class CreateArticles < ActiveRecord::Migration
  def change

    create_table :articles, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4' do |t|
    # COLLATE も指定する場合
    # create_table :articles, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci' do |t|
      t.string :title
      t.string :content

      t.timestamps
    end
  end
end

3. ClearDB にテーブルを作成

変更をコミットして Heroku にプッシュしてデプロイする。
デプロイ完了後、テーブルがまだ未作成ならheroku run rake db:migrateで作成、作成済みならheroku run rake db:migrate:resetを実行して ClearDB にテーブルを再作成する。

ClearDB に直接接続する

$ mysql -u <username> -p -h <host> -D <database>

確認

mysql> show create database heroku_1234567890abcde;

+------------------------+------------------------------------------------------------------------------------+
| Database               | Create Database                                                                    |
+------------------------+------------------------------------------------------------------------------------+
| heroku_1234567890abcde | CREATE DATABASE `heroku_1234567890abcde` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+------------------------+------------------------------------------------------------------------------------+


mysql> show create table articles;

CREATE TABLE `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `content` varchar(255) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4


mysql> show variables like 'character\_set\_%';
+--------------------------+---------+
| Variable_name            | Value   |
+--------------------------+---------+
| character_set_client     | utf8    |
| character_set_connection | utf8    |
| character_set_database   | utf8mb4 |
| character_set_filesystem | binary  |
| character_set_results    | utf8    |
| character_set_server     | latin1  |
| character_set_system     | utf8    |
+--------------------------+---------+

これでutf8mb4で保存できるようになった。