Mike.Whitehead Mike.Whitehead - 18 days ago 4
Ruby Question

Rails error - ActionController::UrlGenerationError in BookingsController (Create action)

I'm building an events app using rails and I've run into the error above at the end of the booking confirmation process. This is the full error -
Full error

And this is my controller code -

Bookings Controller

class BookingsController < ApplicationController

before_action :authenticate_user!



def new

@event = Event.find(params[:event_id])
# and because the event "has_many :bookings"
@booking = Booking.new(params[:booking])
@booking.user = current_user



end

def create

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


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

if @event.is_free?
@booking.save(booking_params)
end
end

def show
@event = Event.find(params[:event_id])
@booking = Booking.find(params[:id])
end


def update

if @booking.update(booking_params)
redirect_to event_booking_path(@event, @booking) , notice: "Booking was successfully updated!"
else
render 'new'
end
end




private

def booking_params
params.require(:booking).permit(:stripe_token, :booking_number, :quantity, :event_id, :stripe_charge_id, :total_amount)
end






end


I'm trying to implement code to handle both free and paid events/bookings. The event side is fine but handling free bookings has proved troublesome. This is the Booking model code -

Booking.rb

class Booking < ActiveRecord::Base

belongs_to :event
belongs_to :user


before_create :set_booking_number

validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :quantity, :total_amount, :booking_number, presence: true

def set_booking_number
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end



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


if self.event.is_free?

self.total_amount = 0
else



begin
self.total_amount = event.price_pennies * self.quantity
charge = Stripe::Charge.create(
amount: total_amount,
currency: "gbp",
source: stripe_token,
description: "Booking created for amount #{total_amount}")
self.stripe_charge_id = charge.id
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
save!
rescue Stripe::CardError => e
errors.add(:base, e.message)
false
end
end
#end
end
end


This issue arose following the inclusion of the validations - the problem has been trying to implement validations that apply to paid events but not free.

Any assistance with the above error would be appreciated.

Answer

Try replacing

redirect_to event_booking_path(@event, @booking)

with

redirect_to event_booking_path(id: @booking.id, event_id: @event.id)

UPDATE

I believe the error is because @booking.id is evaluating to nil. It would happen is @booking is not saved to db (still a new record). In you model method booking, inside if block, you are just setting an attribute, but not saving the object. So, calling save! inside if block after setting the attribute should fix this.

def booking
  if self.event.is_free?
    self.total_amount = 0
    save!
  else
    ...
  end
end