I'm writing a booking system which handles recurring bookings using the ice_cube gem. A Booking
has_many BookingItem
s, one for each occurrence in the recurrence rule, and these are created in a method which is called by Booking
's after_save callback.
This was all working fine until I added a validation to BookingItem
which avoids double booking by checking that there isn't already a BookingItem
at the given time. This validation raises an error which I'd like to display on the booking form but at the moment it just silently prevents the Booking
from being saved - since the error is raised by the BookingItem
it's not being passed back to the form for the Booking
.
app/models/booking.rb
class Booking < ActiveRecord::Base
include IceCube
has_many :booking_items, :dependent => :destroy
after_save :recreate_booking_items!
# snip
private
def recreate_booking_items!
schedule.all_occurrences.each do |date|
booking_items.create!(space: self.requested_space,
booking_date: date.to_date,
start_time: Time.parse("#{date.to_date.to_default_s} #{self.start_time.strftime('%H:%M:00')}"),
end_time: Time.parse("#{date.to_date.to_default_s} #{self.end_time.strftime('%H:%M:00')}"))
end
end
end
app/models/booking_item.rb
class BookingItem < ActiveRecord::Base
belongs_to :booking
validate :availability_of_space
# snip
private
def availability_of_space
unless space.available_between? DateTime.parse("#{booking_date}##{start_time}"), DateTime.parse("#{booking_date}##{end_time}")
errors[:base] << "The selected space is not available between those times."
end
end
end
app/views/booking/_form.html.erb
<% if @booking.errors.any? %>
<div id="error_explanation">
<p><%= pluralize(@booking.errors.count, "error") %> prohibited this booking from being saved:</p>
<ul>
<% @booking.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_for(@booking, :html => { :class => "nice custom"}) do |f| %>
...
<% end %>