web-dev-qa-db-ja.com

DateとActiveSupport :: TimeWithZoneの比較に失敗しました

ageモデルに次のようなWaiverメソッドがあります。

  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)>'
17
Kyle Decot

ActiveSupport::TimeWithZoneDateのインスタンスをdate < date_of_birth + age.yearsのインスタンスと比較しています。 ActiveSupport :: TimeWithZoneは、 ドキュメントによると 、任意のタイムゾーンの時間を表すことができるTimeのようなクラスです。何らかの変換を実行せずに、DateオブジェクトとTimeオブジェクトを比較することはできません。コンソールでDate.today < Time.nowを試してください。同様のエラーが表示されます。

12.years.agoのような式や一般的なActiveRecordタイムスタンプは、ActiveSupport :: TimeWithZoneのインスタンスです。このメソッドでは、TimeオブジェクトまたはDateオブジェクトのみを処理し、両方を処理しないようにすることをお勧めします。日付と日付を比較するために、式は代わりに次のように記述できます。

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