ActiveRecordをutf8mb4で動かす

  • 224
    いいね
  • 5
    コメント
この記事は最終更新日から1年以上が経過しています。

もうMySQL 5.5 GAが出てから一年が経ち、MySQL 5.6 GAもそろそろ出るころだし、新規で作るアプリケーションはutf8mb4でいきたいのでその方法。

まず、mysql2が0.3.11以前のバージョンではutf8mb4に対応してないので、それより新しいバージョンを使う必要があります。

gem 'mysql2', '>= 0.3.12b4'

これでencoding: utf8mb4で接続できるようになります。

つぎにActiveRecord::Migrationでutf8mb4なデータベースを作成するようにコンフィグでcharsetcollationを指定します。

config/database.yml
development:
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
  reconnect: false
  database: kamipo_development

そうすると、schema_migrationsがインデックス張れないエラーでこけます。

Mysql2::Error: Index column size too large. The maximum column size is 767 bytes.: CREATE UNIQUE INDEX `unique_schema_migrations` ON `schema_migrations` (`version`)

MySQL側のinnodb_large_prefixオプションでキープレフィックスを3072バイトまで拡張できるのでmy.cnfで指定します。

my.cnf
[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix

このオプションはROW_FORMATがDYNAMICかCOMPRESSEDのとき有効なので、create_tableメソッドで'ROW_FORMAT=DYNAMIC'がデフォルトで指定されるようにしておきます。

config/initializers/ar_innodb_row_format.rb
ActiveSupport.on_load :active_record do
  module ActiveRecord::ConnectionAdapters

    class AbstractMysqlAdapter
      def create_table_with_innodb_row_format(table_name, options = {})
        table_options = options.merge(:options => 'ENGINE=InnoDB ROW_FORMAT=DYNAMIC')
        create_table_without_innodb_row_format(table_name, table_options) do |td|
          yield td if block_given?
        end
      end
      alias_method_chain :create_table, :innodb_row_format
    end

  end
end

これでとりあえずutf8mb4で動きます!

参考