Rails
MySQL
RDS

Rails + RDS(MySQL)でよくある文字化け事件

More than 3 years have passed since last update.

モデルの生成

たとえば user モデルを作るとします。
すると同時にマイグレーションファイルも生成されますが、これが「ローカルでは動くけどステージング(RDS)では動かない」という事件を引き起こしてくれます。

$ rails g model user name:string email:string
xxxx_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

ローカルでは動くけどステージング(RDS)では動かない

ローカルでは同梱の SQLite3、もしくはそれ用にインストールした MySQL を利用すると思います。
そのローカルで十分検証したのち、ステージング(DB の向け先が RDS の)環境にデプロイすると、周りから「日本語が文字化けしています。調査をお願いします。」という連絡がきます。

原因は RDS(MySQL)の文字コード

RDS(MySQL)の文字コードはデフォルトでは latin1 が使用されるようになっています。
そのため、先ほどのマイグレーションファイルをそのまま適用すると latin1 でカラムが作られてしまって、日本語が扱えないという事件が起こってしまいます。

$ mysql -u xxx -pYYY -h zzz.rds.amazonaws.com
mysql> show create table users \G
 〜 中略 〜
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

対策1:RDS の設定を変更する

AWS コンソールから RDS ->Parameter Groups といって、下記のパラメータを utf8 に修正しましょう。

  • character_set_client
  • character_set_connection
  • character_set_database
  • character_set_results
  • character_set_server

対策2:マイグレーションファイルで charset を指定する

マイグレーションファイルの options で charset を指定します。

xxxx_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table(:users, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8') do |t|  # <--「utf8」を指定
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

付け足し

対策1/対策2ともに、対応前に生成されたテーブルは latin1 のままなので、drop ->create で作り直すか、alter table <テーブル名> convert to charcter set utf8 で変更するような対応が必要になります。

まとめ

どちらの対応でも問題ないですが、場合によってはインフラを変更できないようなプロジェクトも存在すると思うので、MySQL を利用する際は 対策2 の対応を取るような癖をつけておけば良いと思います。