LoginSignup
11
8

More than 5 years have passed since last update.

【Rails 5】utf8 -> utf8mb4 対応【mysql】

Posted at
ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect string value: '...' for column 'body' at row
Mysql2::Error: Index column size too large. The maximum column size is 767 bytes.

「使えない文字が含まれてるよ」
「カラムのサイズがデカすぎる。767バイト以内にして」(合ってる・・?)

rails5で開発中にこのエラーに出くわしたので、ここに対策を記載しておきます。
簡単に言うと上のエラー(1つめ)は絵文字が原因です。
絵文字を含んだ文字列をレコードに格納するには
utf8からutf8mb4にテーブルの構造を変えなきゃならんのですが、
変えたら今度はバイト数の関係で下のエラー(2つめ)が発生します。

環境: ruby 2.5.1, rails 5.2.1, mysql 5.6

データベースの設定を変更する。
$ vim config/database.yml

config/database.ymlを編集
default: &default
  adapter: mysql2
  encoding: utf8mb4 # <= utf8 から utf8mb4 に変更
  charset: utf8mb4 # <= 追加
  collation: utf8mb4_general_ci # <= 追加
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: xxxx
  password: xxxx
  socket: /tmp/mysql.sock

デフォルトではテーブル作成時に
ROW_FORMATがCOMPACTになるので、DYNAMICを指定するようにする。
$ touch config/initializers/ar_innodb_row_format.rb

config/initializers/ar_innodb_row_format.rbを作成
module InnodbRowFormat
  def create_table(table_name, options = {})
    table_options = options.merge(options: 'ENGINE=InnoDB ROW_FORMAT=DYNAMIC')
    super(table_name, table_options) do |td|
      yield td if block_given?
    end
  end
end

ActiveSupport.on_load :active_record do
  module ActiveRecord::ConnectionAdapters
    class AbstractMysqlAdapter
      prepend InnodbRowFormat
    end
  end
end

mysqlの設定を変える。
767バイト以内にするんじゃなくて、設定を変えて767超えても大丈夫なようにする。
ファイルフォーマットをAntelopeからBarracudaに変更。

$ vim ~/.my.cnf

~/.my.cnfの編集
[mysql]
default-character-set=utf8mb4

[mysqld]
character-set-server = utf8mb4
skip-character-set-client-handshake
collation-server = utf8mb4_general_ci
init-connect = SET NAMES utf8mb4
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda
innodb_file_per_table = 1
innodb_large_prefix = 1

↓結果↓

$ bundle exec rails db:migrate

== 20181028110407 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0377s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0161s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0156s
== 20181028110407 DeviseCreateUsers: migrated (0.0696s) =======================

解決!!

参考にさせて頂いた記事
ActiveRecordをutf8mb4で動かす

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8