web-dev-qa-db-ja.com

Railsで今日より後の日付を検証する方法は?

Expiry_dateという属性を含むActive Recordモデルがあります。今日(現在の日付)以降になるように検証するにはどうすればよいですか? Rails and Rubyにまったく新しいのですが、これに正確に答える同様の質問が見つかりませんでしたか?

私はRails 3.1.3およびRuby 1.8.7

39

あなたの質問は(ほとんど)正確に答えられます Railsガイド で。

ここに彼らが与えるサンプルコードがあります。このクラスは、日付がpastにあることを検証しますが、質問は、日付がfutureにあることを検証する方法ですしかし、それを適応させるのは非常に簡単です:

class Invoice < ActiveRecord::Base
  validate :expiration_date_cannot_be_in_the_past

  def expiration_date_cannot_be_in_the_past
    if expiration_date.present? && expiration_date < Date.today
      errors.add(:expiration_date, "can't be in the past")
    end
  end    
end
64
apneadiving

カスタムバリデーターを設定するコードは次のとおりです。

#app/validators/not_in_past_validator.rb
class NotInPastValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.blank?
      record.errors.add attribute, (options[:message] || "can't be blank")
    elsif value <= Time.zone.today
      record.errors.add attribute,
                        (options[:message] || "can't be in the past")
    end
  end
end

そしてあなたのモデルでは:

validates :signed_date, not_in_past: true
18
Dan Kohn

@dankohnの回答を取得し、I18nに対応するように更新しました。 blankテストも削除しました。これはこのバリデーターの責任ではなく、validates呼び出しにpresence: trueを追加することで簡単に有効にできるためです。

in_futureという名前の更新されたクラスは、not_in_pastよりも優れていると思います

class InFutureValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add(attribute, (options[:message] || :in_future)) unless in_future?(value)
  end

  def in_future?(date)
    date.present? && date > Time.zone.today
  end
end

ローカリゼーションファイルにin_futureキーを追加します。

errors.messages.in_futureの下のすべてのフィールド、たとえばオランダ語の場合:

nl:
  errors:
    messages:
      in_future: 'moet in de toekomst zijn'

または、activerecord.errors.models.MODEL.attributes.FIELD.in_futureの下のフィールドごと、たとえばオランダ語のVacancyモデルのend_dateの場合:

nl:
  activerecord:
    errors:
      models:
        vacancy:
          attributes:
            end_date:
              in_future: 'moet in de toekomst zijn'
3
Koen.

Rails 4+にはfuture?およびpast?メソッドはDateTimeオブジェクトのため、より簡単な答えは

class Invoice < ActiveRecord::Base
  validate :expiration_date_cannot_be_in_the_past

  def expiration_date_cannot_be_in_the_past
    if expiration_date.present? && expiration_date.past?
      errors.add(:expiration_date, "can't be in the past")
    end
  end    
end
3
Obromios

最も単純で実用的なソリューションは、Railsの組み込み検証を使用することです。次のように検証するだけです:

validates :expiry_date, inclusion: { in: (Date.today..Date.today+5.years) }
2
Amit Attri