Ruby on Rails:集合Partial中评论遍历执行两次的问题
为什么添加评论表单后,Micropost的评论循环会渲染出一个空Comment对象?
问题回顾
你在渲染Feed的Partial时使用了<%= render @feed_items %>,每个Micropost对应的Partial里包含评论表单与该Micropost的评论列表。但表单存在时,评论循环会执行两次,还多出一个空的Comment对象,可数据库里实际只有一条对应评论。
问题根源
问题出在你表单中的这行代码:
<%= form_for([micropost, micropost.comments.build], remote: true, :html => {:class => 'comment_form'}) do |f| %>
这里的micropost.comments.build方法会做两件事:
- 在内存中创建一个新的、未保存到数据库的Comment实例(所有属性都是默认值,比如
id: nil、content: nil) - 自动将这个新实例添加到
micropost.comments的关联集合中
当你后续执行micropost.comments.each循环时,这个内存里的空对象会和数据库中已有的评论一起被遍历,所以才会出现两次循环,并且渲染出那个空的Comment。
解决方案
这里有两种简单的修复方式,任选其一即可:
方案1:创建不关联到集合的空Comment实例
把micropost.comments.build换成直接创建Comment对象,手动指定micropost_id,这样新对象不会被加入到micropost.comments集合中:
<%= form_for([micropost, Comment.new(micropost_id: micropost.id)], remote: true, :html => {:class => 'comment_form'}) do |f| %>
方案2:遍历仅包含已保存的评论
如果你更倾向于保留build的写法,可以在循环时过滤掉未保存的对象(通过persisted?方法判断,该方法会返回true仅当对象已存入数据库):
<% micropost.comments.select(&:persisted?).each do |comment| %> <div class="comment"> <%= comment.content %> <%= link_to "Comments posts", micropost_comment_path(micropost, comment), method: :get %> </div> <% end %>
两种方法都能解决你遇到的问题,根据你的代码习惯选择就好。
内容的提问来源于stack exchange,提问作者Lee Eather
相关产品推荐
相关产品推荐

