You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用will_paginate gem实现无限滚动?求助排查实现失败问题

Fixing Infinite Scroll with will_paginate: Step-by-Step Guide

Hey there! Let’s get your infinite scroll working with will_paginate. I’ve debugged this exact issue dozens of times, so let’s break down the fixes focusing on your posts_controller.rb and _allposts.html.erb files.

1. First, Double-Check Your Controller Setup

The most common mistake here is not handling AJAX requests properly or misconfiguring pagination. Here’s what your controller action (probably index) should look like:

# app/controllers/posts_controller.rb
def index
  # Order posts (optional but recommended) and paginate with a per-page limit
  @posts = Post.order(created_at: :desc).paginate(page: params[:page], per_page: 8)
  
  # Critical: Respond to both HTML and AJAX (JS) requests
  respond_to do |format|
    format.html # Renders the default index.html.erb
    format.js   # Will render index.js.erb for AJAX calls
  end
end

If you skip the respond_to block, your AJAX requests will return full HTML pages instead of the partial content you need for infinite scroll—this is a super common failure point!

2. Update Your _allposts.html.erb Partial

Your partial needs to wrap posts in a targetable container and include a way to trigger the next page (either a "Load More" button or just a hidden marker for auto-scroll). Here’s a solid structure:

<!-- app/views/posts/_allposts.html.erb -->
<div id="posts-container">
  <% @posts.each do |post| %>
    <div class="post-item">
      <!-- Your existing post content here -->
      <h3><%= post.title %></h3>
      <p><%= post.body.truncate(150) %></p>
    </div>
  <% end %>
</div>

<!-- Handle pagination state -->
<% if @posts.next_page %>
  <div id="pagination-trigger">
    <%= link_to 'Load More', posts_path(page: @posts.next_page), remote: true, id: "load-more-link" %>
  </div>
<% else %>
  <p class="no-more-posts">That's all the posts we've got!</p>
<% end %>

Key notes here:

  • The #posts-container gives us a clear place to append new posts via JS.
  • The remote: true flag on the link tells Rails to send an AJAX request instead of a full page reload.
  • We use @posts.next_page to get the correct next page number (no manual incrementing—this avoids off-by-one errors).

3. Add the JS to Handle Infinite Scroll

You’ll need a JavaScript view to process the AJAX response. Create index.js.erb in your app/views/posts folder:

// app/views/posts/index.js.erb
// Append the new posts to the container
$('#posts-container').append('<%= j render partial: "allposts", locals: { posts: @posts } %>');

// Update the "Load More" link or remove it if there are no more pages
<% if @posts.next_page %>
  $('#load-more-link').attr('href', '<%= posts_path(page: @posts.next_page) %>');
<% else %>
  $('#pagination-trigger').replaceWith('<p class="no-more-posts">No more posts to load!</p>');
<% end %>

The j (alias for escape_javascript) ensures your HTML is properly escaped for JS, preventing syntax errors—don’t skip this!

Want Auto-Scroll Instead of a Button?

If you don’t want a "Load More" button and want to load posts when the user scrolls to the bottom, add this JS to your application.js or a dedicated posts.js file:

$(window).on('scroll', function() {
  // Check if we're near the bottom of the page
  if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
    const loadLink = $('#load-more-link');
    // Only request if there's a valid link and we're not already loading
    if (loadLink.length && !loadLink.hasClass('loading')) {
      loadLink.addClass('loading');
      $.get(loadLink.attr('href'), function(data) {
        // Append new posts
        $('#posts-container').append($(data).find('#posts-container').html());
        // Update the link or remove it
        const newLink = $(data).find('#load-more-link');
        if (newLink.length) {
          loadLink.attr('href', newLink.attr('href')).removeClass('loading');
        } else {
          $('#pagination-trigger').replaceWith('<p class="no-more-posts">No more posts!</p>');
        }
      });
    }
  }
});

Common Reasons Your Infinite Scroll Failed

Let’s cover the top pitfalls that trip people up:

  • Missing respond_to :js: Without this, Rails returns HTML instead of JS, breaking the partial append.
  • Incorrect selectors: If your JS targets a container that doesn’t exist (e.g., misspelled #posts-container), nothing will happen.
  • Manual page increment: Using params[:page] + 1 instead of @posts.next_page can lead to invalid page numbers (e.g., trying to load page 5 when there are only 4 pages).
  • No escape_javascript: Forgetting j before render causes syntax errors in the JS response.
  • Not handling last page: If you don’t remove the load link when there are no more pages, your app will keep making invalid requests.

内容的提问来源于stack exchange,提问作者keith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:04:36