Я создаю приложение Events с помощью Ruby on Rails. Мне нужно создать систему для бронирования, чтобы гарантировать, что Событие не будет забронировано. Каждое событие имеет конечное количество доступных пространств - как я могу гарантировать, что, если доступно, например, 100 пробелов, 105 заказов не принимаются.Rails - Обеспечение того, что событие не переутомилось
Это мои мысли до сих пор, а также некоторый код, который я пробовал, но на самом деле не работал.
bookings_controller
def create
@event = Event.find(params[:event_id)
if @event.bookings.count >= @event.total_spaces
flash[:warning] = "Sorry, this event is fully booked."
redirect_to root_path
else
#code to save the booking
end
end
В воззрениях -
<% if @event.bookings.count > @event.total_spaces %>
# flash: "This event is fully booked"
<% else %>
# code to make the booking
Я не уверен, что этого достаточно, чтобы достичь своей цели. Нужен ли мне более надежный метод в моей модели бронирования и некоторые валидации для покрытия этого?
Я пробовал код транзакции блок -
Booking.transaction do
@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
, но это не сработало, как это до сих пор разрешено пользователю обработать платеж перед сообщением вспышки появился & после сделки была завершена.
Я никогда не строил ничего подобного раньше, поэтому немного в тупике. Любые указания, оцененные.
ОБНОВЛЕНИЕ -
Booking.rb
def set_booking
return {result: false, flash: :warning, msg: 'Sorry, this event is fully booked'} if event.bookings.count >= event.total_spaces
if self.event.is_free?
self.total_amount = 0
save!
else
self.total_amount = event.price_pennies * self.quantity
begin
charge = Stripe::Charge.create(
amount: total_amount,
currency: "gbp",
source: stripe_token,
description: "Booking created for amount #{total_amount}")
self.stripe_charge_id = charge.id
save!
rescue Stripe::CardError => e
# if this fails stripe_charge_id will be null, but in case of update we just set it to nil again
self.stripe_charge_id = nil
# we check in validatition if nil
end
end
{result: true, flash: :success, msg: 'Booking successful!'}
конец
bookings_conroller.rb
def create
# actually process the booking
@event = Event.find(params[:event_id])
# as above, the association between events and bookings means -
@booking = @event.bookings.new(booking_params)
@booking.user = current_user
handler = BookingHandler.new(@event)
booking = handler.set_booking(booking_params)
flash[booking[:flash]] = booking[:msg]
redirect_to root_path
# rest of controller code for booking
Пожалуйста, прочтите http://stackoverflow.com/help/how-to-ask. Было бы хорошо, если бы вы сузились до одной конкретной проблемы и более четко описывали свои намерения, чтобы люди могли вам помочь. –
Хорошо. Соответственно, я буду исправлять. Я пытаюсь обеспечить, чтобы событие не принимало заказы свыше и над количеством доступных им мест. Можете ли вы помочь с этим? –
Независимо от того, какой метод вы используете, вам понадобится способ блокировки/сериализации активности добавления человека к событию, чтобы избежать состояния гонки. –