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
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
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
[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で動かす