Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Dario Hunt
2,245 PointsRails ajax append single item from collection
In my app I have a commenting system in place that displays comments as a collection and I've got ajax commenting working but currently it renders the entire collection again but what I want is to just append the latest comment. Here's my code:
comments_controller.rb
class CommentsController < ApplicationController
before_filter :authenticate_member!
before_filter :load_commentable
before_filter :find_member
def index
redirect_to root_path
end
def new
@comment = @commentable.comments.new
end
def create
@comment = @commentable.comments.new(params[:comment])
@comment.member = current_member
respond_to do |format|
if @comment.save
format.html { redirect_to :back }
format.json
format.js
else
format.html { redirect_to :back }
format.json
format.js
end
end
end
def destroy
@comment = Comment.find(params[:id])
respond_to do |format|
if @comment.member == current_member || @commentable.member == current_member
@comment.destroy
format.html { redirect_to :back }
else
format.html { redirect_to :back, alert: 'You can\'t delete this comment.' }
end
end
end
private
def load_commentable
klass = [Status, Medium, Project, Event, Listing].detect { |c| params["#{c.name.underscore}_id"] }
@commentable = klass.find(params["#{klass.name.underscore}_id"])
end
def find_member
@member = Member.find_by_user_name(params[:user_name])
end
end
statuses_controller
def show
@status = Status.find(params[:id])
@commentable = @status
@comments = @commentable.comments.order('created_at desc').page(params[:page]).per_page(15)
@comment = Comment.new
respond_to do |format|
format.html # show.html.erb
format.json { redirect_to profile_path(current_member) }
format.js
end
end
statuses/show.html.erb
<% if member_signed_in? %>
<div id="comm_form_wrap">
<%= render "shared/comment_form" %>
</div>
<div id="comments_<%= @commentable.id %>">
<%= render partial: "shared/comments", :collection => @comments, :as => :comment %>
</div>
<% end %>
shared/_comments.html.erb
<div id="comment_<%= comment.commentable.id %>_<%= comment.id %>" class="comments">
<span class="comment_av">
<%= comment_avatar_link_2 comment.member, :class => "com_av", title: comment.member.full_name, alt: comment.member.full_name %>
</span>
<span>
<div class="comment_name">
<% if comment.member == @commentable.member %>
<%= link_to comment.member.user_name, profile_path(comment.member) %> <span class="owner">Creator</span>
<% else %>
<%= link_to comment.member.user_name, profile_path(comment.member) %>
<% end %>
<% if comment.member == current_member || @commentable.member == current_member %>
<span class="comment_del">
<%= link_to image_tag("Delete.png", title: 'Delete'), [@commentable, comment], remote: true, method: :delete, data: { confirm: 'Are you sure?' } %>
</span>
<% end %>
<span class="meta">
<%= time_ago_in_words(comment.created_at) %>
</span>
</div>
<div class="com_con">
<%= Rinku.auto_link(comment.content).html_safe %>
</div>
</span>
</div>
comments/create.js.erb
$("#comments_<%= @commentable.id %>").html("<%= escape_javascript(render :partial => 'shared/comments', :collection => @comments, :as => :comment) %>");
$('#comment_form')[0].reset();
If I just change html
to append
in the create.js.erb
file it will append the entire collection of comments. I guess I could copy and paste the code from my comments partial but that'd be a lot of code and I wouldn't know how to define the variables that way. What's the best way for me to append the single new comment? Thanks in advance.
2 Answers

sitkibagdat
27,311 PointsYou just need to render one but you say render a collection. Instead render @comment, not @comments.
comments/create.js.erb
$("#comments_<%= @commentable.id %>").append("<%= escape_javascript(render partial: 'shared/comments', object: @comment) %>");

Dario Hunt
2,245 PointsI was able to figure this one out. Instead of rendering or appending the collection I could just append @comment
like so:
$("#comments_<%= @commentable.id %>").append("<%= escape_javascript(render :partial => @comment, :locals => {:comment => @comment}) %>");
Then I just needed to create a _comment.html.erb
partial in my comments folder.
Dario Hunt
2,245 PointsDario Hunt
2,245 PointsThanks