クラス

# 値を設定(setter)する際に、指定の方法で正規化した値を設定する。
#
# 宣言方法:string_normalizable :name, :type
# name: カラム名
# type: 正規化タイプ
#
# 正規化タイプはselfメソッドとして「normalize_[type]」の形式で宣言する。
module StringNormalizable
  extend ActiveSupport::Concern

  KATAKANA_SMALL_CHAR_DIC = {
    'ァ' => 'ア', 'ィ' => 'イ', 'ゥ' => 'ウ', 'ェ' => 'エ', 'ォ' => 'オ',
    'ヵ' => 'カ', 'ヶ' => 'ケ', 'ッ' => 'ツ', 'ャ' => 'ヤ', 'ュ' => 'ユ',
    'ョ' => 'ヨ', 'ヮ' => 'ワ'
  }.freeze

  class << self
    def normalize_name(val)
      val if val.blank?
      val = val.to_s

      val = normalize(val)

      val.strip
    end

    def normalize_mail(val)
      val if val.blank?
      val = val.to_s

      val = num_to_hankaku(val)
      val = alpha_to_hankaku(val)
      val = val.tr('@.+_-−', '@.+_-')
      val = compress_space_and_tab(val)

      val.strip
    end

    private

    def num_to_hankaku(val)
      val.tr('0-9', '0-9')
    end

    def alpha_to_hankaku(val)
      val.tr('a-zA-Z', 'a-zA-Z')
    end

    def kigou_to_hankaku(val)
      val.tr('()-−', '()-')
    end

    def compress_space_and_tab(val)
      val.tr(" \t", ' ').gsub(/ +/, ' ')
    end

    def normalize(val)
      val = num_to_hankaku(val)
      val = alpha_to_hankaku(val)
      val = kigou_to_hankaku(val)
      compress_space_and_tab(val)
    end
  end

  class_methods do
    # attr_accessorの変数か判断する必要があるため
    def attributes
      @attributes ||= superclass.respond_to?(:attributes, true) ? superclass.__send__(:attributes) : Set.new
    end

    def attr_accessor(*names)
      super
      attributes.merge(names.map(&:to_sym))
    end

    # setterを拡張する。指定の正規化を通して設定される。
    # @param [Symbol] カラム名
    # @param [Symbol] 正規化タイプ
    def string_normalizable(name, type)
      model_attributes = attributes
      define_method("#{name}=") do |val|
        # modelに存在するカラムは、super、attr_accessorで宣言する変数は、インスタンス変数に設定する
        normalized_val = StringNormalizable.send("normalize_#{type}", val)
        if model_attributes.include?(name)
          instance_variable_set("@#{name}".to_sym, normalized_val)
        else
          super(normalized_val)
        end
      end
    end
  end
end

How to

class User < ApplicationRecord
  include StringNormalizable

  attr_reader :test_mail

  string_normalizable :name, :name
  string_normalizable :test_mail, :mail
end