Rails code readability for my validation

我怕爱的太早我们不能终老 提交于 2019-12-25 03:32:09

问题


The code works fine in detecting overlapping dates to not save a Booking if it already exist for a given Room. However, I had to twist my code to make it work because validation would make the update in my controller not valid instead of the save. So I want to know what is wrong with my code as normally the not valid should apply to the save and not the update.

In fact, to tell me that a booking cannot be saved instead of throwing an error, it just did not update the booking.end_date in my contoller while it should raise an error when it save and not when I try to update it:

I have a controller that create a new booking for a room (this is what I want to improve):

  def create_book_now
    @room = Room.find(params[:room_id])
    booking = @room.bookings.build(booking_params)

    if booking.save  #I want to not save if model validation are not OK
      if @room.bookings.last.update(end_date: booking.start_date + booking.length.days) # I have to check if this is true for my validation to work, I am sure it is not normal
        flash[:notice] = "Booking done"
        redirect_to root_path
      else
        flash[:error] =  "booking.errors.full_messages.first if booking.errors.any?"
        redirect_to room_book_now_path(@room.id)
      end
    else
      flash[:error] =  booking.errors.full_messages.first if booking.errors.any?
      redirect_to room_book_now_path(@room.id)
    end
  end

The new booking go through validation to make sure no booking with overlapping date has been made:

class Booking < ActiveRecord::Base
    belongs_to :room

    validates :length, :presence => true

    validate :dates_are_available

    def dates_are_available
        room = Room.find(self.room_id)
        # if Room.find(self.room_id).bookings.exists?
        #    self.errors.add(:base, 'Date already taken')
        # end
        conditions = []
        conditions << '(start_date >= :new_start_date AND end_date >= :new_end_date)'
        conditions << '(start_date >= :new_start_date AND end_date <= :new_end_date)'
        conditions << '(end_date BETWEEN :new_start_date AND :new_end_date)'
        conditions << '(start_date <= :new_start_date AND end_date >= :new_end_date)'
        if room.bookings.where(conditions.join(' OR '), new_start_date: self.start_date, new_end_date: self.end_date).exists?
            self.errors.add(:base, 'Date already taken')
            return false
        end
    end
end

So my question is how to make my code in my controller better so that the validation will work when Booking is saved and not when it is updated


回答1:


You can do something like that, check all bookings that you assing to your room before save, and one by one check the condition.

def dates_are_available
    room.bookings.each do |b|
        if bookings.start_date
            self.errors.add(:base, 'Date already taken')
        end
    end
end


来源:https://stackoverflow.com/questions/29551261/rails-code-readability-for-my-validation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!