Rails通过对象关联重现了奇怪的行为

Edu*_*ard 7 ruby ruby-on-rails ruby-on-rails-3.2 ruby-2.1

我有一个与回复相关的评论表.基本上,具有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 %>
Run Code Online (Sandbox Code Playgroud)

输出是:

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

在第二次迭代中,comment.replies是一个Comment,而不是一个数组,并且都从那里掉了下来.

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

<% x = comment.reload.replies %>
Run Code Online (Sandbox Code Playgroud)

一切都开始工作,输出是:

349223; 注释
数组
349229; 注释
Array
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
Run Code Online (Sandbox Code Playgroud)

acs*_*ith 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
Run Code Online (Sandbox Code Playgroud)

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