如何针对特定范围验证模型的日期属性(在运行时评估)

Oll*_*lly 8 validation ruby-on-rails date

我有几个带有日期属性的模型,对于每个模型,我想根据给定的范围验证这些日期.一个基本的例子是:

validates_inclusion_of  :dated_on, :in => Date.new(2000,1,1)..Date(2020,1,1)
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想在运行时使用类似的方法评估日期范围named_scope,例如:

validates_inclusion_of  :dated_on, :in => lambda {{ (Date.today - 2.years)..(Date.today + 2.years)}}
Run Code Online (Sandbox Code Playgroud)

当然上面的方法不起作用,那么实现相同结果的最佳方法是什么?

小智 13

您可以使用日期验证器:

    validates :dated_on, :date => {:after => Proc.new { Time.now + 2.years },
                                   :before => Proc.new { Time.now - 2.years } }
Run Code Online (Sandbox Code Playgroud)


Jam*_*sen 6

如果每个类的验证相同,答案很简单:将验证方法放在模块中并将其混合到每个模型中,然后使用validate添加验证:

# in lib/validates_dated_on_around_now
module ValidatesDatedOnAroundNow
  protected

  def validate_dated_around_now
    # make sure dated_on isn't more than five years in the past or future
    self.errors.add(:dated_on, "is not valid") unless ((5.years.ago)..(5.years.from_now)).include?(self.dated_on)
  end
end

class FirstModel
  include ValidatesDatedOnAroundNow
  validate :validate_dated_around_now
end

class SecondModel
  include ValidatesDatedOnAroundNow
  validate :validate_dated_around_now
end
Run Code Online (Sandbox Code Playgroud)

如果你想为每个模型设置不同的范围,你可能想要更像这样的东西:

module ValidatesDateOnWithin
  def validates_dated_on_within(&range_lambda)
    validates_each :dated_on do |record, attr, value|
      range = range_lambda.call
      record.errors.add(attr_name, :inclusion, :value => value) unless range.include?(value)
    end
  end
end

class FirstModel
  extend ValidatesDatedOnWithin
  validates_dated_on_within { ((5.years.ago)..(5.years.from_now)) }
end

class SecondModel
  extend ValidatesDatedOnWithin
  validates_dated_on_within { ((2.years.ago)..(2.years.from_now)) }
end
Run Code Online (Sandbox Code Playgroud)