.build的奇怪行为

时间:2015-01-03 16:23:42

标签: ruby-on-rails ruby-on-rails-4 renderpartial

背景

build

我遇到这种奇怪的行为时,我正在向rails guide学习

所以在指南中我正在制作一个帖子有评论部分的博客。在指南中,发布的评论发布在评论表单之前,用于添加新评论。不知怎的,我想尝试相反的方式(评论形式首先)。但是,当我这样做时,会渲染其他空标记<h4></h4><p></p>

最初,我认为它是从模型中呈现空注释但是在运行

之后
<%= @article.comments.count %> # => 2 gives expected comments count

现在是奇怪的部分。当我按照指南颠倒顺序时,首先是评论,然后是评论, 空标签消失了,一切正常。

问题

  1. 我该如何解决? (解决)
  2. 为什么更改表单和注释的顺序会导致'bug'消失?
  3. 视图

    #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 %>
    

    答案/结果摘要

    解决方案

    使用

    Comment.new代替@article.comments.build,因为.build正在制作一个额外的实例(这是一个错误吗?)

    new vs build

    根据克里斯的说法

      

    .new方法自Rails&gt;以来已发生变化3.2.13

    newbuild是相同的。 build仅仅是别名

    sizecount

    的比较

    我在帖子中找到了此SO post about count vs sizerecommended reading。万一有人经过,想要了解更多关于微妙的事情。

    本质上(来自SO帖子)和@JiříPospíšil回答 count向db发送查询以检索元素数。在这种情况下,@ article.comments.count返回数据库中的注释数

    length给出加载到内存中的注释数,表示内存和db数据可能不一样。记忆中的一些元素可能是新的。

    size as @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时,所有方法都返回1,这与this guy said

    一致

    修改

    更明确地陈述问题 添加了答案/讨论摘要

2 个答案:

答案 0 :(得分:1)

<%= 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创建的评论未保存到数据库中{{1无论是否已加载集合,始终执行#count查询。您可以使用COUNT代替(#size)来查看额外的评论。

答案 1 :(得分:0)

问题在于您的评论形成了部分调用@article.comments.build,除了构建新的Comment实例之外,还会将此实例添加到集合中。所以这就是你看到额外评论的原因。请尝试使用@article.comments.new

另请参阅:Build vs new in Rails 3

修改

我刚发现自{Rails&gt;以来.new方法已发生变化3.2.13。既然你用Rails-4标记了帖子,我提出的解决方案就不起作用了。相反,请尝试使用@article.comments.scoped.new作为建议here