Reputation: 256
I've got a service object which has several validations that validate two params. Everything works fine until these params are "". In this case, even though I validate their presence, later validations raise errors. How can I make my code validate the presence first and then, only if the values are present, continue the validations?
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
Upvotes: 0
Views: 84
Reputation: 263
Based on your comment above, it sounds like you never want the from or till to be nil so remove allow_nil: true
. Then just add a conditional to the other validations as suggested by 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. don't use and
over &&
unless you know why (suggested by Rahul). &&
is better in nearly all cases. Difference between "and" and && in Ruby?
Upvotes: 1
Reputation: 5995
You could do something like this:
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
Upvotes: 1