[英]Allowing only one update for specific param?
如何填充參數,使其無法再次更新或編輯?
問題:我有一個參數: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的視頻創建一個單獨的表。
UPDATE
我最終做了下面的工作,...如果有任何更好的想法,我願意提出建議!
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
更好的方法是制作一個具有這些值的表
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 )
我將使用ActiveModel::Dirty
實現回調,以在將列值更改 為非 null或nil之外的任何值時啟動對任何更改的回滾。
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
我將確保在模型層中,一旦成功創建記錄,就無法再對其進行更新。
一種簡單的方法可能是重寫readonly?
Rails用於在內部檢查只讀記錄的方法:
# in your model
def readonly?
super || video.present? && persisted?
end
在只讀實例上調用save
將引發ActiveRecord::ReadOnlyRecord
異常。
使用這種方法,您可以編寫if @order.readonly?
在控制器中,並查看@order
是否仍可更新。
我最終創建了一個僅用於上傳視頻文件的控制器。
這樣,我可以在創建過程中使用費用代碼創建上傳文件,然后無需單獨進行更新就可以進行更新...
到目前為止,這是控制器的要點:
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方法中也有預防措施。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.