2012-10-10 11 views
15

Ho un metodo di age sul mio modello Waiver che assomiglia a:confronto di Data con ActiveSupport :: TimeWithZone fallito

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 

Ho poi una specifica che assomiglia:

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

Quando ho eseguire questa specifica ottengo comparison of Date with ActiveSupport::TimeWithZone failed. Che cosa sto facendo di sbagliato?

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

Non so il motivo per cui sta venendo a mancare, ma si sta lavorando bene se si imposta date_of_birth a '12.years.ago. to_date' e non '12.years.ago'. – oldergod

risposta

34

si sta confrontando un'istanza di Date con un'istanza di ActiveSupport::TimeWithZone nell'espressione date < date_of_birth + age.years; ActiveSupport :: TimeWithZone è, according to the docs, una classe Time-like che può rappresentare un orario in qualsiasi fuso orario. Non è possibile confrontare gli oggetti Date e Time senza eseguire alcun tipo di conversione. Prova Date.today < Time.now su una console; vedrai un errore simile.

Le espressioni come 12.years.ago e i timestamp tipici di ActiveRecord sono istanze di ActiveSupport :: TimeWithZone. È meglio assicurarsi di trattare solo gli oggetti Time o gli oggetti Date, ma non entrambi in questo metodo. Per rendere il vostro confronto data-to-date, l'espressione potrebbe invece essere scritta come:

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

Grazie per la spiegazione approfondita. Ho apportato le modifiche appropriate al mio codice e tutto funziona alla grande ora! –

+0

, in realtà, è possibile confrontare Data con TimeWithZone, ma sembra che Rails convertirà la data in 00:00:00 UTC di default quindi, che potrebbe introdurre bug. Vale a dire. >> 'Time.zone.parse ('Tue, 01 ago 2017 00:00:00 CEST +02: 00') 'true' – Magne