求助:按日期分组的Games列表实现无限滚动时重构局部视图遇死循环
Let's break down how to properly refactor your view into partials while squashing that infinite loop problem. Here's a step-by-step solution:
1. First, Identify the Root Cause of the Infinite Loop
Most likely, your loop is happening for one of two reasons:
- You accidentally added a recursive
render @gamescall inside your partial (e.g., your_game.html.erbis trying to render the entire collection again). - Your infinite scroll JavaScript isn't handling loading states correctly, causing repeated requests for the same page of data.
Let's fix the view structure first.
2. Create Proper Partials
Step 2.1: Single Game Partial
Create app/views/games/_game.html.erb for individual game items (this is exactly the code you extracted earlier):
<%= game.game_external_link %> <%= image_tag game.photos[0].image.url(:thumb), class:"img-responsive" if game.photos.length > 0 %> <%= game.game_name %> <%= game.game_description %> <%= image_tag avatar_url(game.user) %>
Step 2.2: Day Group Partial
Since your original view groups games by day, create a partial to handle each day's section (app/views/games/_game_day.html.erb):
<%# Add a date header if you want to show the day %> <h3><%= day.strftime("%B %d, %Y") %></h3> <div class="game-day-container"> <%= render partial: 'game', collection: games %> </div>
3. Update Your Main View
Replace your original view code with this (e.g., app/views/games/index.html.erb):
<div class="infinite-scroll-container"> <% @game_days.each do |day, games| %> <%= render partial: 'game_day', locals: { day: day, games: games } %> <% end %> </div> <%# Add a loading spinner placeholder %> <div class="loading-spinner" style="display: none;">Loading more games...</div>
4. Fix Your Controller for Pagination
Infinite scroll relies on paginated data. Use a gem like kaminari or will_paginate to handle this (we'll use kaminari here):
# app/controllers/games_controller.rb def index # Paginate games (adjust per-page count to your needs) @paginated_games = Game.order(created_at: :desc).page(params[:page]).per(10) # Group the paginated games by day @game_days = @paginated_games.group_by { |game| game.created_at.to_date } respond_to do |format| format.html format.js # For AJAX infinite scroll requests end end
5. Add AJAX Handling for Infinite Scroll
Create app/views/games/index.js.erb to append new content when the user scrolls:
<% if @paginated_games.any? %> <% @game_days.each do |day, games| %> <%= j render partial: 'game_day', locals: { day: day, games: games } %> <% end %> <% else %> <%# Disable scrolling when no more content exists %> $('.infinite-scroll-container').off('scroll'); $('.loading-spinner').text('No more games to load!'); <% end %> $('.loading-spinner').hide();
Then add the JavaScript to handle scroll events (put this in app/assets/javascripts/games.js):
$(document).on('turbolinks:load', function() { const scrollContainer = $('.infinite-scroll-container'); let currentPage = 2; let isLoading = false; scrollContainer.scroll(function() { // Exit if we're already loading or there's no more content if (isLoading) return; // Check if user has scrolled near the bottom const isNearBottom = (scrollContainer.scrollTop() + scrollContainer.innerHeight()) >= (scrollContainer[0].scrollHeight - 100); if (isNearBottom) { isLoading = true; $('.loading-spinner').show(); // Fetch the next page via AJAX $.getScript(`/games?page=${currentPage}`) .done(function() { currentPage++; isLoading = false; }) .fail(function() { isLoading = false; $('.loading-spinner').text('Failed to load games.'); }); } }); });
6. Double-Check for Recursive Render Calls
Make sure your _game.html.erb partial does not contain any render @games or similar calls—this is the most common cause of infinite loops when refactoring partials.
内容的提问来源于stack exchange,提问作者Henri

