7

我有一个与自己相关联的评论表,用于回复。基本上,具有 parent_id 的评论也是对他的父评论的回复。

为了渲染这个,我使用了一个递归视图,它在过去很简单,但不适用于 rails 3.2.0 和 ruby​​ 2.1.1

这是简化的代码:

<% x = comment.replies %>
<%= comment.id %>; <%= comment.class %><br/>
<%= comment.replies.class %><br><br>
<hr>
<br><br>
<% if x and x.is_a?(Array) %>
  <%= render :partial => "/_redesign/entry/comment", :collection => x, :as => :comment%>
<% end %>

输出是:

349223; 注释
数组
349229;评论
评论

在第二次迭代中,comment.replies是一个评论,而不是一个数组,并且全部从那里掉下来。

但是,如果我更改第一行并添加重新加载:

<% x = comment.reload.replies %>

一切开始工作,输出是:

349223; 注释
数组
349229;注释
数组
349230;评论
数组

我很想了解这里发生了什么以及关联如何返回单个对象实例而不是它们的列表以及为什么使用重新加载。

添加模型代码:

class Comment < Response
  acts_as_deactivatable :dependencies => [:community_news_feed_items]

  has_many :replies, :class_name=>"Comment", :foreign_key=>"referring_c_id", :order=>"date ASC"

  belongs_to :parent_comment, :class_name=>"Comment", :foreign_key=>"referring_c_id"
end
4

1 回答 1

1

我认为问题在于,当您进入评论回复的范围时,您ActiveRecord::Association::CollectionProxy在原始评论和评论回复之间添加了一个中间人。它说,

@reflection对象代表一个:has_many宏。

这将遵循您:has_many在模型代码中的使用。至少在 Rails 4 中,CollectionProxy包含对通过 关联的对象集合的缓存:has_many文档中的这个示例概述了缓存/重新加载过程。

我在Rails 4Rails 3.2CollectionProxy的源代码上快速搜索了“缓存” ,Rails 3.2 文档中没有提到它。但它本可以在文档更改之前实施。

此外,也许这是意识形态,但#is_a?可以避免使用。您可以只使用:respond_to?(:each), 以便您可以Enumerable在其中使用任何类型的。

编辑!从CollectionProxy 源检查一下:

# This class has most of the basic instance methods removed, and delegates
# unknown methods to <tt>@target</tt> via <tt>method_missing</tt>. As a
# corner case, it even removes the +class+ method and that's why you get
#
#   blog.posts.class # => Array
#
# though the object behind <tt>blog.posts</tt> is not an Array, but an
# ActiveRecord::Associations::HasManyAssociation.
#
# The <tt>@target</tt> object is not \loaded until needed. For example,
#
#   blog.posts.count

看起来comment.replies实际上只是给你一个HasManyAssociation,而不是一个实际的对象。由于CollectionProxy是 Rails 3.1 中的新功能,这可能是您的问题。

于 2014-06-04T15:35:06.337 回答