问题
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:
<% @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.
来源:https://stackoverflow.com/questions/34514908/infinite-scroll-rails-ajax-request-firing-but-not-displaying-next-paginated-pag