如何绕过 validates_email_format_of 验证以保存零电子邮件值?

How can I bypass validates_email_format_of validation to save nil email value?

在 Rails 4 应用程序的多个位置,validates_email_format_of gem 是完美的解决方案。但是当电子邮件地址退回时,我想在电子邮件字段中保存一个 nil 值。

在我的 Gemfile 中:

gem 'validates_email_format_of', git: 'https://github.com/alexdunae/validates_email_format_of.git'

在我的用户模型中:

validates_email_format_of :email, :message => 'Email format looks invalid. Did you mistype?'

在我看来:

<%= button_to 'Delete this Email Address', delete_email_addy_admin_path(user.id), data: { confirm: 'Are you sure?'}, class: "btn_danger" %>

在控制器中:

def delete_email_addy
   @user = User.find(params[:id])
   @user.email = nil
   @user.save!
   redirect_to email_bounces_admins_path
end

结果就是我的消息'Email format looks invalid...'产生了。使用 update_attributes 而不是保存或保存!导致回滚到以前的值。

看来你可以使用:

validates_email_format_of :email,
    :message => 'Email format looks invalid. Did you mistype?',
    :allow_nil => true

根据gem documentation,它同时支持:allow_nil:allow_blank选项。所以:

validates_email_format_of :email, 
                          :message => 'Email format looks invalid. Did you mistype?',
                          :allow_nil => true

已编辑 以回答您的跟进

如果您想有时允许 nil 有时不允许,它还支持 :if:unless 选项。您不需要模型了解控制器的任何信息(您也不应该)。您可以只向模型添加一个非持久性布尔属性,然后使用 :if/:unless 来检查它。

型号

class YourModel < ActiveRecord::Base
  attr_accessor :skip_email_validation

  validates_email_format_of :email, 
                            message: 'Email format looks invalid.',
                            unless: -> { skip_email_validation? }
  ...
end

控制器

def delete_email_addy
   @user = User.find(params[:id])
   @user.email = nil
   @user.skip_email_validation = true
   @user.save!
   redirect_to email_bounces_admins_path
end

快速浏览@Karl 的gem 表明它自动执行添加那些非持久属性的过程。如果你有很多情况需要有条件地跳过验证 and/or 不介意额外的 gem,超级的,但对于单个情况,它可能很容易推出你自己的。

使用 allow_nil: true 是允许 nil 的简单处理,但我有一个 validation_skipper gem 可以处理更复杂的需求。

来自我的 Gemfile:

# Rails gem that lets you skip validations
gem 'validation_skipper', '>= 1.3.0', github: 'K-and-R/validation_skipper'

使用这个 gem,您可以针对何时跳过验证有更复杂的逻辑。