2

I have a Booking model , associated with Availability > Facility > Venue

I have a page in my view which renders all bookings for a given venue and it's causing a huge N+1 query.

Controller Action:

  def summary
    @venue = Venue.find params[:venue_id]
    @bookings = Booking.includes{availability.facility.venue}.for_venue(@venue).references(:all).sort_recent
  end 

View:

<table id="booking-history" class="table table-condensed table-hover">
    <thead>
        <th>Date</th>
        <th>Time</th>
        <th>Facility</th>
        <th>Purchase Time</th>
        <th>User</th>
        <th>Price</th>
        <th>Receipt</th>
    </thead>
    <tbody>
        <!-- venue_bookings is a method in venues helper -->
        <%= render :partial => "bookings/booking", collection: bookings, as: :booking %>

    </tbody>
</table>

Partial:

    <tr>
  <!-- avail date -->
  <td><%= booking.availability.start_time.strftime("%a, %b %d %Y")%></td>
  <!-- avail time -->
  <td><%= booking.availability.start_time.strftime("%I:%M")%> - <%= booking.availability.end_time.strftime("%I:%M  %p")%></td>
  <td><%= booking.facility.name %></td>
  <td><%= booking.created_at.to_formatted_s(:short) %></td>
  <td><%= User.find(booking.user_id).name %></td>
  <td><%= number_to_currency booking.total_price%></td>
  <!-- Receipt Link -->
  <td> <%= link_to("Receipt", charge_path(booking) ) %></td>
</tr>

Bullet Log:

user: vagrant
N+1 Query detected
  Booking =&gt; [:facility]
  Add to your finder: :includes =&gt; [:facility]
N+1 Query method call stack
  /vagrant/playtoday/app/views/bookings/_booking.html.erb:6:in `_app_views_bookings__booking_html_erb___965508066735177428_69970894883840'
  /vagrant/playtoday/app/views/bookings/_bookingHistory.html.erb:21:in `_app_views_bookings__booking_istory_html_erb___724060916350777358_69971212148620'

I already have includes in the class variable, I'm not sure where else I should be doing it.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Batman
  • 5,563
  • 18
  • 79
  • 155
  • I've never seen `includes` used in that format. Did you try `includes(availability: { facility: :venue })` – sjagr Nov 10 '15 at 21:41
  • It's the syntax that Squeel gem uses for joins. They amount to the same thing – Batman Nov 10 '15 at 21:51
  • 2
    What about `@bookings = Booking.includes(:availability, :facility, :venue).where(venue: @venue)` ? – MC2DX Nov 10 '15 at 22:09
  • 1
    @Batman You should mention that in your question. – sjagr Nov 10 '15 at 22:25
  • @MateuszCzerwiński that seemed to have worked. Now the majority returned from the cache and bullet isn't reporting an N1 issue. – Batman Nov 10 '15 at 22:52
  • You can use `<%= render @bookings %>` to render the collection in the partial instead - rails will use convention over configuration and figure out the partial all by itself. http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-collections – max Nov 10 '15 at 23:00
  • `Rails.cache.clear`? – MC2DX Nov 11 '15 at 06:32
  • @MateuszCzerwiński why do I need to clear the cache? It seems to be working as intended, I think. Isn't it a good thing it's returning everything from the cache? – Batman Nov 11 '15 at 17:54
  • If data doesn't change, it can faster loading data but sometimes it helps a lot and fix errors. – MC2DX Nov 11 '15 at 18:09
  • Awesome, I'll keep it in mind. Thanks for the help, everything seems to be working fine now. – Batman Nov 11 '15 at 19:08

0 Answers0