Reputation: 838
I would like to add a conditional custom validation to a model
Rails allows to create methods in order to create custom validations
class Invoice < ApplicationRecord
validate :expiration_date_cannot_be_in_the_past
def expiration_date_cannot_be_in_the_past
if expiration_date.present? && expiration_date < Date.today
errors.add(:expiration_date, "can't be in the past")
end
end
It also allows to create conditional validations
class Order < ApplicationRecord
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
end
end
How can I mix both ?
My guess would be something like
validate :condition, if: :other_condition
But this creates a SyntaxError:
syntax error, unexpected end-of-input, expecting keyword_end
Upvotes: 3
Views: 11958
Reputation: 104
class User < ApplicationRecord
validate :email_not_changeable, on: :update
private
def email_not_changeable
return unless email_changed? && persisted?
errors.add(:email, "can't be changed")
end
end
Upvotes: 1
Reputation: 4427
You missed end, corrected code:
class Invoice < ApplicationRecord
validate :expiration_date_cannot_be_in_the_past
def expiration_date_cannot_be_in_the_past
if expiration_date.present? && expiration_date < Date.today
errors.add(:expiration_date, "can't be in the past")
end # this end you missed in code
end
end
Upvotes: 2
Reputation: 999
You can use each validator. For this you have to follow these steps:
validators
inside your app
directory.some_validator.rb
Write codes as like:
class SomeValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
return unless value.present?
if some_condition1
object.errors[attribute] << 'error msg for condition1'
end
object.errors[attribute] << 'error msg 2' if condition2
object.errors[attribute] << 'error msg 3' if condition3
object.errors[attribute] << 'error msg 4' if condition4
end
end
Now validates by this custom validator, as like:
validates :attribute_name, some: true
Make sure your are giving the same name on validator. You can write the multiple conditions inside this custom validator.
Upvotes: 3
Reputation: 52357
When you fix the missing closing end
to opened if
in expiration_date_cannot_be_in_the_past
, you can have the following working:
validate :expiration_date_cannot_be_in_the_past, if: :paid_with_card?
Upvotes: 5