7

I have an Active Record model that contains two attributes: start_date and end_date. How do I go about validating the following:

  1. The dates are in the correct (yyyy-mm-dd) format
  2. That end_date > start_date
Kevin Pang
  • 41,172
  • 38
  • 121
  • 173

2 Answers2

21

Does it matter what format they are stored in? A Date object is a Date object. Are you storing it in a date column in the DB?

Here is how I do the validation:

class MyModel < ActiveRecord::Base
  validate :validate_end_date_before_start_date

  def validate_end_date_before_start_date
    if end_date && start_date
      errors.add(:end_date, "Put error text here") if end_date < start_date
    end
  end
end

Keep in mind this does not check for nil dates... you might want to if either could be.

FYI, if you want to be able to accept a variety of formats Chronic is pretty flexible.

brettish
  • 2,628
  • 3
  • 17
  • 22
  • Well, I'm populating my "MyModel" object in the controller action with the following line of code: mymodel = MyModel.new(params[:mymodel]) I'm guessing that is setting the start_date and end_date as strings. I suppose I could manually convert the params[:start_date] and params[:end_date] to date objects first before storing them in my model. Is that what you would recommend? (and yes, I'm storing them in date columns in the db) – Kevin Pang Apr 14 '11 at 16:30
  • 1
    you can pass the dates as strings the params hash without any problems... they will be converted into Date objects automatically. But a little word of warning: if you pass in a string like 01-04-1990, it will not be interpreted as Jan 4, 1990 but as April 1, 1990. However, YYYY-MM-DD is unambiguous and will be parsed correctly. – brettish Apr 14 '11 at 22:22
  • Thanks. Yes, I ran into that mm/dd/yyyy vs dd/mm/yyyy issue. I decided to simply ask for user input in yyyy-mm-dd format. – Kevin Pang Apr 14 '11 at 22:32
  • @kevin One of the reasons I am using the chronic gem is to (among other things) parse mm/dd/yyyy. I overrode my end_date setter using chronic. – brettish Apr 14 '11 at 22:36
  • There is a problem with the answer above. The "s" behind validates leads to a crash. Took me 30 minutes to figure that out. Correct form:'validate :validate_end_date_before_start_date ' – Michael Schmitz Sep 07 '12 at 11:36
  • @Michael Schmitz - good catch. I corrected the answer. Sorry for the confusion. – brettish Sep 07 '12 at 23:26
1

Here is how to do date validation:

How do I validate a date in rails?

And seeing if a date is greater than another date, you can just use the greater than/less than operators on date objects:

ruby-1.9.2-p136 :006 > d1 = Date.civil(2011, 05, 01)
 => #<Date: 2011-05-01 (4911365/2,0,2299161)> 
ruby-1.9.2-p136 :007 > d2 = Date.civil(2011, 01, 01)
 => #<Date: 2011-01-01 (4911125/2,0,2299161)> 
ruby-1.9.2-p136 :008 > d2 > d1
 => false 
ruby-1.9.2-p136 :009 > d2 < d1
 => true 

So in your example:

def validate_dates
  errors.add("Created at date", "is invalid.") unless convert_created_at
  errors.add("End Date" , "is invalid") if end_date > start_date
end
Community
  • 1
  • 1
Mike Lewis
  • 63,433
  • 20
  • 141
  • 111