1. kamipo

    Posted

    kamipo
Changes in title
+ActiveRecordをutf8mb4で動かす
Changes in tags
+Rails
3.2.8
+MySQL
5.6.8
Changes in body
Source | HTML | Preview
@@ -0,0 +1,62 @@
+
+もうMySQL 5.5 GAが出てから一年が経ち、MySQL 5.6 GAもそろそろ出るころだし、新規で作るアプリケーションはutf8mb4でいきたいのでその方法。
+
+まず、mysql2が0.3.11以前のバージョンではutf8mb4に対応してないので、それより新しいバージョンを使う必要があります。
+
+```ruby:Gemfile
+gem 'mysql2', '>= 0.3.12b4'
+```
+
+これで`encoding: utf8mb4`で接続できるようになります。
+
+つぎにActiveRecord::Migrationでutf8mb4なデータベースを作成するようにコンフィグで`charset`と`collation`を指定します。
+
+```yaml: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'がデフォルトで指定されるようにしておきます。
+
+```ruby: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.reverse_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で動きます!
+
+### 参考
+- [MySQL(InnoDB) で "Index column size too large. The maximum column size is 767 bytes." いわれるときの対策 - かみぽわーる](http://blog.kamipo.net/entry/2012/11/13/102024)