Hi,
After introducing Active Storage into one of my models I’m experiencing an N+1 query on active_storage_attachments
that I can’t quite figure out how to resolve.
Here’s my associations:
class Course < ApplicationRecord
has_many :sections
has_many :lessons, through: :sections
end
class Section < ApplicationRecord
belongs_to :course
has_many :lessons
has_many :videos, through: :lessons
end
class Lesson < ApplicationRecord
belongs_to :section
has_many_attached :downloads
has_one :course, through: :section
has_one :video
end
class Video < ApplicationRecord
belongs_to :lesson
has_one :course, through: :lesson
end
My goal is to be able to build a table of contents and loop through all of the sections
and display a list of sections, lessons, video durations and display a number of files for each lesson. All of this is working except for the N+1 query.
Here’s my main controller query and view:
@sections = @course.sections.preload(:lessons, :videos).all
<% sections.each do |section| %>
[REDACTING A BUNCH OF THINGS HERE, IT IS NOT IMPORTANT]
<% section.lessons.each do |lesson| %>
[REDACTING A BUNCH OF THINGS HERE, IT IS NOT IMPORTANT]
<% lesson.downloads.includes(:blob).references(:blob).order(:filename).each do |download| %>
[REDACTING A BUNCH OF THINGS HERE, IT IS NOT IMPORTANT]
<% end %>
<% end %>
<% end %>
- The includes the blob query so I can sort the downloads by filename, I’m not sure if there’s a better way but I get the N+1 query with and without this part
I tried a bunch of combinations of things unsuccessfully. No matter what I try I end up with this query executing 212 times (1 for each lesson):
SQL (1.4ms) SELECT "active_storage_attachments"."id" AS t0_r0, "active_storage_attachments"."name" AS t0_r1, "active_storage_attachments"."record_type" AS t0_r2, "active_storage_attachments"."record_id" AS t0_r3, "active_storage_attachments"."blob_id" AS t0_r4, "active_storage_attachments"."created_at" AS t0_r5, "active_storage_blobs"."id" AS t1_r0, "active_storage_blobs"."key" AS t1_r1, "active_storage_blobs"."filename" AS t1_r2, "active_storage_blobs"."content_type" AS t1_r3, "active_storage_blobs"."metadata" AS t1_r4, "active_storage_blobs"."service_name" AS t1_r5, "active_storage_blobs"."byte_size" AS t1_r6, "active_storage_blobs"."checksum" AS t1_r7, "active_storage_blobs"."created_at" AS t1_r8 FROM "active_storage_attachments" LEFT OUTER JOIN "active_storage_blobs" ON "active_storage_blobs"."id" = "active_storage_attachments"."blob_id" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 ORDER BY "filename" ASC [["record_id", 208], ["record_type", "Lesson"], ["name", "downloads"]]
I think I need to do something with with_attached_downloads
but I can’t figure out where that would go. That scope is referenced here: ActiveStorage::Attachment
I can really use your assistance, thanks!