There are several pieces to work on here, but the good news is I think the answer you're looking for is simpler than what you already have. If I understand you correctly, you want comments to have many child comments of their own. This is how YouTube works, letting members reply to existing comments. For this, you don't need the has_many :through
solution you've implemented. You don't need the conversations object at all. A comment may have many replies (child comments), but a reply isn't going to have more than one parent.
The answer for this is using polymorphism, which is easier to implement than it is to pronounce :) You want your comments to either belong to a post, or to another comment. Polymorphism lets an object belong to one of possibly many things. In fact, comments are the most common use for this.
I cover polymorphism with the example of addresses in this blog post:
http://kconrails.com/2010/10/19/common-addresses-using-polymorphism-and-nested-attributes-in-rails/
But I can show you how it applies to your case more specifically. First, drop the conversation model/controller/routes entirely. Then, change your comments table:
change_table :comments do |t|
t.integer :commentable_id
t.string :commentable_type
t.remove :post_id
end
We don't need post_id
anymore, because we're going to change how we associate with other tables. Now let's change the models:
# app/models/post.rb
has_many :comments, :as => :commentable
# app/models/comment.rb
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
Notice we dropped the comment belonging to a post directly. Instead it connects to the polymorphic "commentable" association. Now you have an unlimited depth to comments having comments.
Now in your Post#show action, you'll want to create a blank comment like so:
get show
@post = Post.find(params[:id])
@comment = @post.comments.build
end
@comment
will now have commentable_id
and commentable_type
set for you, automatically. Now in your show page, using erb:
<% form_for @comment do |f| %>
<%= f.hidden_field :commentable_type %>
<%= f.hidden_field :commentable_id %>
/* other fields go here */
<% end %>
Now when Comments#create is called, it works like you'd expect, and attaches to the right parent. The example above was showing a comment being added directly to a post, but the process is essentially the same for a comment. In the controller you'd call @comment.comments.build
, and the form itself would stay the same.
I hope this helps!