What's the best way to install a robust system which checks if an event is over-booked in Rails?
I need to create a system for my Events site that monitors the number of bookings being taken to ensure an Event does not become over-subscribed. What is the most effective (DRY) way to do this?
I've tried this in my controller but it didn't work -
if @event.bookings.count >= @event.number_of_spaces flash[:warning] = "Sorry, this event is fully booked." redirect_to root_path end
I also tried this transaction code, also in my controller, which didn't work either ( well, it sort of worked as the flash message did come up however it came up AFTER a payment was taken which is not good) -
Booking.transaction do @booking.save! @event.reload if @event.bookings.count > @event.number_of_spaces flash[:warning] = "Sorry, this event is fully booked." raise ActiveRecord::Rollback, "event is fully booked" end end
Is it more effective to do this in the Model? On my index page I have each event listed with a main image, event title and date. I also want to include a tracking message illustrating how many spaces are left e.g "50 spaces left - book now". So, before I can do that, I have to sort this out. Any assistance would be appreciated.
Based on what I see, you're saving the booking, reloading the event, and then checking if it is now over filled. You need to check first if the requested number of spaces is greater than the number of available spaces before you ever call
@booking.save!. So you'll want a separate function that gets called in your create function before you save which checks if that event has enough slots available. Also, I'm not sure how you have everything setup, but I would limit the number of bookings a user can select based on the number of slots left at that moment in time as a UX improvement so you don't even let the client think they're going to be able to book that many slots, just to then have the system tell them "sorry, you can't do that!"
You should have a column in your event table that lets you set the total # of spaces available when you're creating the event itself. So to see how many slots are available for that event, you'd just
@event.spaces_available. When you're showing all the events, just do something like:
<% @events.each do |event| %> <%= event.name %> <%= event.date %> <% if event.spaces_available == 0 %> Sorry, no spaces left! <% else %> <%= event.spaces_available %> spaces left - book now! <% end %> <% end %>
Anytime you're working with booking events / appointments you need to be aware of race conditions. You need a way to temporarily "reserve" slots while your user is completing the checkout process. There are a ton of ways of handling this, you'll just have to figure out what works best for your setup.