Rails递归查看对象关联的奇怪行为

Posted

技术标签:

【中文标题】Rails递归查看对象关联的奇怪行为【英文标题】:Rails recurive view strange behaviour with object association 【发布时间】:2014-07-17 21:13:57 【问题描述】:

我有一个与其自身关联的 cmets 表,用于回复。基本上,具有 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

【问题讨论】:

你能在github上推送示例应用吗? 你能告诉我们你是如何得到回复的吗?它是一个named_scope 还是一个关联?还有它之前在什么 Rails/ruby 上工作过? 能否显示非简化视图?代码在我的机器上正常工作。 我无法将应用推送到 git,它是一个巨大的应用,这只是其中的一小部分。它适用于 rails 2.3 和 ruby​​ 1.8.7。我刚刚登陆这个应用程序,我必须将它升级到 rails 3.2 和 ruby​​ 2.1.1。我解决了很多问题,但这一个打败了我。我还将添加定义关联的模型代码 【参考方案1】:

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

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

您在模型代码中使用:has_many 会得出这样的结论。至少在 Rails 4 中,CollectionProxy 包含通过:has_many 关联的对象集合上的缓存。文档中的This example 概述了缓存/重新加载过程。

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

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

编辑!看看吧,来自CollectionProxy source:

# 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 中是新的,这可能是你的问题。

【讨论】:

谢谢,我会尽快尝试(现在我将其搁置并处理其他事情),我会回复您结果

以上是关于Rails递归查看对象关联的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

boost::variant:递归向量类型的奇怪行为

JavaScript递归奇怪的行为?

递归泛型类型来扩展类型 - 奇怪的行为,这是一个错误吗?

定递归验证关联的对象可以用于继承对象吗 spring validate

Inotify:目录创建的奇怪行为

Laravel 一对多关系不起作用 - 返回递归