2012-10-10 27 views
15

Tôi có một phương pháp age trên mô hình Waiver của tôi trông giống như:so sánh Date with ActiveSupport :: TimeWithZone thất bại

def age(date = nil) 

    if date.nil? 
     date = Date.today 
    end 
    age = 0 
    unless date_of_birth.nil? 
     age = date.year - date_of_birth.year 
     age -= 1 if date < date_of_birth + age.years #for days before birthday 
    end 
    return age 
    end 

Sau đó tôi có một spec trông giống như:

it "calculates the proper age" do 
waiver = FactoryGirl.create(:waiver, date_of_birth: 12.years.ago) 
waiver.age.should == 12 
end 

Khi tôi chạy thông số này tôi nhận được comparison of Date with ActiveSupport::TimeWithZone failed. Tôi đang làm gì sai?

Failures: 

    1) Waiver calculates the proper age 
    Failure/Error: waiver.age.should == 12 
    ArgumentError: 
     comparison of Date with ActiveSupport::TimeWithZone failed 
    # ./app/models/waiver.rb:132:in `<' 
    # ./app/models/waiver.rb:132:in `age' 
    # ./spec/models/waiver_spec.rb:23:in `block (2 levels) in <top (required)>' 
+0

Tôi không biết tại sao nó thất bại nhưng nó hoạt động tốt nếu bạn đặt date_of_birth thành '12.years.ago. to_date' và không phải '12.years.ago'. – oldergod

Trả lời

34

Bạn đang so sánh một thể hiện của Date với một thể hiện của ActiveSupport::TimeWithZone trong biểu thức date < date_of_birth + age.years; ActiveSupport :: TimeWithZone là, according to the docs, một lớp Thời gian giống như có thể đại diện cho một thời gian trong bất kỳ múi giờ nào. Bạn chỉ không thể so sánh các đối tượng DateTime mà không thực hiện một số loại chuyển đổi. Hãy thử Date.today < Time.now trên bảng điều khiển; bạn sẽ thấy một lỗi tương tự.

Các biểu thức như 12.years.ago và dấu thời gian ActiveRecord điển hình là các trường hợp của ActiveSupport :: TimeWithZone. Bạn nên đảm bảo rằng bạn chỉ giải quyết được với các đối tượng Time hoặc Date, chứ không phải cả hai trong phương pháp này. Để làm cho so sánh của bạn được cập nhật, thay vào đó, biểu thức có thể được viết là:

age -= 1 if date < (date_of_birth + age.years).to_date 
+0

Cảm ơn bạn đã giải thích chi tiết. Tôi đã thực hiện các thay đổi thích hợp cho mã của mình và mọi thứ đang hoạt động tốt ngay bây giờ! –

+0

thực sự, bạn có thể so sánh ngày với TimeWithZone, nhưng có vẻ như Rails sẽ chuyển đổi Date thành 00:00:00 UTC theo mặc định sau đó, có thể giới thiệu lỗi. I E. >> 'Time.zone.parse ('Thứ Ba, 01 Aug 2017 00:00:00 CEST +02: 00') 'true' – Magne

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