简体   繁体   中英

Rails 4 ActiveRecord help using includes query with Postgres

We're trying to eager load an association with the AR includes query, but we're running into an issue.

The relevant bit in the controller:

def index
  @students = current_admin.current_cohort.students.includes(:attendance_records)
end

That part seems to work fine with the resulting query:

  Student Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."type" IN ('Student') AND "users"."id" IN (413, 400, 386, 399, 380, 410)  ORDER BY "users"."name" ASC
  Student Load (0.8ms)  SELECT "users".* FROM "users" WHERE "users"."type" IN ('Student') AND "users"."cohort_id" = $1  ORDER BY "users"."name" ASC  [["cohort_id", 8]]
  AttendanceRecord Load (4.2ms)  SELECT "attendance_records".* FROM "attendance_records" WHERE "attendance_records"."student_id" IN (212, 216, 210, 282, 305, 283, 361, 265, 168, 229, 228, 376, 338, 223, 339, 308, 214, 185, 165, 224, 211, 91, 172, 221, 266, 220, 192, 240, 173, 226, 218, 302, 183, 241, 163, 219, 243, 231, 272, 244, 362, 213, 328, 171, 227, 202, 201, 275, 248, 236, 342, 217, 293, 194, 208, 39, 199, 170, 284)

The problem is that we're checking for attendance records elsewhere in the view, as shown below. Something in this part is querying the database for attendance records, even though they've already been preloaded, resulting in an n+1 query problem.

View code:

<% if student.signed_in_today? %>
  <p class="text-success"><span class="check">&#x2713;</span> Signed in</p>
    <% if student.signed_out_today? %>
      <p class="text-success"><span class="check">&#x2713;</span> Signed out</p>
    <% else %>
      <%= form_for student.attendance_records.today.first do |f| %>
        <%= f.hidden_field :student_id, value: student.id %>
        <%= f.hidden_field :signing_out, value: true %>
        <%= f.submit "I'm leaving", class: 'btn btn-warning' %>
      <% end %>
    <% end %>
<% else %>
  <%= form_for AttendanceRecord.new do |f| %>
    <%= f.hidden_field :student_id, value: student.id %>
    <%= f.submit "I'm soloing", class: 'btn btn-primary' %>
  <% end %>
<% end %>

Model code:

# Student model
  def signed_in_today?
    attendance_records.today.exists?
  end

  def signed_out_today?
    if signed_in_today?
      attendance_records.today.first.signed_out_time != nil
    end
  end

# AttendanceRecord model
    scope :today, -> { where(date: Time.zone.now.to_date) }

The problematic query is below:

  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 212], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 216], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 210], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 282], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 305], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 283], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 361], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 265], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 168], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 229], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 228], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 376], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 338], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 223], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 339], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 308], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 214], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 185], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 165], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 224], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 211], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 91], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 172], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 221], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 266], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 220], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 192], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 240], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.3ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 173], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 226], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 218], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 302], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 183], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 241], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 163], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 219], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 243], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 231], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 272], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 244], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 362], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 213], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 328], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 171], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 227], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 202], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 201], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 275], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 248], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 236], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 342], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.2ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 217], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 293], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 194], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 208], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.3ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 39], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 199], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 170], ["date", "2015-09-17"]]
  AttendanceRecord Exists (0.1ms)  SELECT  1 AS one FROM "attendance_records" WHERE "attendance_records"."student_id" = $1 AND "attendance_records"."date" = $2 LIMIT 1  [["student_id", 284], ["date", "2015-09-17"]]

Any help would be greatly appreciated. Thanks!

As soon as you call where (as you do in your today scope), you will trigger a query. You are getting the records you need with your student index query - they will all be in memory, so you should treat that as an array - use array methods like select to find the records you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM