Rails - 不保存到数据库的预订

时间:2016-07-15 10:39:04

标签: ruby-on-rails ruby ruby-on-rails-4 model-view-controller

我正在使用Rails构建一个Event站点。创建活动时,用户可以提供付费和免费活动。似乎booking_id仅分配给付费事件而非免费活动。我检查了我的控制台,这绝对是这样的。这显然会引发问题,我不太清楚如何解决。

这是我的代码:

bookings_controller.rb

class BookingsController < ApplicationController

before_action :authenticate_user!

def new
    # booking form
    # I need to find the event that we're making a booking on
    @event = Event.find(params[:event_id])
    # and because the event "has_many :bookings"
    @booking = @event.bookings.new
    # which person is booking the event?
    @booking.user = current_user
    @booking.quantity = @booking.quantity
    @total_amount = @booking_quantity.to_f * @event_price.to_f

end

def create
    # actually process the booking
    @event = Event.find(params[:event_id])
    @booking = @event.bookings.new(booking_params)
    @booking.user = current_user
    #@total_amount = @booking.quantity.to_f * @event.price.to_f

    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

    if @booking.save

        # CHARGE THE USER WHO'S BOOKED
        # #{} == puts a variable into a string
        Stripe::Charge.create(amount: @event.price_pennies, currency: "gbp",
            card: @booking.stripe_token, description: "Booking number #{@booking.id}")

        flash[:success] = "Your place on our event has been booked"
        redirect_to event_path(@event)
    else
        flash[:error] = "Payment unsuccessful"
        render "new"
    end

    if @event.is_free?

        @booking.save!
        flash[:success] = "Your place on our event has been booked"
        redirect_to event_path(@event)
    end
end

private

def booking_params
    params.require(:booking).permit(:stripe_token, :quantity)
end

end

events_controller.rb

 class EventsController < ApplicationController
before_action :find_event, only: [:show, :edit, :update, :destroy,]
# the before_actions will take care of finding the correct event for us
# this ties in with the private method below
before_action :authenticate_user!, except: [:index, :show]
# this ensures only users who are signed in can alter an event

def index
    if params[:category].blank?
        @events = Event.not_yet_happened.order("created_at DESC")
    else
        @category_id = Category.find_by(name: params[:category]).id
        @events = Event.not_yet_happened.where(category_id: @category_id).order("created_at DESC")
    end
    # The above code = If there's no category found then all the events are listed
    # If there is then it will show the EVENTS under each category only
end

def show
end

def new
    @event = current_user.events.build
    # this now builds out from a user once devise gem is added
    # after initially having an argument of Event.new
    # this assigns events to users
end

def create
    @event = current_user.events.build(event_params)
    # as above this now assigns events to users
    # rather than Event.new

    if @event.save
        redirect_to @event, notice: "Congratulations, you have successfully created a new event."
    else
        render 'new'
    end
end

def edit
    # edit form
    # @edit = Edit.find(params[:id])
    @event = current_user.events.find(params[:id])
end

def update
    if @event.update(event_params)
        redirect_to @event, notice: "Event was successfully updated!"
    else
        render 'edit'
    end
end

def destroy
    @event.destroy
    redirect_to root_path
end

private

def event_params
    params.require(:event).permit(:title, :location, :date, :time, :description, :number_of_spaces, :is_free, :price, :organised_by, :url, :image, :category_id)
    # category_id added at the end to ensure this is assigned to each new event created
end

def find_event
    @event = Event.find(params[:id])
end







end

预订表

create_table "bookings", force: :cascade do |t|
  t.integer  "event_id"
  t.integer  "user_id"
  t.string   "stripe_token"
  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
  t.integer  "quantity"
end

我已将@booking.save!添加到免费事件的create方法中,但没有更改。我还添加了交易代码块以避免超额预订,但这仅适用于付费事件。任何帮助,赞赏。

1 个答案:

答案 0 :(得分:0)

分析您的create操作方法,我找到了以下检查:

  • 在包含新数量后
  • 检查事件是否超出容量
  • 保存预订
    • 如果活动是免费的,我们就完成了
    • 否则我们会尝试创建Stripe :: Charge

因此create操作可能如下所示:

def create
  # actually process the booking
  @event = Event.find(params[:event_id])
  @booking = @event.bookings.new(booking_params)
  @booking.user = current_user
  #@total_amount = @booking.quantity.to_f * @event.price.to_f

  if ( @event.bookings.sum(&:quantity) + @booking.quantity ) > @event.number_of_spaces
    flash[:warning] = "Sorry, this event is fully booked."
    redirect_to event_path(@event)
  end

  if @booking.save
    if @event.is_free?
      flash[:success] = "Your place on our event has been booked"
      redirect_to event_path(@event)
    else
      begin
        Stripe::Charge.create(
          amount: @event.price_pennies,
          currency: "gbp",
          source: @booking.stripe_token,
          description: "Booking number #{@booking.id}"
        )

        flash[:success] = "Your place on our event has been booked"
        redirect_to event_path(@event)
      rescue => e
        @booking.destroy  # delete the entry we have just created
        flash[:error] = "Payment unsuccessful"
        render "new"
      end
    end
  end
end

当然,您需要足够好地重构代码,以确保您的控制器不会变得