How to validate the date such that it is after today in Rails?

后端 未结 5 561
伪装坚强ぢ
伪装坚强ぢ 2021-02-03 19:07

I have an Active Record model that contains attributes: expiry_date. How do I go about validating it such that it is after today(present date at that time)? I am totally new to

相关标签:
5条回答
  • 2021-02-03 19:09

    In rails 4+ there are future? and past? methods for DateTime objects, so a simpler answer is

    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
    
    0 讨论(0)
  • 2021-02-03 19:10

    I took @dankohn answer, and updated to be I18n ready. I also removed the blank test, because that's not the responsibility of this validator, and can easily be enabled by adding presence: true to the validates call.

    The updated class, now named in_future, which I think is nicer than 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
    

    Now add the in_future key to your localization file.

    For all fields under errors.messages.in_future, e.g. for Dutch:

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

    Or per field under activerecord.errors.models.MODEL.attributes.FIELD.in_future, e.g. for the end_date in a Vacancy model in Dutch:

    nl:
      activerecord:
        errors:
          models:
            vacancy:
              attributes:
                end_date:
                  in_future: 'moet in de toekomst zijn'
    
    0 讨论(0)
  • 2021-02-03 19:11

    Here's the code to set up a custom validator:

    #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
    

    And in your model:

    validates :signed_date, not_in_past: true
    
    0 讨论(0)
  • 2021-02-03 19:22

    Your question is (almost) exactly answered in the Rails guides.

    Here's the example code they give. This class validates that the date is in the past, while your question is how to validate that the date is in the future, but adapting it should be pretty easy:

    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
    
    0 讨论(0)
  • 2021-02-03 19:28

    The simplest and working solution is to use the in-built validation from Rails. Just validates it like that:

    validates :expiry_date, inclusion: { in: (Date.today..Date.today+5.years) }
    
    0 讨论(0)
提交回复
热议问题