Rails does partial twice
Rails prints my articles partially in half. Currently I am just browsing the article collection and outputting them. At first I thought it was an AJAX issue, but I removed all javascript in the application.js and index.js.erb files and it still repeats twice. I also checked the database by logging into Rails c and starting Articles.all.count
and returning the correct number of articles. I also reset the db and tried it again with the same result.
Article # index
<h1 class="text-center">talks</h1>
<div id="articles-list" class="small-12 small-centered columns">
<%= render @articles %>
</div>
<%= will_paginate @articles %>
_article.html.erb partial:
<% @articles.each_with_index do |article, index| %>
<%= index %>
<dl class="individual-article">
<dt><%= article.title %>
<% if current_user.try(:admin) %>
| <%= link_to 'Edit', edit_article_path(article) %>
<% end %><br>
<%= raw article.tags.map(&:name).map { |t| link_to t, tag_path(t), class: get_class(t) }.join(', ') %>
</dt>
<dd><%= truncate(article.body.html_safe, length: 200) %>
<%= link_to 'more', article_path(article) %>
</dd>
</dl>
I put the index in the header if it is repeated and it does. If I have three articles, it will output 0 1 2 0 1 2 for detection. So I know that it runs twice.
article controller
def index
if params[:tag]
@articles = Article.tagged_with(params[:tag]).order('created_at DESC').paginate(page: params[:page], per_page: 3)
else
@articles = Article.order('created_at DESC').paginate(page: params[:page], per_page: 3)
end
end
I have AJAX for infinite scrolling which could be a problem. Except when I delete the entire js file, it has the same behavior.
index.js.erb
$('#articles-list').append('<%= escape_javascript render(@articles) %>');
$('.pagination').replaceWith('<%= escape_javascript will_paginate(@articles) %>');
Application.js
$(document).ready(function() {
if ($('.pagination').length) {
$(window).scroll(function() {
var url = $('.pagination .next_page').attr('href');
if (url && $(window).scrollTop() > $(document).height() - $(window).height() - 50) {
$('.pagination').text("Please Wait...");
return $.getScript(url);
}
});
return $(window).scroll();
}
});
I am relatively new to Rails and would appreciate advice on how to prevent this from happening twice.
Edit
Partial server logs:
...
Article Load (0.2ms) SELECT "articles".* FROM "articles" ORDER BY created_at DESC LIMIT 3 OFFSET 0
...
Rendered articles/_article.html.erb (6.5ms)
Rendered articles/index.html.erb within layouts/application (12.8ms)
Rendered layouts/_header.html.erb (0.4ms)
source to share
You are passing the collection in partial. This will make partial one time for each element in @articles. In a partial case, you are looping over @articles again. Take the loop outside of the partial, or remove it if you don't need the index. They will work:
Article # index
<div id="articles-list" class="small-12 small-centered columns">
<% @articles.each_with_index do |article, index| %>
<%= render 'article', article: article, index: index %>
<%end%>
</div>
_article.html.erb partial:
<%= index %>
<dl class="individual-article">
<dt><%= article.title %>
<% if current_user.try(:admin) %>
| <%= link_to 'Edit', edit_article_path(article) %>
<% end %><br>
<%= raw article.tags.map(&:name).map { |t| link_to t, tag_path(t), class: get_class(t) }.join(', ') %>
</dt>
<dd><%= truncate(article.body.html_safe, length: 200) %>
<%= link_to 'more', article_path(article) %>
</dd>
</dl>
or if you don't need the index in the partial, save the index.html as it is now and just remove the loop from the partial:
_article.html.erb partial:
<dl class="individual-article">
<dt><%= article.title %>
<% if current_user.try(:admin) %>
| <%= link_to 'Edit', edit_article_path(article) %>
<% end %><br>
<%= raw article.tags.map(&:name).map { |t| link_to t, tag_path(t), class: get_class(t) }.join(', ') %>
</dt>
<dd><%= truncate(article.body.html_safe, length: 200) %>
<%= link_to 'more', article_path(article) %>
</dd>
source to share