Devise - EmailValidatorをカスタマイズする


経緯

  • Deviseで認証するアプリで、Userのemail検証をカスタマイズしたい。
  • うまくいったのでメモ。

やり方

おまじないを一行加える。

class User < ActiveRecord::Base
  #...
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :omniauthable

  TEMP_EMAIL_PREFIX = 'change@me'
  TEMP_EMAIL_REGEX = /\Achange@me/

  # おまじない
  validates :email, :presence => true, :email => true

  #...

EmailValidatorに自分で検証を書き加える。

/app/validators/email_validator.rb
require 'mail'
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    begin
      m = Mail::Address.new(value)
      # We must check that value contains a domain, the domain has at least
      # one '.' and that value is an email address
      r = m.domain!=nil && m.domain.match('\.') && m.address == value

      # Update 2015-Mar-24
      # the :tree method was private and is no longer available.
      # t = m.__send__(:tree)
      # We need to dig into treetop
      # A valid domain must have dot_atom_text elements size > 1
      # user@localhost is excluded
      # treetop must respond to domain
      # We exclude valid email values like <[email protected]>
      # Hence we use m.__send__(tree).domain
      # r &&= (t.domain.dot_atom_text.elements.size > 1)
    rescue Exception => e
      r = false
    end
    record.errors[attribute] << (options[:message] || "is invalid") unless r

    # Reject temporary email address
    record.errors[attribute] << 'must be given. Please give us a real one!!!' unless value !~ User::TEMP_EMAIL_REGEX
  end
end

結果(イメージ)

自分で書いた検証項目を簡単に追加することができた。

資料