Quick, no-hack emoji support with MySQL & Rails

If you’re a MySQL user with a charset of utf8, you’ve probably noticed your database isn’t as excited about native emoji as your users are.

The fix is easy though, right? Just migrate your production database to utf8mb4 and presto! Problem solved.

Not exactly. Such a big migration could take a long time if you have a system that’s been running for 3-5 years, not least of which if you’d like those emoji clamoring users to still be able to use your app meanwhile.

You also don’t want to fiddle with index sizes and column lengths, as you must to pull it through.

But what if you don’t need emoji everywhere?

In fact if you’re willing to trade off emojis all over some day in the future for some emojis today, it’s way easier.

For a Rails app it’s a one line change. Here’s how we did it.

At Firmafon (or Firma in the UK) we have a ratings system, which asks people to rate the support call they’ve just had. They can mark it positive or negative, and then optionally add a comment.

We were seeing a bunch of people dress up those comments with the usual emoji suspects. While Ruby handles any UTF-8 string with aplomb, MySQL, however, aforementioned-ly barfed on them.

It seems we needed some way to transform the string contents before they hit MySQL. There’s a myriad of ways to try to approach this. We went for the fast, easy, and built-in way:

class Rating < ActiveRecord::Base
  serialize :comment

After adding this, the comment would automatically roundtrip Marshal before hitting the database.

Then MySQL was happy, and I wrote a test:

class RatingTest < ActiveSupport::TestCase
  test "poop is acceptable" do
    assert_nothing_raised do
      Rating.create! comment: "You're a ✌️ of 💩."

    assert_equal "You're a ✌️ of 💩.", Rating.last.comment