19

日時属性を持つモデルがあります。モデルを更新する着信 JSON を検証しようとしています。しかし、無効な日時の場合、ActiveRecordは属性の値をnilに設定しているようです。属性を nil にすることが許可されているため、適切なエラーで応答できません。私は何を間違っていますか?

コード:

class DatetimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
  end
end

class Foo
   # column :my_date, :datetime
   validates :my_date, :allow_nil => true, :datetime => true
end

コンソール:

1.9.3p125 :001 > x = Foo.new
=> #<Foo id: nil, my_date: nil>
1.9.3p125 :001 > x.my_date = 'bad value'
=> 'bad value'
1.9.3p125 :001 > x.my_date
=> nil
1.9.3p125 :001 > x.valid?
=> true

ActiveRecord に関する限り、datetime 属性を「bad_value」に設定することは、nil に設定することと同じであり、my_date が必要ないため、検証できません。これは私にはバグのようです。最善の回避策は何ですか?

ありがとう!

4

1 に答える 1

11

allow_nil1 つの回避策は、パーツをdate_time検証に移動することです。

class DatetimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.blank?
    value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
  end
end

class Foo
  validates :my_date, :datetime => true
end

編集:タイプキャスティングの問題だと思います-これを試してください(のコードから適応validates :numericality):

def validate_each(record, attribute, value)
  before_type_cast = "#{attribute}_before_type_cast"

  raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym)
  raw_value ||= value

  return if raw_value.blank?
  raw_value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
end
于 2012-10-23T19:05:02.193 に答える