Reputation: 525
I have an application that I am testing stripe payments on. Right now, I am trying to configuring the charge so that it takes the price from another model (pin.price) and charges it correctly. So far, I am running into the following error message:
NoMethodError in ChargesController#create undefined method `price' for nil:NilClass
app/controllers/charges_controller.rb
class ChargesController < ApplicationController
def create
# Amount in cents
@amount = (@pin.price * 100).floor
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => @amount,
:description => 'Rails Stripe customer',
:currency => 'usd'
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
end
app/controllers/pins_controller.rb
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy, :bid]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
.....
def pin_params
params.require(:pin).permit(:description, :price, :image, :manufacturer, :model)
end
end
app/db/migrate
class AddPriceToPins < ActiveRecord::Migration
def change
add_column :pins, :price, :decimal
end
end
I'm pretty sure the error is coming from "@amount = (@pin.price * 100).floor" but I am just not sure how to better express this amount so each pin's price isn't static but matches to its current inputted value in the database.
EDIT: Including form with link to stripe payment code here:
<%= form_tag charges_path, id: 'chargesForm' do %>
<script src="https://checkout.stripe.com/checkout.js"></script>
<%= hidden_field_tag 'stripeToken' %>
<%= hidden_field_tag 'stripeEmail' %>
<button id="btn-buy" type="button" class="btn btn-success btn-lg btn-block"><span class="glyphicon glyphicon-heart"></span> I want this!</button>
<script>
var handler = StripeCheckout.configure({
key: '<%= Rails.configuration.stripe[:publishable_key] %>',
token: function(token, arg) {
document.getElementById("stripeToken").value = token.id;
document.getElementById("stripeEmail").value = token.email;
document.getElementById("chargesForm").submit();
}
});
document.getElementById('btn-buy').addEventListener('click', function(e) {
handler.open({
name: '<%= @pin.manufacturer %>',
description: '<%= @pin.description %>',
amount: '<%= (@pin.price * 100).floor %>'
});
e.preventDefault();
})
</script>
<% end %>
Any thoughts?
Upvotes: 0
Views: 1297
Reputation: 2961
The problem is that in your charges controller @pin
isn't assigned to anything and therefore has a value of nil
hence the error.
You therefore need to assign @pin
to a value before you call price on it. In order to do that you need to figure out how you are going to get the pin from the DB or whether or not you create it.
One solution could be to pass in the id of the pin in the request path, e.g.
create_charge_path(pin_id: 123)
EDIT: This doesn't have to be hardcoded to 123 it can be whatever pin you like, just depends on where it's being called from. E.g. if you are calling from another controller action that has already loaded a particular pin from the database you could do:
create_charge_path(pin_id: pin.id)
Then in your ChargesController
class ChargesController < ApplicationController
def create
@pin = Pin.find(params[:pin_id])
# Amount in cents
@amount = (@pin.price * 100).floor
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => @amount,
:description => 'Rails Stripe customer',
:currency => 'usd'
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
end
This will then assign @pin
to a pin with a database ID of 123
.
Upvotes: 1