クラス
# 値を設定(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