Railsでメールアドレスのバリデーション
日本で使われているメールアドレスがRFCに準拠していないので、Railsで現実的な最低限のメールアドレスのフォーマットのバリデーションを追加するケースがよくあると思います。
wtf...email...address...validation...@example.com
上記のようなメールアドレスはRailsのデフォルトのメールアドレスのバリデーションでは弾かれますが、このようなメールアドレスを登録できるようにしましょう。
方針
メールアドレスの@よりも前の部分は雑にASCII印字可能文字(0x20〜0x7E
)を許可し、ただしスペース(0x20
)と@(0x40
)は除きます。正規表現で表すと以下のようになります。
[\x21-\x3f\x41-\x7e]+
メールアドレスの@よりも後の部分は、ドメインですね。正規表現で表すと以下のようになります。
(?:[-a-z0-9]+\.)+[a-z]{2,}
2つの正規表現を@でつなげたのが目的の正規表現です。
[\x21-\x3f\x41-\x7e]+@(?:[-a-z0-9]+\.)+[a-z]{2,}
Railsのカスタムバリデーションを作る
Railsのカスタムバリデーションを作りましょう。
app/lib/validators/email_format_validator.rb
class EmailFormatValidator < ActiveModel::EachValidator
# メールアドレスの@よりも前には、ASCII印字可能文字のうちスペース(\x20)と@(\x40)以外を許可する
EMAIL_FORMAT_REGEX = /\A[\x21-\x3f\x41-\x7e]+@(?:[-a-z0-9]+\.)+[a-z]{2,}\z/i
def validate_each(record, attribute, value)
record.errors.add attribute, (options[:message] || :invalid_email) unless valid_email?(value)
end
private
def valid_email?(email)
email =~ EMAIL_FORMAT_REGEX
end
end
これを、Rails起動時に読み込むようにします。
app/config/application.rb
module Sample
class Application < Rails::Application
config.autoload_paths += %W[#{config.root}/lib/validators]
config.eager_load_paths += %W[#{config.root}/lib/validators]
end
end
あとはモデルでバリデーションを利用するだけです。
class User < ApplicationRecord
validates :email, presence: true, email_format: true
end