Rails で JIS X 0208 に対応する文字だけを扱うようにする


外部システムとの連携時によくあるのが、使用できる文字の問題

とある決済系の外部システムとの連携で、使用可能な全角文字は、JISX0208 ( JIS 非漢字 + JIS 第一水準 + JIS 第二水準 ) だけですって書いてあって、しばらく途方に暮れた後、色々と調べて何とか実装できた。

ざっくりいうと、文字コードを、正規表現でチェックするやり方。

サンプルコード

とりあえず、concerns に作成した

app/models/concerns/character_code.rb
module CharacterCode
  extend ActiveSupport::Concern
  # 使用できる文字は、JISX0208 ( JIS 非漢字 + JIS 第一水準 + JIS 第二水準 ) 
  REGEXP = /\A#{"[ -╂亜-腕弌-熙]".encode("SHIFT_JIS")}+\z/

  def self.jisx0208_include?(target_string)
    REGEXP.match(target_string.encode("SHIFT_JIS")).present?
  rescue Encoding::UndefinedConversionError
    false
  end
end

場合によっては、半角英数字等も OK の場合もあるので、その場合は、正規表現にそのまま追加

app/models/concerns/character_code.rb
module CharacterCode
  extend ActiveSupport::Concern
  # 使用できる文字は、半角英数字と JISX0208 ( JIS 非漢字 + JIS 第一水準 + JIS 第二水準 ) 
  REGEXP = /\A#{"[0-9a-zA-Z -╂亜-腕弌-熙]".encode("SHIFT_JIS")}+\z/

  def self.jisx0208_include?(target_string)
    REGEXP.match(target_string.encode("SHIFT_JIS")).present?
  rescue Encoding::UndefinedConversionError
    false
  end
end

今回は、DBに登録する時点で弾きたかったので、モデルの validate に追加した

app/models/user.rb
class User < ActiveRecord::Base
  include CharacterCode

  validate :validate_last_name_available, if: -> { last_name.present? }
  validate :validate_first_name_available, if: -> { first_name.present? }

  private
  def validate_last_name_available
    errors.add(:last_name, 'に使用できない文字が含まれています') unless CharacterCode.jisx0208_include?(last_name)
  end

  def validate_first_name_available
    errors.add(:first_name, 'に使用できない文字が含まれています') unless CharacterCode.jisx0208_include?(first_name)
  end
end

正規表現を修正すれば、カタカナ[ァ-ヶ]だけとか、ひらがな[ぁ-ん]だけとかも可能。

使用できる文字は下記で調べた

http://ash.jp/code/codetbl2.htm