モデルのロード/バリデーション時に文字列型の属性値をNFC正規化する
NFD正規化されたUNICODE文字列が入力された時に、合字(濁点付きかな)のレンダリングが不自然になる問題を回避する
# app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base include UnicodeNormalizer end
# frozen_string_literal: true module UnicodeNormalizer extend ActiveSupport::Concern TARGET_COLUMN_TYPES = %i[string text].freeze EXCEPTIONAL_MODEL_NAMES = %w[Hoge].freeze included do after_find :normalize_columns before_validation :normalize_columns end private def normalize_columns # UNICODE正規化の対象外の場合、早期return return if EXCEPTIONAL_MODEL_NAMES.include?(self.class.to_s) target_attribute_names = self.class.columns_hash.select { |_k, v| TARGET_COLUMN_TYPES.include?(v.type) }.keys attributes.each do |k, v| next unless target_attribute_names.include?(k) # unicode_normalizeメソッドを持たない属性値(nil / serialize)をスキップ next unless v.respond_to?(:unicode_normalize) send("#{k}=", v.unicode_normalize(:nfc)) rescue Encoding::CompatibilityError next end end end