简体   繁体   English

如何为两个字段添加 ruby​​ on rails 模型验证?

[英]How to add ruby on rails model validation for two fields?

#  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:在上面的模型中,我需要添加以下验证:

  1. If user selects any one of the field than other should be nil ( maximum_users or last_registration_date ).如果用户选择任何一个字段,其他字段应该为零( maximum_userslast_registration_date )。
  2. User cannot add both the fields values.用户不能同时添加这两个字段值。
  3. User can choose not to select any of the values.用户可以选择不选择任何值。 But if he chooses then, anyone field must be allowed.但如果他当时选择,任何领域都必须被允许。
  4. maximum_users allowed is less than 999 . maximum_users允许小于999
  5. last_registration_date must be greater than today's date. last_registration_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.我看到的一个问题是可以设置last_registration_date并且maximum_users为 nil,但是上面的maximum_users验证可能不允许 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM