ユーザー名などのバリデーションに、予約語リストを作って対処していたのですが、ケースセンシティブだったり、単数・複数を個別に書くのが大変だったので、CustomValidatorを作ってみました。
exclusionを使った場合
/app/models/user.rb
validates :title,
exclusion: { in: YAML.safe_load(open("#{Rails.root}/config/exclusion/username.yml", &:read)) }
/config/exclusion/username.yml
# 予約語リスト
- user
- users
- manager
- managers
この場合、単数形・複数形は、自力で書いてるのでいいのですが、大文字小文字まで自力でやるわけには行きません…。
CustomValidatorを使った場合
カスタムバリデータークラスを作成します。
/app/validators/exclusion_extend_validator.rb
# coding: utf-8
# frozen_string_literal: true
# 通常のexclusionに追加で、小文字単数形にしてチェックをする
class ExclusionExtendValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return unless value.present?
list = options[:in]
# 含まれていたらエラー
if list.include?(value)
record.errors.add(attribute, 'is reserved')
# 小文字、単数形に変換して再度チェック
elsif list.include?(value.try(:downcase).try(:singularize))
record.errors.add(attribute, 'is reserved')
end
end
end
上記ファイルを読み込むように、下記追加します。
/config/application.rb
config.autoload_paths += Dir["#{config.root}/app/validators"]
exclusion:
のときと同じように、使います。
/app/models/user.rb
validates :title,
exclusion_extend: { in: YAML.safe_load(open("#{Rails.root}/config/exclusion/username.yml", &:read)) }
大文字/小文字や、単数形/複数形も含めてチェックされるようになります。
※ yamlファイルには、小文字・単数形で書くようにします。
/config/exclusion/username.yml
# 予約語リスト(小文字・単数形)
- user
- manager
これでuser
やusers
、User
、USERS
なども弾かれるようになります。