2

What would be the best approach to trying to "validate" uniqueness of dates for object.

--

So for example, I have a Room, that can only have 1 person in it at a time.

A User can book this Room in advance.

Currently the Room is booked from the 1st of March to the 5th of March.

I want to prevent anyone from booking again on those dates.

So if someone attempts to book a room from the 25th of Feb to the 2nd of March, I need to tell them they cannot, because the room is fully booked.

--

I am using Rails 3.0

fighella
  • 580
  • 5
  • 16

1 Answers1

2

I just wrote a simple app to test this out. Here's what I ended up using in the model validation.

class Booking < ActiveRecord::Base
  validate :uniqueness_of_date_range

  private
  def uniqueness_of_date_range
    errors.add(:start_date, "is not available") unless Room.where("? >= start_date AND ? <= end_date",
                                                            start_date, start_date).count == 0
    errors.add(:end_date, "is not available") unless Room.where("? >= start_date AND ? <= end_date",
                                                            end_date, end_date).count == 0
  end
end

The first custom validation checks to see if the current record's start_date falls between the start_date and end_date of any record, and second one does the same for end_date. You might want to show a better error message (like what is the start/end date of the record(s) that is/are clashing with the current one by doing a similar query (using .all instead of .count, and adding all the details of matching rooms).

Here's the db migration I used

class CreateBookings < ActiveRecord::Migration
  def self.up
    create_table :bookings do |t|
      t.date :start_date
      t.date :end_date
      t.string :title

      t.timestamps
    end
  end

  def self.down
    drop_table :bookings
  end
end
Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • Thank you kindly for this. I will try this out. – fighella Feb 17 '11 at 20:40
  • What about if the start_date of the booking is before the start_date of an already existing booking and the attempted end date is after the end date of that existed booking... then I should also have a conflict... because essentially they are trying to book over the whole of that event, not just within it's start and end dates... – fighella Feb 19 '11 at 11:30