Admin chapter workshops index is unbounded (no pagination + per-row COUNT queries)
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 104
- Forks
- 205
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 63
Description
Summary
Admin::WorkshopsController#index (/admin/chapters/:chapter_id/workshops) loads every workshop for the chapter and runs one extra SQL COUNT per rendered row. Slow on older chapters — chapter 1 (London) has ~13 years of workshops (~700+).
Symptom
- One page view loads 700+
Workshoprecords and renders 700+<tr>rows. - Each row's
workshop.invitations.accepted.countemits a separate SQL COUNT — ~700 queries per page view. - Memory, DB time, and DOM size all scale with chapter age, so the page degrades as the chapter grows.
Root cause (two compounding problems)
1. Unbounded result set
app/controllers/admin/workshops_controller.rb:
@workshops = @chapter.workshops.includes(:sponsors)
No pagination. The view renders all rows in a single table.
2. N+1 COUNT queries in the view
app/views/admin/workshops/index.html.haml:
= workshop.invitations.accepted.count
One query per workshop per render. Each COUNT is cheap (index index_workshop_invitations_workshop_attending exists), but the round trips accumulate across all rows.
Proposed fix
Paginate with Pagy (already used elsewhere in this controller, e.g. #rsvp):
@pagy, @workshops = pagy(@chapter.workshops.includes(:sponsors), items: 50)
Ordering is already deterministic via default_scope { order('date_and_time DESC') } and index_workshops_on_date_and_time, so offset pagination is fine at codebar's scale.
Replace per-row COUNTs with one aggregate query, keyed by workshop id and looked up in the view:
@accepted_counts = @workshops.joins(:invitations)
.where(invitations: { attending: true })
.group('invitations.workshop_id').count
Optional follow-ups (only if still slow after the above)
- Default the listing to upcoming + recent past (e.g.
where(date_and_time: 1.year.ago..)) with a link to the full list. - Fragment caching per row — probably unnecessary once pagination lands.
Acceptance criteria
- The page is paginated and renders a bounded number of rows regardless of chapter age.
- Query count drops from O(workshops) to O(1): pagination count query + one aggregate + sponsors preload.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with app/controllers/admin/workshops_controller.rb and the #rsvp pagination example, then inspect app/views/admin/workshops/index.html.haml where accepted invitation counts are rendered. Add bounded pagination and replace per-row counts with the aggregate lookup described in the issue; done means the page renders a fixed number of rows and meets the stated query-count criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100