Help us understand the problem. What is going on with this article?

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ツールで表示

Pasted image at 2017_12_15 10_49 AM.png

チケットにはお問い合わせの内容やアカウントの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化)した話

njin
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした