Rails
MySQL
絵文字
utf8mb4

Mysqlデータベースに絵文字を格納する方法

More than 3 years have passed since last update.


絵文字

絵文字とは語(音形)ではなく、ものや事柄を、絵を文字のように用いて象徴的に示唆したもののことです。


Mysqlデータベースに絵文字を格納したい場合はどうすれば良いか

皆さんが存じると思いますが、mysqlのデフォルトの文字コードはUTF-8ですが、

UTF-8のデータベースに絵文字を格納できないです。

絵文字を格納したい場合はmysqlのデータベースの文字コードをutf8mb4に変更する必要です。


Utf8mb4の設定

utf8mb4をサーポートするバージョンは5.5.3+です。

mysqlのmy.confファイルに以下の設定を追加します。

   # my.conf

[client]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip-character-set-client-handshake

mysqlサーバーを再起動して、文字コードをちゃんと反映されたかどうか、確認します。

   mysql> use sample

Database changed
mysql> show variables like "char%" ;
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

上記のようにcharacter_set_client、character_set_connection、character_set_database、character_set_results、character_set_serverがutf8mb4になったらOKです。


Railsアプリで修正する必要

Railsアプリではデファオルでutf-8文字コードを使うので、utf8mb4を使用するため修正する必要があります。

まず、データベース設定ファイルを修正する。以下のように修正したら、問題なく動くはずです。

   development:

adapter: mysql2
charset: utf8mb4
encoding: utf8mb4
collation: utf8mb4_unicode_ci
reconnect: false

Rails 4+場合上記の設定で動けるが、Rails 3以下を使えば、767バイトに制限されるバグがあります。mysqlはデファオルでインデックスキーのバイト数を767バイトに制限します。Utf8場合は1つ文字が3バイトなので、インデックスキーの文字数が最大255文字です。ですが、Utf8mb4では1つ文字が⒋バイトなので、インデックスキーの文字数が最大191文字しかないです。その原因で、Railsアプリでインデックスを貼る時、エラーが出てしまいます。

修正方法はSchemaStatementsとSchemaMigrationをオーバーライドします。

// SchemaStatement

module ActiveRecord
module ConnectionAdapters # :nodoc:
module SchemaStatements
MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
def initialize_schema_migrations_table
if @config[:encoding] == 'utf8mb4'
ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
else
ActiveRecord::SchemaMigration.create_table
end
end
end
end
end

// SchemaMigration

module ActiveRecord
class SchemaMigration < ActiveRecord::Base
def self.index_name
"#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
end

def self.create_table(limit=nil)
unless connection.table_exists?(table_name)
version_options = {null: false}
version_options[:limit] = limit if limit

connection.create_table(table_name, id: false) do |t|
t.column :version, :string, version_options
end
connection.add_index table_name, :version, unique: true, name: index_name
end
end
end
end

そして、インデックスを貼るmigrationファイルに文字列の文字数を修正します。

 add_index :users, :email, unique: true, length: 191