Rails:在type_cast之前验证模型中的日期

wri*_*bln 5 validation ruby-on-rails date

当以格式输入格式错误或无效的日期(例如,非le年的2月29日)时,任何验证似乎都将访问nil值。原因是在Rails中进行验证之后,将原始字符串强制转换为日期变量:如果失败(由于上述原因),则强制转换返回nil值,该值存储在模型的属性中。

我发现可以通过这些attribute_before_type_cast函数访问原始日期字符串,因此能够编写以下自定义验证器:

class DateFieldValidator < ActiveModel::EachValidator

  def validate_each( record, attribute, value )

    # this may be interesting only if value could not be read

    return unless value.nil?

    # but not if original value was blank

    original_value = record.read_attribute_before_type_cast( attribute )
        return if original_value.blank?

    # ignore any other value but String

    return unless original_value.is_a? String

    # _parse must return some useful values

    parsed_value = Date._parse( original_value )
    unless [ :year, :mon, :mday ].all? { |key| parsed_value.has_key?( key ) }
      record.errors.add( attribute, ( options[ :message ] || I18n.t( 'validators.date_field.bad_syntax' )))
      return
    end

    # valid_date? must return true

    unless Date.valid_date?( parsed_value[ :year ], parsed_value[ :mon ], parsed_value[ :mday ])
      record.errors.add( attribute, ( options[ :message ] || I18n.t( 'validators.date_field.bad_date' )))
      return
    end

  # date is OK

  end
end
Run Code Online (Sandbox Code Playgroud)

这可以正常工作,但是如果需要日期(验证时为真:true),我会收到两个验证错误,一个来自我的验证器,另一个来自Rails,告诉用户缺少必需的属性。

这可能会激怒用户,特别是因为原始不良价值(当前)未显示在表单上。我应该在表单中显示原始值并删除Rails生成的错误消息吗?

PS日期选择器不能仅插入有效日期,因为我不得不考虑将来的日期,这需要在日期选择器中多次单击。