Mike.Whitehead Mike.Whitehead - 1 month ago 10
Ruby Question

Rails - How to ensure a parameter is updated correctly

I'm building an events app using rails. For the payment process I'm using Stripe and some javascript to update the amounts. I want the user to be able to specify the number of spaces (quantity) they wish to pay for and for this to update the total amount they then need to pay.
The code I'm using is updating the text for the total amount payable but it's not updating the server so every time I do a test payment only one single amount is collected. So, if an event costs £10 per space and I try and input, say, 4 spaces (£40) when I do a test only £10 has been collected by Stripe.
I need to ensure the quantity parameter is being passed correctly.

This is my booking page code -

new.booking.html.erb

<div class="col-md-6 col-md-offset-3" id="eventshow">
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h2>Confirm Your Booking</h2>
</div>



<%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>

<div class="calculate-total">
<p>
Confirm number of spaces you wish to book here:
<input type="number" placeholder="1" min="1" value="1" class="num-spaces">
</p>
<p>
Total Amount
£<span class="total" data-unit-cost="<%= @event.price %>">0</span>
</p>
</div>



<span class="payment-errors"></span>

<div class="form-row">
<label>
<span>Card Number</span>
<input type="text" size="20" data-stripe="number"/>
</label>
</div>

<div class="form-row">
<label>
<span>CVC</span>
<input type="text" size="4" data-stripe="cvc"/>
</label>
</div>

<div class="form-row">
<label>
<span>Expiration (MM/YYYY)</span>
<input type="text" size="2" data-stripe="exp-month"/>
</label>
<span> / </span>
<input type="text" size="4" data-stripe="exp-year"/>
</div>
</div>
<div class="panel-footer">

<%= form.button :submit %>


</div>

<% end %>
<% end %>

</div>
</div>
</div>

<script type="text/javascript">
$('.calculate-total input').on('keyup change', calculateBookingPrice);

function calculateBookingPrice() {
var unitCost = parseFloat($('.calculate-total .total').data('unit-cost')),
numSpaces = parseInt($('.calculate-total .num-spaces').val()),
total = (numSpaces * unitCost).toFixed(2);

if (isNaN(total)) {
total = 0;
}

$('.calculate-total span.total').text(total);


}

$(document).ready(calculateBookingPrice)

</script>


This is my controller code with the quantity param -

bookings_controller.rb

def new
# booking form
# I need to find the event that we're making a booking on
@event = Event.find(params[:event_id])
# and because the event "has_many :bookings"
@booking = @event.bookings.new(quantity: params[:quantity])
# which person is booking the event?
@booking.user = current_user
#@total_amount = @event.price * @booking.quantity


end

def create

# actually process the booking
@event = Event.find(params[:event_id])
@booking = @event.bookings.new(booking_params)
@booking.user = current_user

if
@booking.reserve
flash[:success] = "Your place on our event has been booked"
redirect_to event_path(@event)
else
flash[:error] = "Booking unsuccessful"
render "new"
end
end


booking.rb

class Booking < ActiveRecord::Base

belongs_to :event
belongs_to :user

validates :total_amount, presence: true, numericality: { greater_than: 0 }
validates :quantity, :total_amount, presence: true


def reserve
# Don't process this booking if it isn't valid
self.valid?

# We can always set this, even for free events because their price will be 0.
#self.total_amount = booking.quantity * event.price

# Free events don't need to do anything special
if event.is_free?
save!

# Paid events should charge the customer's card
else

begin
self.total_amount = event.price * self.quantity
charge = Stripe::Charge.create(
amount: total_amount * 100,
currency: "gbp",
source: stripe_token,
description: "Booking created for amount #{total_amount}")
self.stripe_charge_id = charge.id
save!
rescue Stripe::CardError => e
errors.add(:base, e.message)
false
end
end

end
end


How do I amend this so the total amount is correctly collected?

This is the output from my development log -

Started POST "/events/25/bookings" for ::1 at 2016-10-06 18:57:42 +0100
Processing by BookingsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qHYjvqAqNORnpBKjk4KdQ4++X53Av1KVO+BVIWkq0asLbyd8ssEJKFFcvR9CQHwc+UdAM041gpO3ZFlz0t7o9Q==", "quantity"=>"2", "booking"=>{"stripe_token"=>"tok_191g7l2hHbuHRh0YjftQP0eC"}, "event_id"=>"25"}
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 2]]
[1m[35mEvent Load (0.2ms)[0m SELECT "events".* FROM "events" WHERE "events"."id" = ? LIMIT 1 [["id", 25]]
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
[1m[35mSQL (0.3ms)[0m INSERT INTO "bookings" ("stripe_token", "event_id", "user_id", "total_amount", "stripe_charge_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["stripe_token", "tok_191g7l2hHbuHRh0YjftQP0eC"], ["event_id", 25], ["user_id", 2], ["total_amount", 1], ["stripe_charge_id", "ch_191g7m2hHbuHRh0YGAZhmxIu"], ["created_at", "2016-10-06 17:57:43.430265"], ["updated_at", "2016-10-06 17:57:43.430265"]]

Answer

I think name parameter is missing in the input tag. Try the below one.

<input type="number" name="booking[quantity]" placeholder="1" min="1" value="1" class="num-spaces”>

And check whether the quantity parameter is received with the correct value in server.

May be with puts params[:quantity] in create method in the controller.

Comments