Having difficulty with threaded comments, using acts_as_tree

I've been having problems making threaded comments for the last few days. Mainly with creating children and displaying the children. Currently, I have comments shown at the bottom of my articles show view. The top level comments work, but I do not really know how to implement a way for users to "reply" to the top level comments and take them to a form (the comment 'new' view) to create a new comment. I want the controller to determine if the user is creating the new comment in an article or in a comment and create the new comment as a child if its parent is a comment. I've been facing multiple problems, maybe the recursion messes up and I get an infinite loop.

Here is the articles show controller:   def show     @article = Article.find(params[:id])     @commentable = Article.find(params[:id])     @comments = @commentable.comments # @comments = @commentable.comments.paginate(:page => params[:page])     @comment = Comment.new     @title = @article.title   end

Here is my comments controller:   def show     @commentable = find_commentable     @comment = @commentable.comments.find(params[:id]) # @comments = @commentable.comments.paginate(:page => params[:page])   end

  def new     @commentable = find_commentable     @comment = Comment.new   end

  def create     @commentable = find_commentable     if @comment.commentable_type == "Comment"       @comment = @commentable.children.create(param[:comment])     else       @comment = @commentable.comments.build(params[:comment])     end     @comment.user_id = current_user.id     if @comment.save       flash[:success] = "Comment saved."       redirect_to @commentable     else       flash[:error] = "Error in creating comment." # @comments = @commentable.comments.paginate(:page => params[:page])       render 'new'     end   end

Here is the comment creation form: <%= form_for([@commentable, @comment]) do |f| %>   <%#= render 'shared/error_messages', :object => f.object %>   <div class="field">     <%= f.label :title %><br />     <%= f.text_field :title %>   </div>   <div class="field">     <%= f.label :content %><br />     <%= f.text_area :content %>   </div>   <div class="actions">     <%= f.submit "Post Comment" %>   </div> <% end %>

Here is the loop that goes through all of the existing comments: <% unless @comments.nil? || @comments.empty? %>     <%= render :partial => 'comments/comment', :collection => @comments %>     <%#= will_paginate @comments %> <% end %>

Here is what each individual comment looks like: <div id="comment <%= comment.id %>">   <%= comment.title %>   > <%= link_to "Permalink", polymorphic_path([@commentable, comment]), :action => :show %>   > <%= link_to "Reply", polymorphic_path([@commentable, @comment]), :action => :new %>   > <%= link_to "Edit Comment", polymorphic_path([@commentable, comment]), :action => :edit %>   > <%= link_to 'Delete Comment', [[@commentable, comment]], :confirm => "Are you sure?", :method => :delete %><br />   <%= comment.content %><br />   <%= comment.user.name %><br /><br />   <%= render :partial => 'comments/comment', :collection => @comment.children %> </div>

When I click reply, I get taken to: http://localhost:3000/articles/299/comments and not http://localhost:3000/articles/299/comments/new. I went into rails console and gave one of my comments a comment child, and the recursive nature of the threaded comments gave me recursion that crashed my site.

your are doing a polimorphic assotiacion on the same model and another model , thats not needed, you only need a self referential association and a has many, your main problem is that you are using a polymorphic associations where there was no need to.

you comment table should have

t.integer :article_id t.integer :parent_id

drop the polymorphic association if the comments will only belong to articles and install the acts_as_three gem, then you’ll be done with it.

if you want to apply comment to something else besides articles then use the polymorphic association bad that is not need for the comments they just need to refer to themself.

you site crashed because the comment on the page article are found by pulling the article_id from the params but you want to add childrens to a comment and there is no way to pull that id with the find_commentable function

radhames brito wrote:

you site crashed because the comment on the page article are found by pulling the article_id from the params but you want to add childrens to a comment and there is no way to pull that id with the find_commentable function

I am having trouble following you. I have to use the polymorphic association because my comments will be found on the Article, Profile, and Picture models.

try to fix the thing i suggested in red and add a parent_id field to the comments table, then make a self referencial associaction or use the acts_as_tree gem, the thing is along with the polimorphic fields a comment should be able to belong to another comment, when you try to make a comment belong to another comment with the same association you are using for when it belongs to article or anything else the migration to that polymorphic parent is lost, why ? because you are using this function

def find_commentable
  params.each do |name, value|
if name =~ /(.+)_id$/
      return $1    .classify.constantize.find(value)
end
  end
  nil
end

with it you are trying to find what comments owns the new comment that was added as a chils. but this

~ /(.+)_id$/

pulls from the params hash, the params hash passes the model that has comments nested not the comment want to attach your new comment to.

also you are calling new on something that will call new again, that is when you check with new to build the child

is tries to see who the parent is but you mistankenly pass the same object.

if need more details on how to fix all this, i can try to help, but as you notice my english is far from perfect.

here is how the acts_as_tree gem works

http://railscasts.com/episodes/162-tree-based-navigation

radhames brito wrote:

try to fix the thing i suggested in red and add a parent_id field to the comments table, then make a self referencial associaction or use the acts_as_tree gem,

[...]

Or rather, don't. acts_as_tree uses an adjacency list model, which is simple, but ridiculously inefficient to query. What you generally want instead is awesome_nested_set, which makes it possible to retrieve all comment threads, to arbitrary depth, with one single query.

acts_as_tree is almost never the right choice.

Best,

yes but he is new to rails and there is a railscast for acts_as_tree, thats why i was suggesting it.

Please quote when replying. It's hard to follow the discussion otherwise.

radhames brito wrote:

yes but he is new to rails and there is a railscast for acts_as_tree, thats why i was suggesting it.

So there's a Railscast. Big whoop. :slight_smile: acts_as_tree is easy to use for some things, but so what? Its data model -- and therefore its performance -- is poor, and it can actually be harder to use than awesome_nested_set in certain cases. Just don't even consider it for serious work.

On Wed, Sep 15, 2010 at 2:03 PM, Marnen Laibow-Koser

Best,

:cry: , but, but …

Are my routes correct in using this:   resources :articles, :has_many => :comments

yes do that for articles and every model that as a comment attached