If you get error like this one:
Mysql2::Error: Incorrect string value: '\xF0\x9F\x99\x82'
it means that you use verion of Mysql with settings that does not support full Unicode. Changing that in Ruby on Rails should be fairly simple:
class ChangeEncoding < ActiveRecord::Migration[5.0] def change config = Rails.configuration.database_configuration db_name = config[Rails.env]["database"] collate = 'utf8mb4_polish_ci' char_set = 'utf8mb4' execute("ALTER DATABASE #{db_name} CHARACTER SET #{char_set} COLLATE #{collate};") ActiveRecord::Base.connection.tables.each do |table| execute("ALTER TABLE #{table} CONVERT TO CHARACTER SET #{char_set} COLLATE #{collate};") end end end
However you might encounter following error:
Specified key was too long; max key length is 767 bytes
767 bytes is the stated prefix limitation for InnoDB tables.
To fix that you need to:
- Update your database.yml file
- Upgrade to MySQL 5.7 or edit your my.cnf to enable innodb_large_prefix
- Change row format to DYNAMIC
- Alter the database and all the tables using Ruby on Rails migration
Database.yml
You need to change your encoding and collation for ActiveRecord:
production: encoding: utf8mb4 collation: utf8mb4_polish_ci
MySQL my.cnf
Edit my.cnf and add following lines:
innodb_large_prefix=on innodb_file_format=barracuda innodb_file_per_table=true
DYNAMIC row format
If you don't do this, you will probably (if you have enough indexes) end up with this error:
767 bytes is the stated prefix limitation for InnoDB tables
To change row format, you need to run following query for each table:
ALTER TABLE table_name ROW_FORMAT=DYNAMIC;
However, you don't need to do this manually - below you will find a Ruby on Rails migration that will do everything that is required to make things going.
Complex migration to set everything as it should be in the MySQL database
class ChangeEncoding < ActiveRecord::Migration[5.0] def change config = Rails.configuration.database_configuration db_name = config[Rails.env]["database"] collate = 'utf8mb4_polish_ci' char_set = 'utf8mb4' row_format = 'DYNAMIC' execute("ALTER DATABASE #{db_name} CHARACTER SET #{char_set} COLLATE #{collate};") ActiveRecord::Base.connection.tables.each do |table| execute("ALTER TABLE #{table} ROW_FORMAT=#{row_format};") execute("ALTER TABLE #{table} CONVERT TO CHARACTER SET #{char_set} COLLATE #{collate};") end end end
After you run this migration, everything should work fine.