Валідація в Rails досить потужна та зручна фішка, але як виявилось (якщо я досить добре читав розділ документації про валідацію) немає штатної можливості вказати, що цю валідацію виконуємо тільки після вон тих (у разі їх успіху звісно)
Можливо постає питання для чого це все? В одному проекті аля "Склад", необхідно зробити приход (переміщення) товару з одного складу на інший, вибравши у формі товар та вказавши його кількість.
Перевіряти ми будемо наступні речі:
- Товар вибраний
- Кількість вказана, та більше нуля
- Вказана кількість товару не перевищує фактичну кількість на складі, з якого ми виконуємо переміщення на текучий склад
Наша валідація
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Sklad < ActiveRecord::Base validates :tovar_id, presence: true validates :count, presence: true validates :count, numericality: true validates :count, numericality: { only_integer: true,greater_than: 0} validate :validate_max_count_sklad_tovar#, :if => Proc.new { |a| a.dependent_attributes_valid? } def validate_max_count_sklad_tovar tovar = Sklad.find_by(tovar_id: tovar_id, visible: 1) tovar_count = tovar.present? ? tovar.count : 0 errors.add(:count, "Товар на основному складі відсутній") if tovar_count == 0 errors.add(:count, "На основному складі залишилось лише #{tovar_count}шт товару.") if count.to_i > tovar_count end ... |
в такому разі ми отримаємо наступну ситуацію
Як бачимо, у нас все на купу, а не хотілось би, для цього третю валідацію будемо виконути лише тоді, коли перші дві вернуть true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class InetSklad < ActiveRecord::Base validates :tovar_id, presence: {message: "Поле обов'язкове для заповнення"} validates :count, presence: {message: "Поле обов'язкове для заповнення"} validates :count, numericality: true validates :count, numericality: { only_integer: true,greater_than: 0} validate :validate_max_count_sklad_tovar#, :if => Proc.new { |a| a.dependent_attributes_valid? } def dependent_attributes_valid? [:tovar_id, :count].each do |field| self.class.validators_on(field).each { |v| v.validate(self) } if self.errors.messages[field].present? self.errors.messages[field]=[self.errors.messages[field][0]] if self.errors.messages[field].kind_of?(Array) return false end end return true end private def validate_max_count_sklad_tovar if flag== 'tovar_plus' or flag == 'tovar_update' tovar = Sklad.find_by(tovar_id: tovar_id, visible: 1) tovar_count = tovar.present? ? tovar.count : 0 errors.add(:count, "Товар на основному складі відсутній") if tovar_count == 0 errors.add(:count, "На основному складі залишилось лише #{tovar_count}шт товару.") if count.to_i > tovar_count end end |