Validate presence before custom validation

validates :place_id, :title, :level, :start_at, :end_at, :presence =>
true
validate :event_takes_place_in_one_day, :event_is_not_in_past

  def event_takes_place_in_one_day
    self.start_at.day == self.end_at.day
  end
  def event_is_not_in_past
    admissible_range =
DateTime.now.beginning_of_day..DateTime.now.end_of_month
    admissible_range.cover?(self.start_at) &&
admissible_range.cover?(self.end_at)
  end

and bang! error when start_at or end_at is nil.

undefined method `to_datetime' for nil:NilClass

app/models/meeting.rb:22:in `cover?'
app/models/meeting.rb:22:in `event_is_not_in_past'
app/controllers/meetings_controller.rb:18:in `create'

You realise that validations are performed when the attempt is made to
save to the database?

Otherwise it might be helpful to show us the cover method.

Colin

cover? is the method of ActiveSupport.
Ahh yeah, I loose it:)
So what should I do - create a new inheritance from
ActiveModel::Validator for each check?

Sorry, I don't understand what you are trying to do. Please explain
in more detail what the problem is that you are trying to solve.

If the problem is that you need non-nil dates in the controller then
then you could just check them.

Colin

Sorry, English is not my native language:)
Application have a Meeting model with start_at and end_at DateTime type
attributes, which indicate a start and the end of the meeting
respectively.
I need to implement next logic
start_at < end_at (that it starts after than end)
start_at.day == end_at.day (meeting ends within one day)
and also meeting can be created only for the current month.

Sorry, English is not my native language:)
Application have a Meeting model with start_at and end_at DateTime type
attributes, which indicate a start and the end of the meeting
respectively.
I need to implement next logic
start_at < end_at (that it starts after than end)
start_at.day == end_at.day (meeting ends within one day)
and also meeting can be created only for the current month.

Ok I see the problem, it is that the validations are not performed in
the order that you hoped. I don't know whether you can control this.
One solution is just to add checks into your validate methods to stop
them crashing. Something like
def event_is_not_in_past
    admissible_range = DateTime.now.beginning_of_day..DateTime.now.end_of_month
    self.start_at.nil? || self.end_at.nil? ||
(admissible_range.cover?(self.start_at) &&
admissible_range.cover?(self.end_at))
  end

Then that test will pass but your presence validations will fail.

Colin

Great, according to this logic system will take care for error messages
and this will not take place, right? :slight_smile:
if start_at.nil?
    errors.add(:start_at, "can't be blank")
    return
if start_end.nil?
    errors.add(:end_at, "can't be blank")
    return

Sorry, I do not understand what you are asking? Is this a
continuation of your first question or is it a new question? If is
is a new question then it would be better to start a new thread.

Colin