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