Skip to content

Paginate plans index with Turbo Frame infinite scroll#96

Merged
HamptonMakes merged 2 commits intomainfrom
plans-index-pagination
Apr 23, 2026
Merged

Paginate plans index with Turbo Frame infinite scroll#96
HamptonMakes merged 2 commits intomainfrom
plans-index-pagination

Conversation

@HamptonMakes
Copy link
Copy Markdown
Collaborator

Problem

The plans index loads all plans in a single request with no pagination. With ~6,500+ users and growing plan counts, this causes:

  • 537ms page loads (338ms view rendering alone)
  • N+1 queries on created_by_user (missing from includes)
  • Subquery for unread counts re-executing the full plans query

Changes

  • Fix N+1: Add :created_by_user to includes()
  • Fix unread counts: Use .map(&:id) on loaded records instead of .select(:id) subquery
  • Infinite scroll: Paginate at 20 plans per page using Turbo Frames with loading: :lazy
    • Extracts plan items into _plan_page partial
    • Each page renders a lazy Turbo Frame pointing to the next page
    • Turbo Frame requests skip filter UI queries (@plan_types, onboarding banner)
    • Uses the same Turbo Frame pattern as the existing inbox panel and history views

Testing

  • All 24 existing plans request specs pass
  • Tested locally with 200+ plans — pages load progressively on scroll

- Add :created_by_user to includes to fix N+1 queries on the plans index
- Switch unread counts query from subquery to .map(&:id) on loaded records
- Paginate plans at 20 per page using LIMIT/OFFSET
- Implement infinite scroll via Turbo Frames with loading: :lazy
- Extract plan list items into _plan_page partial
- Skip filter UI queries (plan_types, onboarding) for Turbo Frame requests

Amp-Thread-ID: https://ampcode.com/threads/T-019db090-8247-7319-b0b6-e4cc4ef4b28c
Co-authored-by: Amp <amp@ampcode.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 950b3df52d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


@plan_types = PlanType.order(:name)
@page = (params[:page] || 1).to_i
@plans = plans.limit(PER_PAGE + 1).offset((@page - 1) * PER_PAGE)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stabilize sort key before offset pagination

Using offset pagination here without a deterministic tie-breaker means pages can skip or duplicate plans when multiple records share the same updated_at value. The query still orders only by updated_at, so frame page=2 can return overlapping or missing rows relative to page=1 for ties, which breaks infinite scroll correctness; add a secondary unique order (for example id) before applying offset.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — added id: :desc as a secondary sort key in 283dc0d to make the offset pagination deterministic.

@HamptonMakes HamptonMakes merged commit ee7321a into main Apr 23, 2026
5 checks passed
@HamptonMakes HamptonMakes deleted the plans-index-pagination branch April 23, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant