# columns
# maximum_users :integer(4)
# last_registration_date :datetime
class Training < ApplicationRecord
validates :maximum_users, numericality: { greater_than: 0, less_than_or_equal_to: 999,
only_integer: true }
validate :last_reg_date_cannot_be_in_the_past
private
def last_reg_date_cannot_be_in_the_past
if last_registration_date_changed? && last_registration_date < Time.now.utc
errors.add(:training, "can't be in the past")
end
end
end
In the above model I need to add followings validations:
maximum_users
or last_registration_date
).maximum_users
allowed is less than 999
. last_registration_date
must be greater than today's date. I have added few validations but don't think this is a good practice.
How can I refactor the model to cover all the above scenarios ?
Having plenty of validations is not a bad practice. At some point you may want to move it to a validator class.
class Training < ApplicationRecord
validates_with TrainingValidator
end
One problem I see with what you have is that last_registration_date
can be set and maximum_users
be nil, but your maximum_users
validation above might not allow nil.
app/models/concerns/traning_validator.rb
classTrainingValidator < ActiveModel::Validator
def validate(training)
if training.last_registration_date_changed? && training.last_registration_date < Time.now.utc
training.errors.add(:training, "can't be in the past")
end
unless training.last_registration_date.nil? || training.maximum_users.nil?
training.errors.add(:last_registration_date, "last_registration_date cannot both be set when maximum_users is set")
end
unless training.maximum_users.nil? || training.maximum_users < 999
training.errors.add(:maximum_users, "must be less than 999")
end
end
end
I did something like this :
class NotInPastValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add attribute, (options[:message] || "Date can't be in the past") if value <= Time.now.utc
end
end
Model :
validates :maximum_users,
numericality: {
greater_than: 0,
less_than_or_equal_to: 999,
only_integer: true
}
validates :last_registration_date, not_in_past: true
validate :validate_max_users_and_last_reg_date
def validate_max_users_and_last_reg_date
if maximum_users_changed? && last_registration_date_changed?
errors.add(:training, 'Specify either maximum users or last registration date, not both')
end
end
def maximum_users_changed?
changes.keys.include? 'maximum_users'
end
def last_registration_date_changed?
changes.keys.include? 'last_registration_date'
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.