Rails新手,使用Stripe的API。我的rails应用程序中有一个名为pieces的模型。每个部分都有一个名为status的整数。我只希望人们能够购买该作品,如果该作品的状态为1.在我目前的代码中,我已经隐藏了碎片上的购买按钮,除非状态为1.这大部分时间都有效,但是,如果两个人同时看到这件作品,那么他们都可以买到它们。这是因为在重新加载页面之前,其他页面上的文件状态不会更新。
我的要求:我希望找到一种方法来检查作品的状态是否为1,就在有人购买之前。如果它不是1,我希望有一条铁路闪存消息说这件作品已经被买了。这样可以防止用户收费并阻止创建charge
。
这是我的收费控制器:
class ChargesController < ApplicationController
def create
piece = Piece.find(params[:piece_id])
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => piece.total_price_in_cents,
:description => piece.title,
:currency => 'usd'
)
purchase = Purchase.create(
customer_email: params[:stripeEmail],
total_transaction: piece.total_price,
stripe_fee: piece.stripe_fee,
taxes: piece.taxes,
artist_cut: piece.artist_cut,
charity_cut: piece.charity_cut,
our_cut: piece.our_cut,
currency: charge.currency,
card: params[:stripeToken],
description: charge.description,
customer_id: customer.id,
piece_id: piece.id,
customer_name: params[:stripeShippingName],
customer_address_line_1: params[:stripeShippingAddressLine1],
customer_city: params[:stripeShippingAddressCity],
customer_state: params[:stripeShippingAddressState],
customer_zip_code: params[:stripeShippingAddressZip],
customer_country: params[:stripeShippingAddressCountry],
seller_name: piece.user.name,
seller_email: piece.user.email,
seller_address_line_1: piece.user.address_line_1,
seller_address_line_2: piece.user.address_line_2,
seller_city: piece.user.city,
seller_state: piece.user.state,
seller_zip_code: piece.user.zip_code
)
purchase.ship_by = purchase.created_at + 7.days
purchase.arrive_by = purchase.created_at + 21.days
purchase.save!
piece.status = 3
piece.save!
redirect_to pieces_path, notice: "Thanks for buying #{piece.title} for $#{'%.2f' % piece.total_price}. You should get an email shortly."
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
这是我的展示页面,上面有条纹购买按钮:
<div class="container">
<div class="row">
<div class="col-md-offset-2 col-md-8">
<div class="panel panel-default">
<div class="panel-body">
<!-- Stripe Form -->
<% if current_user != @piece.user && @piece.status == 1 %>
<%= form_tag charges_path, id: 'chargeForm' do %>
<script src="https://checkout.stripe.com/checkout.js"></script>
<%= hidden_field_tag 'stripeToken' %>
<%= hidden_field_tag 'stripeEmail' %>
<button id="btn-buy-show" type="button" class="btn btn-success btn-lg btn-block">Buy for $<%= number_with_precision(@piece.total_price, :precision => 2, :delimiter => ',')%></button>
<script>
var handler = StripeCheckout.configure({
key: '<%= Rails.configuration.stripe[:publishable_key] %>',
shippingAddress: true,
token: function(token, arg) {
document.getElementById("stripeToken").value = token.id;
document.getElementById("stripeEmail").value = token.email;
document.getElementById("chargeForm").submit();
}
});
document.getElementById('btn-buy-show').addEventListener('click', function(e) {
handler.open({
name: 'Metallic Palette',
description: '<%= @piece.title %> ($<%= number_with_precision(@piece.total_price, :precision => 2, :delimiter => ',')%>)',
amount: document.getElementById("amount").value
});
e.preventDefault();
})
</script>
<% end %>
<% end %>
<% if @piece.status == 3 %>
<p>This piece has already been bought.
<% if current_user == @piece.user || admin_user_signed_in? %>
<%= render 'pieces/purchase_details' %>
<% end %>
</p>
<% end %>
</div>
</div>
</div>
非常感谢你们。
答案 0 :(得分:0)
你只需要检查一下:)
def create
piece = Piece.find(params[:piece_id])
if piece.status != 1
flash[:error] = 'Piece is not available :('
return redirect_to peaces_path # or whatever
end
...
end
然而,很少有人建议你:
1)不要在代码中使用数字。制作常量(如Piece::AVAILABLE
)和方法(piece.available?
)或使用enum
。如果您只使用数字
2)提取表单对象 - 您不希望在控制器中拥有如此大的方法。如果将其提取为单独的服务 - 它将更加可测试,可预测和可更新。
3)将Piece.find
和片段状态检查提取到before_filters。