Rails错误 - 订阅失败
我使用Rails构建一个Event应用程序。我最近改变了我的预订控制器,以适应免费的活动。应用程序的这一面似乎工作正常,但当我尝试为付费活动进行测试预订时,应用程序在完成付款提交表单后默认为“预订不成功”。Rails错误 - 订阅失败
我不确定为什么会发生这种情况。这里是我的控制器逻辑 -
def new
@event = Event.find(params[:event_id])
@booking = Booking.new
@booking.user = current_user
end
def create
@event = Event.find(params[:event_id])
@booking = Booking.new(booking_params)
@booking.user = current_user
if
@booking.save
flash[:success] = "Your place on our event has been booked"
redirect_to event_booking_path(@event, @booking)
else
flash[:error] = "Booking unsuccessful"
render "new"
end
end
def show
@event = Event.find(params[:event_id])
@booking = Booking.find(params[:id])
end
def update
if @booking.update(booking_params)
redirect_to event_booking_path(@event, @booking) , notice: "Booking was successfully updated!"
else
render 'new'
end
end
private
def booking_params
params.require(:booking).permit(:stripe_token, :booking_number, :quantity, :event_id, :stripe_charge_id, :total_amount)
end
而且在我的模型我有这个 -
Booking.rb
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
before_create :set_booking_number
validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :quantity, :total_amount, :booking_number, presence: true
def set_booking_number
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end
def booking
# Don't process this booking if it isn't valid
self.valid?
if booking.is_free?
self.total_amount = event.price_pennies.nil?
save!
end
begin
self.total_amount = event.price_pennies * self.quantity
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
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
save!
rescue Stripe::CardError => e
errors.add(:base, e.message)
false
end
end
end
所以,由于某种原因,它不保存或还有别的东西不对。任何援助赞赏。
这是完整的代码?你的“booking.rb”似乎完全错误。
您正在定义一个“预订”方法,但我没有看到您在任何地方调用它。 除了可能在预订法本身,当你执行
if booking.is_free?
你混的东西了吗?
你的意思是在控制器?用@ booking.is_free?在这个模型中,我试图区分免费预订和付费预订。在我的事件模型中,我有一个if_free?属性,但不是在预订,所以我试图在这里分开他们。 –
好的。但在您的Booking.rb中,您定义了一个“预订”方法,并在第4行中称您为“booking.is_free?”但此预订仅引用方法本身。这就是为什么我问代码是否完整。或者您是否打算调用event.is_free?或某种@ booking.is_free? – Fallenhero
也许是完整的预订。rb会有帮助 – Fallenhero
好的,让我们来看看。
我想你需要的东西是这样的:
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
before_create :set_booking_number
### new
before_save(:set_total_amount)
validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :quantity, :total_amount, :booking_number, presence: true
### new
validate(:validate_booking)
def set_booking_number
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end
def set_total_amount
# does event.is_free? exist? if not: either define .is_free? or use self.event.price_pennies.nil? or self.event.price_pennies.to_i == 0
if self.event.is_free?
# I am guessing total_amount is an Int but you are assigning a boolean
# self.total_amount = event.price_pennies.nil?
# should be
self.total_amount = 0
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
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
# booking number was already set, see set_booking_number
# self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end
end
# is suppose to be a validation, so I renamed it
# def booking
def validate_booking
# Don't process this booking if it isn't valid
# will be called on .save anyway
# self.valid?
# I pushed this to set_total_amount (called by before_save)
# if booking.is_free?
# self.total_amount = event.price_pennies.nil?
# Why call save! ? with "!" it will cast an exception if invalid
# save!
# end
# also pushed to set_total_amount since this has nothing to do with validation
# begin
# self.total_amount = event.price_pennies * self.quantity
# 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
# self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
# save!
# rescue Stripe::CardError => e
# errors.add(:base, e.message)
# false
# end
# stripe_charge_id must be set for not free events
unless self.event.is_free?
return !self.stripe_charge_id.nil?
end
end
end
这当然是未经测试。但请放手。
我希望我的意见很明确。
谢谢你。这一切看起来不错。我已经对自己的部分内容进行了一些修改,并将其中的一些内容进行了整合 - 上述回答的主要问题是“保存”!需要在控制器中传递适当的参数。我会尽快发布我的最终代码。 –
终于突破了关于参数的一些工作,并在模型代码上工作。下面是我的控制器和模型最终代码 -
Booking.rb
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
before_create :set_booking_number
validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validate(:validate_booking)
def set_booking_number
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end
def set_booking
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
self.stripe_charge_id = nil
end
end
end
unless self.event.is_free?
return !self.stripe_charge_id.nil?
end
end
end
Bookings_controller.rb
class BookingsController < ApplicationController
before_action :authenticate_user!
def new
@event = Event.find(params[:event_id])
# and because the event "has_many :bookings"
@booking = Booking.new(params[:booking])
@booking.user = current_user
end
def create
# actually process the booking
@event = Event.find(params[:event_id])
@booking = @event.bookings.new(booking_params)
@booking.user = current_user
if
@booking.set_booking
flash[:success] = "Your place on our event has been booked"
redirect_to event_booking_path(@event, @booking)
else
flash[:error] = "Booking unsuccessful"
render "new"
end
if @event.is_free?
@booking.save(booking_params)
end
end
def show
@event = Event.find(params[:event_id])
@booking = Booking.find(params[:id])
end
def update
if @booking.update(booking_params)
redirect_to event_booking_path(@event, @booking) , notice: "Booking was successfully updated!"
else
render 'new'
end
end
private
def booking_params
params.require(:booking).permit(:stripe_token, :booking_number, :quantity, :event_id, :stripe_charge_id, :total_amount)
end
end
那就像你期望的那样工作? – Fallenhero
是的。迄今为止都很好。 –
看到错误消息对视图通过显示验证错误。 'flash [:error] = @ booking.errors.full_messages.join(',')' – usha
您的代码看起来不完整...不确定您预订模型中的预订方法从哪里调用,但它看起来不是从你的控制器。也可以很方便地看到你的模型中有什么验证。 – David
全预订型号代码现在添加了验证。有什么想法吗?而不是booking.is_free?它应该是一个带有event.is_free的if/else语句吗?那么'其他'付费方法代码? (见下面的其他评论) –