Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Validating a Date Greater than Another

I'm writing a custom validator in ActiveRecord so that a deadline makes sense:

  validate :deadline_is_possible?

  def deadline_is_possible?
    if deadline > begins_at
      errors.add(:deadline, 'must be possible')
    end
  end

This however generates a "NoMethodError: undefined method `>' for nil:NilClass". I event tried to turn the dates into strings, like:

  def deadline_is_possible?
    if deadline.to_s > begins_at.to_s
      errors.add(:deadline, 'must be possible')
    end
  end

and though it doesn't generate an error, doesn't work either.

I also declared other validators (such as

  def begins_at_is_date?
    if !begins_at.is_a?(Date)
      errors.add(:begins_at, 'must be a date')
    end
  end

that work OK.

like image 505
piffy Avatar asked May 18 '12 15:05

piffy


People also ask

What is the difference between validate and validates in rails?

So remember folks, validates is for Rails validators (and custom validator classes ending with Validator if that's what you're into), and validate is for your custom validator methods.

How does validate work in Rails?

Rails validation defines valid states for each of your Active Record model classes. They are used to ensure that only valid details are entered into your database. Rails make it easy to add validations to your model classes and allows you to create your own validation methods as well.

What is validate in Ruby on Rails?

Validations are used to ensure that only valid data is saved into your database. For example, it may be important to your application to ensure that every user provides a valid email address and mailing address. Model-level validations are the best way to ensure that only valid data is saved into your database.


2 Answers

You can use comparison:

   validates :deadline, comparison: { greater_than: :begins_at }

Doc: https://guides.rubyonrails.org/active_record_validations.html#comparison

like image 194
Anton Kachan Avatar answered Sep 18 '22 09:09

Anton Kachan


You can add your own validator:

class AfterDateValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.blank?

    other_date = record.public_send(options.fetch(:with))

    return if other_date.blank?

    if value < other_date
      record.errors.add(attribute, (options[:message] || "must be after #{options[:with].to_s.humanize}"))
    end
  end
end

And use it in a model:

validates :invited_on, presence: true
validates :selected_on, presence: true, after_date: :invited_on
like image 41
Kris Avatar answered Sep 19 '22 09:09

Kris