ブログ

読んで思い出す。忘れるために書く

日付の前後を比較するバリデーションを書く

自回答の転記

teratail.com

やりたいこと

モデルにバリデーションを掛けて、open_day が今日ではなく昨日以前であった場合に、エラーにしたい

テストコードと実装

仮に Post モデルとして話を進めていく

テストコード

# == Schema Information
#
# Table name: posts
#
#  id         :integer          not null, primary key
#  open_day   :date
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

RSpec.describe Post, type: :model do
  context 'validation about open_day' do
    before { Timecop.travel(2018, 1, 2).freeze }

    it 'invalid: when before today' do
      post = Post.new(open_day: Date.today.advance(days: -1))
      expect(post).to_not be_valid
    end

    it 'valid: when today or after' do
      post = Post.new(open_day: Date.today.advance(days: 1))
      expect(post).to be_valid
    end

    it 'invalid: when empty value' do
      post = Post.new
      expect(post).to_not be_valid
    end

    after { Timecop.return }
  end
end

実装

# == Schema Information
#
# Table name: posts
#
#  id         :integer          not null, primary key
#  open_day   :date
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Post < ApplicationRecord
  validate :not_before_today

  def not_before_today
    errors.add(:open_day, 'Please set today or after today') if open_day.nil? || open_day < Date.today
  end
end

Links