How to paginate a nested hash tree (comments) with closure tree and will paginate

200 Views Asked by At

I cannot seem to sway my way out of getting a The @posts variable appears to be empty. Did you forget to pass the collection object for will_paginate? error. I am not sure if there is something I am forgetting to pass to the will_paginate view helper but I have gone through the documentation trying to figure it out. Is there an apparent will paginate and closure tree compatibility issue or where should the @posts be passed.

posts_controller.rb

...
def show
  @comments = @post.comments.includes(:user)
    .paginate(page: params[:page], per_page: 8).hash_tree(limit_depth: 2)

  @bookmark_exists = Bookmark.where(view: @post, user: current_user).blank? ? false : true 
  respond_to do |format|
    format.html
    format.js
  end
end
...

show.html.erb

...
<div class="comments-modal">
  <div class="comments-modal-content">
    <div class="comments-modal-header">
      <h1 class="header-name">Comments</h1>
      <span class="comments-close-button">close</span>
    </div>
    <div class="view-comments" id="comments_<%= @post.id %>">
      <% if @comments.any? %>
        <div id="comments-index">
          <%= comments_tree_for(@comments) %>
        </div>
      <% end %>
      <div id="with-button">
        <%= will_paginate @comments %>  <!-- ArgumentError in Posts#show -->
      </div>
      <% if @comments.next_page %>
        <div id="load-more-comments">More comments</div>
      <% end %>
    </div>
    <div class="comments-user-input">
      <div class="comments-user-input-container">
        <div class="comments-user-container">
          <%= gravatar_for(current_user, size: 45) %>
        </div>
        <div class="comments-form">
          <%= form_for([@post, @post.comments.build], remote: true) do |f| %>
            <%= f.hidden_field :parent_id %>
            <%= f.text_area :content, placeholder: 'Add a comment...', class: "comment_content", 
              id: "comment_content_#{@post.id}", data: {post_id: "#{@post.id}", value: "#{@post.comments.count}"} %>
          <% end %>
        </div>
      </div>
    </div>
  </div>
 ...

comments_helper.rb

module CommentsHelper
  def comments_tree_for(comments)
    comments.map do |comment, nested_comments|
      render(comment) +
          (nested_comments.size > 0 ? content_tag(:div, comments_tree_for(nested_comments), class: "nested-comment") : nil)
    end.join.html_safe
  end  
end
1

There are 1 best solutions below

0
Thato Sello On

I ended up resorting to turning the hash to an array through the addition of require 'will_paginate/array' to my application.rb file.

post.rb

...
def comments_tree_array
  comments.hash_tree(limit_depth: 2).to_a
end
...

posts_controller.rb

...
def show
  @comments = @post.comments_tree_array.paginate(page: params[:page], per_page: 8)

  @bookmark_exists = Bookmark.where(view: @post, user: current_user).blank? ? false : true 
  respond_to do |format|
    format.html
    format.js
  end
end
...

show.js.erb

...
$('#comments-index').append('<%= j comments_tree_for @comments %>');
...

That is about it. Thanks