Loading more comments using AJAX in Rails
I am currently implementing a blog-like site using Ruby on Rails. Each "Post" has some comments. Currently I only have the latest 5 comments load, but I want to implement a hyperlink that would load the rest of the comments. Unfortunately with my current implementation, all I get is a bunch of junk spit out.
Before
Comments
Posted 7 minutes ago
New
Posted 1 day ago
Comment 3
Posted 1 day ago
Comment 2
Posted 1 day ago
Comment 1
Posted 1 day ago
This is a new comment
View more comments
After Click 'View more comments'
Comments
try { Element.insert("comments", { bottom: "
\n
\n Posted 1 day ago\n
\n Comment 2\n
\n
" }); Element.insert("comments", { bottom: "
\n
\n Posted 1 day ago\n
\n Comment 3\n
\n
" }); Element.insert("comme开发者_运维知识库nts", { bottom: "
\n
\n Posted less than a minute ago\n
\n New\n
\n
" }); Element.hide("morecomments"); } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('Element.insert(\"comments\", { bottom: \"
\\n
\\n Posted 1 day ago\\n
\\n Comment 2\\n
\\n
\" });\nElement.insert(\"comments\", { bottom: \"
\\n
\\n Posted 1 day ago\\n
\\n Comment 3\\n
\\n
\" });\nElement.insert(\"comments\", { bottom: \"
\\n
\\n Posted less than a minute ago\\n
\\n New\\n
\\n
\" });\nElement.hide(\"morecomments\");'); throw e }
The post's show.html.erb has:
<div id="morecomments">
<%= link_to_remote "View more comments", :url=>{:action=>'morecomments',:post_id=>@post.id},:update=>'comments' %>
</div>
In my post controller I have
def morecomments
@post = Post.find(params[:post_id])
@comments = @post.comments.values_at(Range.new(5, @post.comments.size-1))
respond_to do |format|
format.html {redirect_to @post.comments}
format.js
end
end
And finally my morecomments.js.rjs:
@comments.each do |p|
page.insert_html :bottom, :comments, :partial => p
end
page.hide 'morecomments'
I'm really new to Rails, and I don't really know about all of the meta magic rails is doing in the background. Any help would be awesome.
Thank you!
Your problem is that you're mixing concepts. You get your choice of using link_to_remote
with the :update option, or using RJS. Not both.
When you use link_to_remote
with the :update option your view expects to receive a chunk of html which will replace the inner html of the DOM element matching the id provided to :update. In your case, this is the comments div.
Your format .js section is rendering the rjs template because you haven't told it to do anything else and it's generating javascript, which the link_to_remote treats as html uses it to replace the comments div.
You have two solutions:
Use
link_to_remote
with:update
Your view doesn't change, and your rjs file goes unused. To implement this fix replace the foramt.js line in your controller with this:
format.js { render :partial => 'comments', :collection => @comments}
Use RJS
In this solution, your controller doesn't change. all you have to do is remove the
, :update =>'comments'
from yourlink_to_remote
call.
The problem is that your morecomments action is simply returning javascript and injecting it into the bottom of the page.
When you call an action that responds to a .js extension, you get back javascript. That's useful if you need to create dynamic javascript, but you really don't. Have that action return a json file, and use some javascript on the front-end that interprets it and injects it. Or, you could stick what it's already returning into script tags and it (should) work.
精彩评论