Infinite scroll rails ajax request firing, but not

2019-09-05 08:51发布

I have a rails app that I am using will_paginate for. I am then using will_paginate as a basis for infinite scroll. After a lot of trial and error, the request seems to be working, but instead of rendering the next page of content in the app, the request is re-rendering all of my content and displaying it in paginated form again. I have a thought that it is to do with my .each iterator in my partial, but I am not sure exactly.

Below is my partial, controller, js.erb, coffescript, and logs. If anyone can help with a reason why this is not working properly, I would greatly appreciate it!

Logs: you can see that it is getting the next page, and it does that for all 5 pages on each request:

Started GET "/links?page=2&_=1451404304001" for ::1 at 2015-12-29 10:51:46 -0500
Processing by LinksController#index as JS
  Parameters: {"page"=>"2", "_"=>"1451404304001"}
  Link Load (0.2ms)  SELECT  "links".* FROM "links" LIMIT 5 OFFSET 5
   (0.1ms)  SELECT COUNT(*) FROM "links"
  Link Load (0.2ms)  SELECT  "links".* FROM "links"  ORDER BY "links"."cached_votes_score" DESC LIMIT 5 OFFSET 5
  CACHE (0.0ms)  SELECT COUNT(*) FROM "links"

_link.html.erb:

    <!-- order links based on total number of votes -->

  <div class="link row clearfix">
    <h2>

    </h2>
    <h2>
      <%= link_to link.title, link %><br>
    </h2>
    <p>
      <%= link_to link.url, link %><br>
    </p>

<!-- acts_as_votable for like_link -->
    <div class="btn-group">
        <%= link_to like_link_path(link), method: :put, class: "btn btn-default btn-sm" do %>
          <span class="glyphicon glyphicon-chevron-up"></span>
          Upvote
          <%= link.get_upvotes.size %>
        <% end %>
        <%= link_to dislike_link_path(link), method: :put, class: "btn btn-default btn-sm" do %>
          <span class="glyphicon glyphicon-chevron-down">
          Downvote
          <%= link.get_downvotes.size %>
        <% end %>
    </div>
  </div>

index.js.erb:

$('#links').append('<%= j render(@links) %>');
<% if @links.next_page %>
  $('.pagination').replaceWith('<%= j will_paginate @links.next_page %>');
<% else %>
  $('.pagination').remove();
<% end %>

link.js.coffee:

jQuery ->
        $(window).scroll ->
            if $(window).scrollTop() > $(document).height() - $(window).height() - 50
                    $.getScript($('.pagination a.next_page').attr('href'))

links_controller.rb index action:

class LinksController < ApplicationController
  before_filter :authenticate_user!, except: [:index, :show]

  def index
    @links = Link.order(cached_votes_score: :desc).paginate(page: params[:page], per_page: 5)

    respond_to do |format| 
      format.js
      format.html
    end
  end
end

index.html.erb:

<div class = "sort_paginate_ajax"><%= render @links %></div>

<div id="quotes_links">
  <%= will_paginate @links %>
</div>

When I changed my index.js.erb to the change recommended in the first comment by Miles, I now get the following undefined method error:

ActionView::Template::Error (undefined method `total_pages' for 3:Fixnum):
    1: $('#links').append('<%= j render(@links) %>');
    2: <% if @links.next_page %>
    3:   $('.pagination').replaceWith('<%= j will_paginate @links.next_page %>');
    4: <% else %>
    5:   $('.pagination').remove();
    6: <% end %>

1条回答
爷的心禁止访问
2楼-- · 2019-09-05 09:02
<% @links.order(cached_votes_score: :desc).each do |link| %>

You don't need to do this, because you're rendering a collection of ActiveRecord models:

$('#links').append('<%= j render(@links) %>');

Rails will iterate over links and render app/links/_link.html.erb partial for each link. So this partial should contain only HTML displaying one distinct link. You can use link variable inside it.

Also try to not use order in views, but do so in a controller action. When you pass an instance variable to a view it should be ready to be used, without additional queries. It's better to keep all queries and logic inside controllers and models and don't mix them into views.

查看更多
登录 后发表回答