2012-10-10 84 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