Reputation: 51
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
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
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.
Upvotes: 0