I posted a question last week about refactoring an after_create callback. The code in this question is for the create action. I'm using Stripe to handle credit card payments and am roughly following the railscast on Stripe integration.
Here's my create action on the Payment model:
def create
@unpaid_subs = Subscription.where(:user_id => current_user.id).unpaid.includes(:course)
@payment = Payment.new(params[:payment])
@payment.user_id = current_user.id
@payment.email = current_user.email
@payment.kind = @payment.determine_kind
@payment.amount = calculate_cost(@unpaid_subs)
if @payment.save_with_payment
redirect_to dashboard_url, :notice => "Thank you for Paying!"
else
render :action => 'new'
end
end
I am going to change the model associations so that payment belongs_to :user
, so setting the user_id and email will go away. Here's the save_with_payment
method:
def save_with_payment
if valid?
charge = Stripe::Charge.create(amount: amount, description: "Charge for #{email}", card: stripe_card_token, currency: "usd")
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating charge: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
determine_kind
is a simple if conditional for setting the kind attribute. calculate_cost
is in a module right now and included where needed.
def calculate_cost(unpaid) # Used to return amount total in cents for payment
@amount_in_pesos = BigDecimal.new(unpaid.size) * COURSE_COST
@amount_in_cents = (@amount_in_pesos.div(EXCHANGE_RATE, 10).round(2) * 100).to_i
@amount = @amount_in_cents
@amount
end
So, I'm mainly wanting general suggestions for improvement of this code. I was a little confused as to where calculate_cost should go (maybe as a method on the Payment model, even though it doesn't use an instance of Payment). Is there any better way to handle the call to the Stripe API?