環境:
ruby: 2.2.0 Rails: 4.1.8 ClearDB(MySQL): 5.5.40
Heroku の MySQL アドオン「ClearDB」で文字コードutf8mb4
で保存する方法についてメモ。
Rails + MySQL でutf8mb4
を扱う方法は以前書いた。
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
で保存できるようになった。