custom validators
Explain
- 透過自訂的 class 做驗證,但必須繼承於 ActiveModel::EachValidator
- 自定義的 class 必須實作 validate_each(record, attribute, value) 方法
- 驗證錯誤訊息必須加入到 record.errors[自定義名稱]
Example
- 目的:將免洗 email 排除,不可用於 user 註冊
- disposable-email-domains.json:內容請參考 ivolo/disposable-email-domains
- delegate 用法:將 get_mail_domain 與 valid? 指向給 self,意思是當呼叫 get_mail_domain 與 valid?,實際上是呼叫 self.get_mail_domain 與 self.valid?
/app/models/user.rb
class User < ActiveRecord::Base
validates :email, ban_disposable: true
end
/lib/validators/ban_disposable_validator.rb
class BanDisposableValidator < ActiveModel::EachValidator
DISPOSABLE_DOMAINS =
JSON.parse(File.read("#{Rails.root}/config/disposable-email-domains.json")) rescue []
delegate :get_mail_domain, :valid?, to: self
def validate_each(record, attribute, value)
error_message = I18n.t 'devise.registrations.messages.invalid_email'
unless valid?(value)
record.errors[:email] << error_message
end
end
def self.valid?(mail)
domain_name = get_mail_domain(mail)
return false if domain_name.nil?
!DISPOSABLE_DOMAINS.include?(domain_name)
end
private
def self.get_mail_domain(mail)
Mail::Address.new(mail).domain rescue nil
end
end