【问题标题】:Rails 3 - how to skip validation rule?Rails 3 - 如何跳过验证规则?
【发布时间】:2012-09-21 14:26:54
【问题描述】:

我对注册表有这个验证规则:

  validates :email, 
    :presence => {:message => 'cannot be blank.'}, 
    :allow_blank => true, 
    :format => {
      :with => /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/, 
      :message => 'address is not valid. Please, fix it.'
    }, 
    :uniqueness => true

此规则检查,如果用户填写注册表单电子邮件地址(+其正确格式)。

现在我正在尝试添加使用 Twitter 登录的机会。 Twitter 不提供用户的电子邮件地址。

在这种情况下如何跳过上面的验证规则?

【问题讨论】:

  • 当我通过 twitter 进行身份验证时,我将用户重定向到注册页面并要求他填写遗漏的字段。稍后您可能需要电子邮件来处理某些事情。例如用于向用户发送邮件。

标签: ruby-on-rails ruby validation twitter model


【解决方案1】:

我不确定我的答案是否正确,只是想提供帮助。

我认为您可以向this question 寻求帮助。如果我为您的问题修改接受的答案,它将类似于(免责声明:我无法测试以下代码,因为 env 在我现在正在工作的计算机中尚未准备好)

validates :email, 
  :presence => {:message => 'cannot be blank.', :if => :email_required? },
  :allow_blank => true, 
  :format => {
    :with => /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/, 
    :message => 'address is not valid. Please, fix it.'
  },
  :uniqueness => true

def email_required?
  #logic here
end

现在,您更新email_required? 方法以确定它是否来自推特!如果来自 twitter,则返回 false,否则返回 true。

我相信,您也需要为 :uniqueness 验证器使用相同的 :if。否则它会。不过,我也不确定:(。对不起

【讨论】:

    【解决方案2】:

    您可以在代码中保存用户时跳过验证。不要使用user.save!,而是使用user.save(:validate => false)。从Railscasts episode on Omniauth学到了这个技巧

    【讨论】:

    • 为什么要跳过所有验证?可能应该运行任何其他验证。
    • 谢谢@JasonNoble。没想到:-)
    【解决方案3】:

    您似乎在这里进行了两个单独的验证:

    • 如果用户提供了电子邮件地址,请验证其格式和唯一性
    • 验证电子邮件地址是否存在,除非是 Twitter 注册

    我会这样做作为两个单独的验证:

    validates :email, 
      :presence => {:message => "..."}, 
      :if => Proc.new {|user| user.email.blank? && !user.is_twitter_signup?}
    
    validates :email, 
      :email => true, # You could use your :format argument here
      :uniqueness => { :case_sensitive => false }
      :unless => Proc.new {|user| user.email.blank?}
    

    其他信息:validate email format only if not blank Rails 3

    【讨论】:

    • is_twitter_signup 是某种方法还是只是在保存/登录时传递了附加变量?谢谢!
    • 是的,is_twitter_signup 将为 twitter 用户返回 true,否则返回 false。
    【解决方案4】:

    跳过个人验证 跳过单个验证需要更多的工作。我们需要在我们的模型上创建一个类似于 skip_activation_price_validation 的属性:

    class Product < ActiveRecord::Base
      attr_accessor :skip_activation_price_validation
      validates_numericality_of :activation_price, :greater_than => 0.0, unless: :skip_activation_price_validation
    end
    

    接下来,只要我们想跳过验证,我们就会将该属性设置为 true。例如:

    def create
       @product = Product.new(product_params)
       @product.skip_name_validation = true
       if @product.save
        redirect_to products_path, notice: "#{@product.name} has been created."
      else
        render 'new'
      end
    end
    
    def update
      @product = Product.find(params[:id])
      @product.attributes = product_params
    
      @product.skip_price_validation = true
    
      if @product.save
        redirect_to products_path, notice: "The product \"#{@product.name}\" has been updated. "
      else
        render 'edit'
      end
    end
    

    【讨论】:

      【解决方案5】:

      最好的办法是:

      它会在用户未从 twitter 登录时验证电子邮件,并在用户从 twitter 登录时跳过电子邮件验证。

        validates :email, 
          :presence => {:message => 'cannot be blank.'}, 
          :allow_blank => true, 
          :format => {
            :with => /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/, 
            :message => 'address is not valid. Please, fix it.'
          }, 
          :uniqueness => true
          unless: Proc.new {|user| user.is_twitter_signup?}
      

      【讨论】:

        猜你喜欢
        • 2011-11-26
        • 2011-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-24
        相关资源
        最近更新 更多