H30秋FE試験 問3 を RubyonRails で作ってみる
/
H30 秋 FE 試験の問 3 のコンサートに則したサイトを実際に作っていた。
Refferrence
Transaction for Payment controller
コンサートチケットの支払い時の、ポイント使用・追加あたりの、Payment コントローラ内に実装。
Transaction flow
- ユーザーはポイント User.point を持っている
- 購入時に User.point の一部/全部を支払額 Sale.amount に充てることができる
- 使用ポイント Sale.used_point が更新される
- 支払額から使用した User.point を引いたものが、決済額 Payment.amount となる
- 決済額 Payment.amount のうち、デフォルトの割合が付与ポイント Payment.added_point となる
- ユーザーのポイント残高は、支払前の
User.point - Sale.used_point + Payment.added_point
で更新される
支払い完了の条件
- User.point、Sale.used_point、Payment.added_point はすべて 0 以上(>=0)
- モデル側のバリデーション
validates :point, numericality: { greater_than_or_equal_to: 0 }
利用
- モデル側のバリデーション
- User.point >= Sale.used_point
- False となる操作は悪意しかないので、トランザクション外の if 文で
Implement
User.point、Sale.used_point、Payment.added_point はすべて 0 以上(>=0)
# User modelvalidates :point, numericality: { greater_than_or_equal_to: 0 }# Sale modelvalidates :used_point, numericality: { greater_than_or_equal_to: 0 }# Payment modelvalidates :added_point, numericality: { greater_than_or_equal_to: 0 }
def payment @user = # ... @sale = # ... @concert = # ... @payment = Payment.new(sale_id: @sale.id, date: Date.current) respond_to do |format| if current_user.point < params_used_point # 所持ポイントを超過している旨の警告文 (以下、ポイントをPと略す) else # when pay with appropriate points begin ActiveRecord::Base.transaction do if @sale.amount <= params_used_point # when using points is over sale price @sale.update!(used_point: @sale.amount) # succeeded in paying @payment.update(amount: 0, added_point: 0) else @sale.update!(used_point: params_used_point) @payment.update!(amount: pay_amount, added_point: 追加P計算関数) end @user.update!(point: ユーザP更新関数) # completed to pay end rescue StandardError => e # if transaction failed logger.error e logger.error e.backtrace.join("\n") @sale = # ... @concert = # ... format.html { render :confirm, notice: 'エラー' } end end endend