如何设置参数,使其无法再次更新或编辑?
问题:我有一个参数:video,一旦填充,它将向客户收费。我想这样做,以便一旦填充,就无法再次更新或编辑。
我已在视图方面采取了预防措施,一旦上传了视频,则编辑/更新表单将被隐藏并且无法再次创建,但是我注意到,如果由于某种原因更新失败,则可以返回并可以再次填写更新表单(即使视频已上传),从而再次向客户收费两次。
工作方式: 客户创建一个订单,创建一个数据条ID,一旦卖方履行了该订单(通过上传文件或视频),就会收取费用。
def charge_update
respond_to do |format|
@amount = (@order.order_price).to_i * 100
@amount_seller = (@order.order_price).to_i * 75
if @order.update(order_charge)
begin
charge = Stripe::Charge.create({
:amount => (@order.order_price).to_i * 100,
:description => 'Rails Stripe customer',
:currency => 'usd',
:customer => @order.stripe_customer_token,
:destination => {
:amount => @amount_seller ,
:account => (@order.seller.stripe_token),
}
})
rescue Stripe::CardError => e
charge_error = e.message
end
@order.update_column(:order_status, 2)
format.html { redirect_to ([@user, @order]), notice: 'Order was successfully uploaded.' }
format.json { render :show, status: :ok, location: @order }
elsif
if charge_error
flash[:error] = charge_error
redirect_to user_order_path([@user, @order])
else
format.html { render :edit }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
end
private
def order_charge
params.require(:order).permit(:video, :order_status)
end
如果有更好的方法可以验证客户的费用,请随时告诉我。我最大的担心是,由于卖方混乱,恶意等原因,客户被多次收取费用。我想保证仅向客户收取一次费用。我能想到的唯一方法是只允许对视频列进行一次更新。
要么,要么为每个视频表ID唯一的order_id的视频创建单独的表。
更新
我最终完成了以下工作……如果有任何更好的想法,我愿意提出建议!
def charge_update
respond_to do |format|
if @order.video.present?
format.html { redirect_to ([@user, @order]), notice: 'Order already completed!.' }
format.json { render :show, status: :ok, location: @order }
else
@amount = (@order.order_price).to_i * 100
@amount_seller = (@order.order_price).to_i * 75
if @order.update(order_charge)
begin
...
...
...
end
答案 0 :(得分:0)
更好的方法是制作一个具有这些值的表
order_id
video_id
user_id
charged (Boolean Value )
一旦客户下了订单并收取了费用,您就可以填写这些值并将费用值设为true。
您可以先检查他是否已订购该视频,然后再重新付款。
这是您可以为此模型制作的示例
class CustomerOrder < ActiveRecord::Base
belongs_to :customer
belongs_to :order
belongs_to :video
end
在客户下新订单之前,您可以检查是否存在任何关系
@customerorder =CustomerOrder.where(video_id: @video.id , user_id: @user.id , charged :true )
答案 1 :(得分:0)
我将使用ActiveModel::Dirty
实现一个回调,以在changing列值从空或无变为任何 not 之后的任何更改上发起回滚。
class Amount < ActiveRecord::Base
include ActiveModel::Dirty
before_save :check_video
attr_accessor :video # or whatever your video attribute is
private
def check_video
false if video_changed? && !video_was.nil? # or empty or whatever
true
end
end
答案 2 :(得分:0)
我将确保在模型层中,一旦成功创建记录,便无法再对其进行更新。
一种简单的方法可能是重写Rails在内部检查只读记录的readonly?
方法:
# in your model
def readonly?
super || video.present? && persisted?
end
在只读实例上调用save
会引发ActiveRecord::ReadOnlyRecord
异常。
使用此方法,您可以在控制器中写入if @order.readonly?
并查看@order
是否仍可更新。
答案 3 :(得分:0)
我最终创建了一个仅用于上传视频文件的控制器。
通过这种方式,我可以在创建过程中使用费用代码创建上传文件,然后无需单独进行更新就可以进行更新...
到目前为止,这是控制器的要旨:
def create
@video_order = VideoOrder.new(video_order_params)
@order = Order.find(params[:order_id])
@video_order.order_id = @order.id
respond_to do |format|
if @order.video_order.present?
format.html { redirect_to @order, notice: 'Already complete dog!.' }
format.json { render :show, status: :created, location: @video_order }
else
if @video_order.valid?
begin
charge = Stripe::Charge.create({
:amount => (@order.order_price).to_i * 100,
:description => 'Rails Stripe customer',
:currency => 'usd',
:customer => @order.stripe_customer_token,
:destination => {
:amount => @amount_seller ,
:account => (@order.seller.stripe_token),
}
})
rescue Stripe::CardError => e
charge_error = e.message
end
if charge_error
flash[:error] = charge_error
redirect_to '/'
else
if @video_order.save
@order.update_column(:order_status, 2)
format.html { redirect_to @order, notice: 'Video order was successfully created.' }
format.json { render :show, status: :created, location: @video_order }
else
format.html { render :new }
format.json { render json: @video_order.errors, status: :unprocessable_entity }
end
end
end
end
end
end
# PATCH/PUT /video_orders/1
# PATCH/PUT /video_orders/1.json
def update
respond_to do |format|
if @video_order.update(video_order_params)
format.html { redirect_to user_order_path([@user, @order]), notice: 'Video order was successfully updated.' }
format.json { render :show, status: :ok, location: @video_order }
else
format.html { render :edit }
format.json { render json: @video_order.errors, status: :unprocessable_entity }
end
end
end
为了防止万一,我在create方法中也采取了预防措施。