2016-09-21 6 views
0

У меня есть два валидаций:дублирования Избегайте в Rails валидаторы

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

Да, и он возвращает true, даже если я использую электронную почту '[email protected]'. Тем не менее, оригинальный способ, который у меня есть в вопросе, возвращает 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 алименты ... но делайте что-то подобное.