Activerecord 为什么/如何在关系返回的集合/数组上调用模型的类方法?

Activerecord 为什么/如何在关系返回的集合/数组上调用模型的类方法?,activerecord,ruby-on-rails-3,relationship,Activerecord,Ruby On Rails 3,Relationship,所以我今天遇到了一段有趣的代码,它引起了我的注意。我认为这是不可能的。代码行是: @post.comments.approved_comments 看起来不错,对吧?但是真正发生的事情是,approved\u comments方法在数组对象的实例上被调用,该对象由具有多个关系(即,帖子有多个注释)返回。更有趣的是,approved\u comments是在Comment模型上定义的类方法 让我有点困惑的是,我认为不能将关系链接起来,至少不能直接链接,因为关系返回的是Array,而不是Activ

所以我今天遇到了一段有趣的代码,它引起了我的注意。我认为这是不可能的。代码行是:

@post.comments.approved_comments
看起来不错,对吧?但是真正发生的事情是,
approved\u comments
方法在
数组
对象的实例上被调用,该对象由
具有多个
关系(即,帖子有多个注释)返回。更有趣的是,
approved\u comments
是在
Comment
模型上定义的类方法

让我有点困惑的是,我认为不能将关系链接起来,至少不能直接链接,因为关系返回的是
Array
,而不是
ActiveRecord::Relation
对象。我以前问过一个与此相关的问题,给我的答案是,您可以通过使用
作用域
方法或由于关系而添加到数组中的众多方法之一(即,)来连锁关系

同样让我困惑的是,
approved_comments
是我们编写的一种方法;它不是由
has\u many
关系方法添加的方法。那么我怎么可能访问它呢?更令人困惑的是,我如何能够通过
数组
对象访问它

当然,这里有一些神奇的东西。我想知道是否有人可以告诉我一些文档,或者是否有专家对此有答案。这不是一个大问题,因为它似乎工作得很好,但我真的很想知道如何教育自己

提前谢谢你的帮助

代码 邮递 评论 用法
这与ActiveRecord加载查询的方式有关。在您调用对象上的方法之前,它不会执行。因此,它可以更高效地构建整个查询。但是,使用范围更容易完成您要做的事情:

class Post
  has_many :comments
end

class Comment
  scope :approved_comments, where(:approved => true)
end
现在,您可以执行Comment.approved_comments以获取所有已批准的评论,或执行@post.comments.approved_comments以获取已批准的帖子评论

此外,作用域可以采用可选参数。如果您希望获得自用户上次访问以来的所有帖子的批准(例如):

然后您可以调用:
@post.comments.approved\u-since(@user.last\u-login)
例如


查看以了解更多信息。

这里的这一条准确地解释了您的问题嗨,赛斯,谢谢您的回复。关于使用方法和作用域,除了更少的代码行和声明式的编码风格之外,使用作用域与使用方法相比实际上没有任何优势。我选择听从这篇文章的建议,命名范围是死的()。关于
返回的内容有很多,我不确定您所说的是否是真的。所有文档都说明返回了一个集合对象,这意味着正在执行SQL。我认为Rails 3中对查询接口的新更改可能会引起一些混淆,更具体地说,查询现在返回ActiveRecord::Relation对象的一个实例,并且在调用
all
first
last
或将该对象视为可枚举对象之前不会执行。
@post.comments.class
返回数组这一简单事实证明了ActiveRecord::Relation没有返回。
class Comment
  def self.approved_comments
    where(:approved => true)
  end
end
@post.comments.approved_comments
class Post
  has_many :comments
end

class Comment
  scope :approved_comments, where(:approved => true)
end
class Comment
  scope :approved_since, lambda{ |date| where(['approved_at > ?', date]) }
end