2012-10-23 21 views
15

Tôi có một mô hình có thuộc tính datetime. Tôi đang cố gắng xác thực JSON đến để cập nhật mô hình. Nhưng ActiveRecord dường như thiết lập giá trị của thuộc tính là nil nếu nó là một datetime không hợp lệ. Tôi không thể trả lời với lỗi thích hợp vì thuộc tính được phép là không. Tôi đang làm gì sai?Rails datetime không hợp lệ trên kết quả mô hình trong nil

Code:

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 

Console:

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 

Theo như ActiveRecord là có liên quan, thiết lập các thuộc tính datetime để 'bad_value' tương đương với thiết lập nó để nil, vì vậy tôi không thể xác nhận nó, vì my_date là không cần thiết. Điều này có vẻ như là một lỗi đối với tôi. Cách giải quyết tốt nhất là gì?

Cảm ơn!

+0

Mọi thứ có hoạt động nếu bạn xóa ': allow_nil => true' không? –

+0

Có, nó dường như làm việc (mặc dù vì một lý do nào đó tôi nhận được thông báo lỗi kép lần đầu tiên tôi chạy .valid?). Tôi nhận được dự kiến ​​'phải là một ngày.' –

Trả lời

8

Một workaround sẽ được di chuyển phần allow_nil vào date_time xác nhận:

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 

Edit: Tôi nghĩ đó là một vấn đề với typecasting - thử này (chuyển thể từ mã cho 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 
+0

Ah ok, xem chỉnh sửa. –

+0

Không có điều đó không hoạt động. Giá trị luôn luôn là nil trừ khi nó là một datetime hợp lệ, do đó, Foo.new (: my_date => 'wrong'). # => true –

+0

Mã đã chỉnh sửa với nội dung 'before_type_cast' không hoạt động? –

Các vấn đề liên quan