0

I'm creating a ticket booking app as my sample project using Ruby on Rails 4.1. Three are three models - Events, Tickets and Bookings. Events have many tickets and bookings. Tickets have many bookings and they belong to events. Bookings belongs to events and tickets.

The routes file looks like:

Rails.application.routes.draw do

resources :charges

root 'events#index'

resources :events do
resources :tickets
resources :bookings
end
end

The buttons to the new booking page are located in my events/show page which has the following code:

<% @event.tickets.each do |ticket| %>
 <div class="row">
<div class="col-md-8">
  <table class="table">
    <thead>
          <tr>
              <th>Name</th>
              <th>Price</th>
              <th>Quantity</th>
          </tr>
      </thead>
      <tbody>
          <tr>
              <td><%= ticket.ticket_name %></td>
              <td><%= ticket.ticket_price %></td>
              <td><%= ticket.ticket_quantity %></td>
              <td><%= link_to "Buy Now", new_event_booking_path(@event, ticket), class: "btn btn-primary" %></td>
              <td><%= link_to "Edit", edit_event_ticket_path(@event, ticket), class: "btn btn-link" %></td>
              <td><%= link_to "Delete", event_ticket_path(@event, ticket), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-link" %></td>
      </tr>
  </table>
</div>
</div>

As you can see, the event and ticket variables are grabbed when the user clicks the "Buy Now" button. However, when I use the following code in my Bookings controller:

class BookingsController < ApplicationController

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

def create
@event = Event.find(params[:event_id])
@ticket = @event.tickets.find(params[:id])
@booking = @event.bookings.create(booking_params)

if @booking.save
    redirect_to [@event, @booking]
else
    render 'new'
end
end

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

  private
  def booking_params
params.require(:booking).permit(:buyer_name, :email, :mobile, :address, :order_quantity)
  end
end

I get the ActiveRecord::RecordNotFound in BookingsController#new. Couldn't find Ticket without an ID error.

The new page looks like this (pretty barebones as I testing the functionality)

<%= form_for ([@event, @booking]) do |f| %>
 <div class="row">
  <div class="form-group">
    <%= f.label :buyer_name %>
    <%= f.text_field :buyer_name, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= f.label :order_quantity %>
    <%= f.text_field :order_quantity, class: "form-control" %>
  </div>

</div>
  <%= f.submit "Pay now", class: "btn btn-primary" %>

The Events Model:

has_many :tickets, dependent: :destroy
has_many :bookings
has_many :charges

The Tickets model:

belongs_to :event
has_many :bookings

The Bookings model:

belongs_to :event
belongs_to :ticket
has_many :charges

The foreign key association looks like this:

add_reference :bookings, :ticket, index: true

How to solve this error?

8
  • I think that new_event_booking_path(@event, ticket) sends the wrong params. params[:id] is nil. Commented Jul 22, 2014 at 13:16
  • Do you have a GitHub page for this? Commented Jul 22, 2014 at 13:30
  • @DougSteinberg here you go. bitbucket.org/stravarius/ticket-fire Commented Jul 22, 2014 at 13:43
  • @xlembouras Yep, the ticket params aren't passed on. Using Better errors gem to figure out more. Still no clue. Commented Jul 22, 2014 at 13:45
  • Please post your relevant routes. Most probably thats where the problem lies. Commented Jul 22, 2014 at 14:06

2 Answers 2

1

You can not add ticket to the new_event_booking_path, the way you have done. Instead, do it this way:

new_event_booking_path(@event, ticket_id: ticket.id)

Note that we are adding an additional parameter called ticket_id to the path. This is because route for event_booking_path does not know anything about ticket.

Then, in your controller, find the ticket like this:

@ticket = @event.tickets.find(params[:ticket_id])

Update

In your form, add a hidden field for ticket_id like this:

<%= hidden_field_tag :ticket_id, @ticket.id.to_s %>
Sign up to request clarification or add additional context in comments.

5 Comments

I changed it and the new form now renders fine. But, the same error occurs when I hit the submit button. In the create action, the error says Couldn't find Ticket without an ID. Have made only the changes that you suggested in both places.
still getting the same error. In the value, you have suggested using the instance variable for ticket. But the form block uses only events and booking instance variables. Is the usage right?
That was my mistake. You need to use hidden_field_tag instead of f.hidden_field. Updated the answer.
Thanks a ton. It's working. I really appreciate your help! If it's no bother, can you let me know why the ticket_id field in the booking table is always empty? The events id is perfectly captured and when looking at sqlite browser, ticket_id is empty. I have pasted the model relations in the question.
In create action, before if @booking.save line, add this line: @booking.ticket = @ticket.
0

You need to take @ticket out of new and create

@ticket = @event.tickets.find(params[:id])

There is no params[:id] being passed in from the Buy Now link

Take that line out of new and create actions and your error should go away

2 Comments

There are multiple ticket tiers - Early bird, student etc. and I need the ticket variable to get hold of the respective ticket id number and associate with the booking. Besides, I'll need to use it to access the total ticket quantity, ticket price etc.
Well, params[:id] is not being passed into your action from the link. You need to find a way to add the ticket id to the action. One thing I noticed from your routes it that the tickets and bookings are nested in the same namespace. You would need to generate a rout that looks like /booking/22/ticket/12 to have access to the booking id and ticket id. So you need to nest the ticket routes under booking to get that. The problem with that is it will mess up a lot of the links you already have set up in your app. So you're really going to have to redo a lot of stuff to get this to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.