eksrails
eksrails

Reputation: 51

How to implement custom date validation in Ruby on Rails

I am trying to follow the example in Rails Guides to implement a custom validation, but I can't seem to make it work to validate a date.

Here is the migration:

class CreateSetLists < ActiveRecord::Migration
  def change
    create_table :set_lists do |t|
      t.date :show_date
      t.string :show_name

      t.timestamps
    end
  end

end

Here is the model:

class SetList < ActiveRecord::Base
  validates :show_date, :show_name, presence: true
  validate :must_have_valid_future_date

  private

  def must_have_valid_future_date
    if show_date.present?
        unless show_date.is_a?(Date)
            errors.add(:show_date, "must be a valid date")
        end

        if show_date < Date.today
            errors.add(:show_date, "can't be in the past")
        end
    end
  end

end

When I try to test this by submitting an invalid date, the errors hash for my object shows a message as if the date were never set. If I remove the "presence" validation, then when I submit an invalid date the object simply saves with nil for the date.

Is there something special about validating that I have valid date that I am missing?

UPDATE (2015-12-07 11:45am):

I noticed this playing around in the console:

irb(main):044:0> msl=SetList.new
=> #<SetList id: nil, show_name: nil, show_date: nil, created_at: nil, updated_at: nil>
irb(main):045:0> msl.show_date="invalid"
=> "invalid"
irb(main):046:0> msl.show_date
=> nil

It would appear Rails does not allow me to validate that I have a valid date. It simply throws away invalid dates and sets the field to nil.

Is this some property of the column type for that attribute being of type Date? Is that behavior I can rely on, therefore eliminating the need to validate that I have a valid date (because Rails will automatically throw away an invalid date)?

UPDATE (2015-12-07 8:04pm):

This question seems to imply that I can count on Rails throwing away invalid dates without any validation needed in my model:

rails 3.1 date validation - is acts_like_date? enough or even necessary?

Upvotes: 1

Views: 1567

Answers (2)

eksrails
eksrails

Reputation: 51

It appears that it is not necessary to perform validation on a date attribute to ensure the entry is a valid date. If the value submitted is not a valid date than rails throws it away and leaves the attribute set to nil before any validation methods are called.

Upvotes: 2

noctrnal
noctrnal

Reputation: 191

Sometimes its easier to debug edge cases if you split off the logic. Maybe something in this direction:

def must_have_valid_future_date
  valid_date and future_date
end

def valid_date
  errors.add(:show_date, "must be a valid date") unless show_date.is_a?(Date)
end

def future_date
  errors.add(:show_date, "can't be in the past") if show_date < Date.today
end

If I remove the "presence" validation, then when I submit an invalid date the object simply saves with nil for the date.

This happens because your must_have_valid_future_date method does not return a boolean value. Or rather, it never returns a false, thus the nil allowed through.

ActiveModel::Validations

Upvotes: 0

Related Questions