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

时间:2015-02-16 09:20:57

标签: ruby-on-rails validation date

如果在表单中输入格式不正确或无效的日期(例如,非闰年的2月29日),则任何验证似乎都会访问零值。这样做的原因是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

这很好但是如果日期是必需的(validate is with presence:true)我得到两个验证错误,一个来自我的验证器,另一个来自Rails,告诉用户缺少必需的属性。

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

P.S。作为帮助者的日期选择器只能插入有效日期,因此我不得不考虑将来需要大量点击日期选择器的日期。

0 个答案:

没有答案