2016-09-21 109 views
0

我有兩個驗證:避免重複驗證器

validates :email, format: { with: /\A(.+)@(aol|gmail|office365|outlook|verizon|yahoo)\.com\Z/i }, if: Proc.new { |user| user.imap_server.blank? } 
validates :email, presence: true 
validates :imap_server, presence: true, if: Proc.new { |user| user.email.present? && user.email_invalid? } 


def email_invalid? 
    self.email =~ /\A(.+)@(aol|gmail|office365|outlook|verizon|yahoo)\.com\Z/i 
end 

我展示用戶的形式。它顯示一個email字段,但不顯示imap_server字段。如果email字段中的值與特定的正則表達式不匹配,那麼我想再次顯示它們的形式,同時出現imap_server字段。如果他們輸入imap_server字段的值,那麼我不再需要驗證email字段的正則表達式(儘管它仍然存在)。

感覺就像我複製驗證的問題。 email_invalid?validates :email, format: ...都做同樣的事情。我怎樣才能清理它?

+2

至少您可以將正則表達式提取到本地常量並以此方式重用。 –

回答

1

你可以替換validates :email, format: ...

validate :email_format 

def email_format 
    errors.add(:email, 'format invalid') if imap_server.blank? && email_invalid? 
end 

稍微更行,但您可以在一個地方定義格式驗證。

+0

從控制檯嘗試併發送無效的電子郵件時,這絕不會檢測到「format invalid」消息。 – Donato

+0

你在做'my_record.valid?'對嗎? – SteveTurczyn

+0

是的,即使我使用「[email protected]」的電子郵件,它也會返回true。然而,我在問題中的原始方式,它返回false。 – Donato

0

我懷疑問題在於你正在嘗試檢查驗證結果(email_invalid?),而你仍在執行驗證......你不知道驗證的順序是什麼(頁面上的訂單不是我信賴的東西)...所以解決它的最好方法是將所有這些東西寫入單個驗證方法,例如快速和骯髒的方法:

validates :email_or_imap_server 

def email_or_imap_server 
    email_valid = false # for scoping 
    if email.present? 
    # note: email validation via regex is harder than you think... 
    # google it... 
    email_valid = email.match(/#{VALID_EMAIL_FORMATS}/) 
    if email_invalid 
     errors.add(:email, "email invalid format should be...") 
     errors.add(:imap_server, "email or imap-server must be present") unless imap_server.present? 
    end 
    else 
    errors.add(:imap_server, "either email or imap-server must be present") unless imap_server.present? 
    end 
end 

注:上面的代碼幾乎可以肯定充滿錯誤和錯別字......不要複製/粘貼它幾乎肯定將無法正常工作和邏輯並不完全匹配您v alidations ...但做這樣的事情。