I'm trying to build in comments into my Rails 4 app. I have been able to get nested comments to work using Railcasts 262 as a guide. I would like to make the new comment field appear when a user wants to reply to a comment or add a new one and limit the times the page reloads. I have viewed Railscasts 136 and others. I'm using the ancestry gem and can't get the form and comments to show as desired.
The problem seems to be that when I send the user to the new_comment_path, the post_id gets lost. I had been able to get it to save with the comment before adding the ajax and new step in the routes. Before I was just rendering the comment form on the post show page and it worked. Now the new comment is getting saved, but the post_id, ancestry_id and parent_id are all nil. I can therefore not render those comments to show up on the show page for the posts. After I get the new_comment to work I will also set it up so that the "reply" also works. Please let me know if you have any suggestions. Thanks.
post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
has_ancestry
end
_comment_form.html.erb
<%= form_for @comment, remote: true do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="comment_field">
<%= f.hidden_field :post_id, :value => @comment.post_id %>
<%= f.hidden_field :parent_id, :value => params[:parent_id] %>
<%= f.text_area :content, placeholder: "" %>
</div>
<button class="btn" type="submit">
Send request
</button>
<% end %>
post show.html.erb
... information about post ...
<div id="added_comments">
<%= link_to "New Comment", new_comment_path, id: "new_link", remote: true, :post => @post %>
</div>
<%= nested_comments @post.comments.arrange(:order => :created_at) %>
comment new.html.erb
<h1>New Comment</h1>
<%= render 'comment/form' %>
comment new.js.erb
$('#new_link').hide().after('<%= j render("form") %>');
create.js.erb
$('#new_comment').remove();
$('#new_link').show();
$('#added_comments').append('<%= j nested_comments (@post.comments).arrange(:order => :created_at) %>');
_comment.html.erb
<%= link_to comment.user.name, comment.user %>
<%= comment.content %>
<%= link_to "Reply", post_path(@post, :parent_id => comment) %>
comments_controller.rb
def new
@comment = Comment.new(:parent_id => params[:parent_id], :post_id => params[:post_id])
end
def create
@comment = Comment.create(comment_params)
@comment.user = current_user
if @comment.save
CommentMailer.comment_confirmation(@comment).deliver
flash[:success] = "Comment added."
respond_to do |format|
format.html { redirect_to :back }
format.js
end
else
flash[:error] = "Comment cannot be blank"
end
end
def show
@comment = Comment.find(params[:id])
@user = @comment.user
end
posts_controller.rb
def show
@post = Post.find(params[:id])
@comment = @post.comments.build(:parent_id => params[:parent_id])
@user = User.find(@post.user_id)
@comment.user_id = current_user
end
def create
@post = current_user.posts.build(post_params)
if @post.save
flash[:success] = "Post added!"
redirect_to root_url
else
@repository_items = [ ]
render 'shared/_post_form'
end
end
Your posts show template is a bit wrong. When you pass an arbitrary symbol to link_to it becomes an html attribute on the link tag so when you use
In your html that becomes something like
which won't work for you because you want to pass the parent_id and post_id as params to the new comment action. Instead you could try something like this
Then when you go to implement your comment reply you'd have something like
Also, you might have just omitted files, but from what I see the comment new.js.erb template needs to reference comment_form instead of form since that's what you named your template