← Back to Upcase

Custom Validator


(Scott Hollinshead) #1

I have an app that allows you to book meeting rooms, and I am trying to make it so you cannot book a room if the time slot has already been taken.

Here are 2 examples:

  1. If somebody want’s to book a time slot from 12:00 - 13:00 somebody else should not be able to book that same slot
  2. If somebody want’s to book a time slot from 12:00 14:00 somebody else should not be able to book 13:00 - 15:00 as this will overlap.

This is my current validation code:

class MeetingValidator < ActiveModel::Validator
  def validate(record)
    if record.class.where(to: record.to..record.from).where(from: record.to..record.from)
      record.errors[:time_slot] << "has already been taken, please pick another"
    end 
  end
end

Any help is much apreciated.


(Matthew Sumner) #2

So you can just as easily have this as a class method. Defining a custom validator is usually reserved for when you want to use it across multiple models.

I would go for the following:

class Meeting < ActiveRecord::Base
  validates :time_slot_is_available

  private

  def time_slot_is_available
    if <logic checking meetings with the same slot>
      record.errors[:time_slot] << "has already been taken, please pick another"
    end
  end
end

Another thought is, are your users picking time slots from a drop-down? It might be a good user experience to only show available slots to pick. You should leave the validation in there in case someone gets the slot just before someone else submits.


(Derek Prior) #3

What’s the problem you’re having?


(Scott Hollinshead) #4

@halogenandtoast helped me with this in the Office Hours thanks guys.

The solution was this:

def valdiate_time_slot(record)
  if record.class.where("`to` > ? AND `from` < ?", record.from, record.to).exists?
    record.errors[:time_slot] << "has already been taken please choose another."
 end
end