2012-10-10 533 views
15

我有我的Waiver模型的age方法,看起來像:比較失敗

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 

然後我有一個規範,看起來像:

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

當我運行此規格我得到comparison of Date with ActiveSupport::TimeWithZone failed。我究竟做錯了什麼?

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

我不知道爲什麼會失敗,但如果你設置DATE_OF_BIRTH到'12.years.ago它工作正常。 to_date'而不是'12.years.ago'。 – oldergod

回答

34

您正在使用在表達式date < date_of_birth + age.years一個的ActiveSupport::TimeWithZone實例比較Date實例; ActiveSupport :: TimeWithZone是,according to the docs,類似於時間的類,可以表示任何時區中的時間。您只是無法比較DateTime對象而無需執行某種轉換。在控制檯上嘗試Date.today < Time.now;你會看到類似的錯誤。

12.years.ago這樣的表達式和典型的ActiveRecord時間戳是ActiveSupport :: TimeWithZone的實例。您最好確保僅處理Time對象或Date對象,但不能同時使用此方法。爲了讓您比較日期最新,表達可以改爲寫爲:

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

感謝您的深入解釋。我對代碼做了適當的修改,現在一切都很順利! –

+0

實際上,你可以將Date與TimeWithZone進行比較,但是Rails將默認情況下將Date轉換爲00:00:00 UTC,這可能會引入錯誤。 IE瀏覽器。 >>'Time.zone.parse('2017年8月1日星期二00:00:00 CEST +02:00')'true' – Magne