.build 的奇怪行为
Strange behaviour with .build
背景
当我遇到这种由 build
引起的奇怪行为时,我正在向 rails guide 学习
所以在指南中,我正在创建一个博客,其中 posts 有评论部分。在指南中,他们让评论 posted 出现在用于添加新评论的评论表单之前。不知何故,我想尝试另一种方式(首先形成评论)。但是,当我这样做时,会呈现额外的空标签 <h4></h4><p></p>
。
最初我认为它正在渲染模型中的空注释,但在运行后
<%= @article.comments.count %> # => 2 gives expected comments count
酷儿部分来了。当我按照指南颠倒顺序时,评论先形成然后评论,
空标签消失了,一切正常。
问题
- 我该如何解决? (已解决)
- 为什么更改表单和注释的顺序会导致 'bug' 消失?
查看
#This works
#comments
<h3>Comments</h3>
<%= render @article.comments %>
#comments form
<h3>Add a comment!</h3>
<%= render 'comments/form' %>
#But not this
#comments form
<h3>Add a comment!</h3>
<%= render 'comments/form' %>
#comments
<h3>Comments</h3>
<%= render @article.comments %>
部分
评论部分
<h4>
<%= comment.commenter %>
</h4>
<p>
<%= comment.body %>
</p>
部分评论形式
<%= form_for([@article, @article.comments.build]) do |f| %>
<p class="commenter">
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p class="text">
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
摘要answers/findings
解决方案
使用 Comment.new
而不是 @article.comments.build
因为 .build
正在创建一个额外的实例(这是一个错误吗?)
new
对比 build
根据克里斯
.new method has changed since Rails > 3.2.13
new
和build
是一样的。 build
只是一个别名
size
与 count
的比较
我在那个 post 中找到了这个 SO post about count vs size and the recommended reading。以防有人路过,想知道更多的精妙之处。
本质上(来自 SO post)和@Jiří Pospíšil 的回答
count
向数据库发送查询以检索元素数。在此上下文中@article.comments.count returns 数据库中的评论数
length
给出加载到内存中的注释数量,表示内存和数据库数据可能不相同。内存中的一些元素可能是新的。
size
因为@Jiří Pospíšil 将给出集合中元素的数量(如果已加载)(如 length
),否则工作方式类似于 count
并发送 SQL COUNT 个查询
#when .build was used
<%= @article.comments.length %> # => 2
<%= @article.comments.count %> # => 1
<%= @article.comments.size %> # => 2
并且当使用建议的解决方案Comment.new
时,所有方法return 1 与this guy said
一致
编辑
更明确地陈述问题
添加了 answers/discussion
的摘要
<%= form_for([@article, @article.comments.build]) do |f| %>
@article.comments.build
部分将创建一个新的 Comment
并将其添加到 @article.comments
集合中。稍后,您遍历集合,这就是为什么多了一个集合。如果您这样做,您实际上可以看到它的发生。
<%= form_for([@article, @article.comments.build(commenter: "Hello!")]) do |f| %>
要解决此问题,您需要创建一个 Comment
但不将其与集合相关联。使用 Comment.new
而不是 @article.comments.build
应该就足够了,因为记录本身并不重要。
请注意,您看到正确数量的评论 (@article.comments.count
) 的原因是通过 build
创建的评论尚未保存到数据库并且 #count
始终执行 COUNT
查询,无论集合是否已加载。您可以使用 #size
来查看额外的评论 (@article.comments.size
).
问题是您的评论表单部分调用了 @article.comments.build
,这除了构造一个新的 Comment 实例之外还将此实例添加到集合中。这就是您看到额外评论的原因。请尝试使用 @article.comments.new
。
另请参阅:Build vs new in Rails 3
编辑
我刚刚发现 .new
方法自 Rails > 3.2.13 以来发生了变化。由于您已将 post 标记为 Rails-4,因此我提出的解决方案不起作用。相反,请尝试按照 here 的建议使用 @article.comments.scoped.new
。
背景
当我遇到这种由 build
所以在指南中,我正在创建一个博客,其中 posts 有评论部分。在指南中,他们让评论 posted 出现在用于添加新评论的评论表单之前。不知何故,我想尝试另一种方式(首先形成评论)。但是,当我这样做时,会呈现额外的空标签 <h4></h4><p></p>
。
最初我认为它正在渲染模型中的空注释,但在运行后
<%= @article.comments.count %> # => 2 gives expected comments count
酷儿部分来了。当我按照指南颠倒顺序时,评论先形成然后评论, 空标签消失了,一切正常。
问题
- 我该如何解决? (已解决)
- 为什么更改表单和注释的顺序会导致 'bug' 消失?
查看
#This works
#comments
<h3>Comments</h3>
<%= render @article.comments %>
#comments form
<h3>Add a comment!</h3>
<%= render 'comments/form' %>
#But not this
#comments form
<h3>Add a comment!</h3>
<%= render 'comments/form' %>
#comments
<h3>Comments</h3>
<%= render @article.comments %>
部分
评论部分
<h4>
<%= comment.commenter %>
</h4>
<p>
<%= comment.body %>
</p>
部分评论形式
<%= form_for([@article, @article.comments.build]) do |f| %>
<p class="commenter">
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p class="text">
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
摘要answers/findings
解决方案
使用Comment.new
而不是 @article.comments.build
因为 .build
正在创建一个额外的实例(这是一个错误吗?)
new
对比 build
根据克里斯
.new method has changed since Rails > 3.2.13
new
和build
是一样的。 build
只是一个别名
size
与 count
的比较
我在那个 post 中找到了这个 SO post about count vs size and the recommended reading。以防有人路过,想知道更多的精妙之处。
本质上(来自 SO post)和@Jiří Pospíšil 的回答
count
向数据库发送查询以检索元素数。在此上下文中@article.comments.count returns 数据库中的评论数
length
给出加载到内存中的注释数量,表示内存和数据库数据可能不相同。内存中的一些元素可能是新的。
size
因为@Jiří Pospíšil 将给出集合中元素的数量(如果已加载)(如 length
),否则工作方式类似于 count
并发送 SQL COUNT 个查询
#when .build was used
<%= @article.comments.length %> # => 2
<%= @article.comments.count %> # => 1
<%= @article.comments.size %> # => 2
并且当使用建议的解决方案Comment.new
时,所有方法return 1 与this guy said
编辑
更明确地陈述问题
添加了 answers/discussion
<%= form_for([@article, @article.comments.build]) do |f| %>
@article.comments.build
部分将创建一个新的 Comment
并将其添加到 @article.comments
集合中。稍后,您遍历集合,这就是为什么多了一个集合。如果您这样做,您实际上可以看到它的发生。
<%= form_for([@article, @article.comments.build(commenter: "Hello!")]) do |f| %>
要解决此问题,您需要创建一个 Comment
但不将其与集合相关联。使用 Comment.new
而不是 @article.comments.build
应该就足够了,因为记录本身并不重要。
请注意,您看到正确数量的评论 (@article.comments.count
) 的原因是通过 build
创建的评论尚未保存到数据库并且 #count
始终执行 COUNT
查询,无论集合是否已加载。您可以使用 #size
来查看额外的评论 (@article.comments.size
).
问题是您的评论表单部分调用了 @article.comments.build
,这除了构造一个新的 Comment 实例之外还将此实例添加到集合中。这就是您看到额外评论的原因。请尝试使用 @article.comments.new
。
另请参阅:Build vs new in Rails 3
编辑
我刚刚发现 .new
方法自 Rails > 3.2.13 以来发生了变化。由于您已将 post 标记为 Rails-4,因此我提出的解决方案不起作用。相反,请尝试按照 here 的建议使用 @article.comments.scoped.new
。