Rails验证取决于可能不存在的值

时间:2016-03-26 17:50:45

标签: ruby-on-rails validation

我有一个服务对象,它有几个验证两个参数的验证。一切正常,直到这些参数是""。在这种情况下,即使我验证它们的存在,以后的验证也会引发错误。如何让我的代码首先验证存在,然后,只有值存在时,继续验证?

class SubscriptionPause
  include ActiveModel::Model
  extend ActiveModel::Naming

  attr_accessor :paused_from, :paused_till, :params, :id

  validates :paused_from, presence: true, allow_nil: true
  validates :paused_till, presence: true, allow_nil: true

  validate :paused_from_cant_be_later_than_subscription_ends
  validate :paused_from_cant_be_in_the_past
  validate :paused_till_is_later_than_paused_from

  def initialize(params)
    @params = params
    @paused_form = params[:paused_from]
    @paused_till = params[:paused_till]
  end

  def create
    if valid?
      ...
    else
      ...
    end
  end

  private

  def subscription
    @subscription || Subscription.find(params[:id])
  end

  def paused_from_cant_be_in_the_past
    if !paused_from.empty? && paused_from.to_date < Date.today
      errors.add(:paused_from, I18n.t("..."))
    end
  end

  def paused_till_is_later_than_paused_from
    if paused_from > paused_till
      errors.add :paused_from, I18n.t("...")
    end
  end

  def paused_from_cant_be_later_than_subscription_ends
    if !paused_from.empty? && subscription.expire_date < paused_from
      errors.add :paused_from, I18n.t("...")
    end
  end

end

2 个答案:

答案 0 :(得分:1)

你可以这样做:

validate :paused_from_cant_be_later_than_subscription_ends, :if => :params_present?
validate :paused_from_cant_be_in_the_past, :if => :params_present?
validate :paused_till_is_later_than_paused_from, :if => :params_present?

def params_present?
  return params[paused_from].present? and params[paused_till].present?
end

答案 1 :(得分:1)

根据您在上面的评论,听起来您似乎永远不会想要从或从而为零,因此请删除allow_nil: true。然后只需为Rahul

建议的其他验证添加条件
validates :paused_from, presence: true
validates :paused_till, presence: true

validate :paused_from_cant_be_later_than_subscription_ends, if: :params_present?
validate :paused_from_cant_be_in_the_past, if: :params_present?
validate :paused_till_is_later_than_paused_from, if: :params_present?

def params_present?
  paused_from.present? && paused_till.present?
end

P.S。除非您知道原因(Rahul建议),否则不要使用and而不是&&&&几乎在所有情况下都更好。 Difference between "and" and && in Ruby?