Edited at

MySQL+ActiveRecord環境で絵文字に対応したお話

More than 1 year has passed since last update.

mixiグループ Advent Calendar 2017 の21日目です。

XFLAGスタジオ CRE(Customer Reliability Engineering)チームの @njin です。


:triangular_flag_on_post: はじめに

CREチームの業務の一つに、カスタマーサポート(CS)スタッフ向けの管理画面(CSツール)の開発があります。

今回は最近実装したCSツールの機能で起きた問題とその解決方法についてまとめました。

CREとは?CREチームって何やってるの?など

ご興味を持っていただけた方は、こちらの記事もご覧になってみてください。

CREチームのメンバーがAdvent Calendarに参加しております :smile:

CREチームを設立しました!(@otoyo)

アプリケーションサーバに引きこもるDBを自立させてDocker Composeで開発環境を作る(@upscent)

なれる!CRE(@nukosuke)

フェイルセーフの観点から顧客信頼性を確保しよう(@manji602)


:triangular_flag_on_post: 機能の概要

XFLAGスタジオのCSでは、多くのプロダクトでCS対応にZendeskというCRMを使用しています。

Zendeskではお問い合わせ1件1件を「チケット」と呼ばれるものに紐づけて管理しています。

詳細は書けないのですが、今回追加した機能の簡略化したフローは以下です。

1. ZendeskからAPIでチケット単位のデータ(JSON形式)を取得

2. 取得したチケットのデータをDBへ保存

3. 保存したデータを整形し、CSツールで表示

チケットにはお問い合わせの内容やアカウントのID・ニックネーム・ランクなどが記載されたメール本文が含まれており、ここである問題が発生しました。


:triangular_flag_on_post: 問題

CSスタッフから連絡があり、CSツールでユーザーの情報が途中から表示されていないというのです。

さらにニックネームに絵文字が含まれていると聞き、嫌な予感がしました…

DBのデータを確認すると、ニックネームから後ろが切れています。

[1] pry(main)> ticket.body

=> "【お問い合わせ内容】\r\nhogehogeについて\r\n\r\n【項目1】\r\ntest\r\n\r\n【項目2】\r\ntest\r\n\r\n【ニックネーム】\r\n"

テーブルの定義を確認すると、

> SHOW CREATE TABLE tickets;

| tickets | CREATE TABLE `tickets` (
`body` text NOT NULL,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

そうですよね。

テーブル作成時にCHARSETをutf8mb4に設定していないことが原因でした。

テーブルやカラムがutf8mb4に対応していない場合、絵文字(4バイト文字)が含まれているとそれ以降がカットされてしまいます。

[1] pry(main)> ticket = Ticket.create(body: "すし🍣すし")

[2] pry(main)> ticket.body
=> "すし"


:triangular_flag_on_post: 解決方法

追加した機能がすでに稼働している状況だったため、テーブルの作り直しではなく、CSの業務時間外に change_column を使ったカラム変更でCHARSETをutf8からutf8mb4へ変更することにしました。

change_column でCHARSETを変更するための記法がわからず少々苦戦しましたが、以下の記述で変更することができました。

class ChangeColumn < ActiveRecord::Migration

def self.up
change_column :tickets, :body, "text CHARSET utf8mb4"
...
end
end

[1] pry(main)> Ticket.create(body: "すし🍣") 

SELECT * FROM tickets;

+----+------------------------------+
| id | body |
+----+------------------------------+
| 1 | すし???? |
+----+------------------------------+

絵文字以降も保存されるようになりましたが、文字化けした状態で保存されてしまいました。

そこで、RailsとMySQLでiOSの絵文字に対応(UTF8MB4化)した話を参考に、ActiveRecordでMySQLへ接続する際のCHARSETをutf8mb4に設定することで解決しました。


config/database.yml

development:

encoding: utf8mb4

test:
encoding: utf8mb4

production:
encoding: utf8mb4


[1] pry(main)> Ticket.create(body: "すしすし🍣🍣")

SELECT * FROM tickets;

+----+------------------------------+
| id | body |
+----+------------------------------+
| 1 | すし???? |
| 2 | すしすし🍣🍣 |
+----+------------------------------+

文字化けせずに保存できました。


:triangular_flag_on_post: 終わりに

CSツールに不具合が発生しCSツールが停止すると、CSスタッフは対応ができなくなり、それはそのままユーザーさんへの返信の遅れに直結します。

CREチームのメンバーとして、より速く・正確なCS対応のサポートをしていけるように、CSツールの開発についても「より速く・正確な」を意識して取り組んでいきたいと思います。


参考URL

RailsとMySQLでiOSの絵文字に対応(UTF8MB4化)した話