如果我有这样的话:
class Post < ActiveRecord::Base
has_many :comments, :as => :commentable do
def approved
find(:all, :conditions => {:approved => true})
end
end
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
...当我这样做时,我得到2次点击数据库(不包括找到帖子:p):
post = Post.first
post.comments #=> [Comment1, Comment2...]
post.comments.approved #=> [Comment1, Comment7...]
看起来它应该只是过滤内存中的当前注释数组,不是吗?它是这样做的吗?我问的原因是因为控制台在SELECT * FROM ...
上显示post.comments.approved
,即使我已调用post.comments
。不应该在ActiveRecord中更好地优化它吗?
答案 0 :(得分:1)
它是可选的,因为在某些情况下,您可能只想在需要时加载关联的对象。如果您希望将它们全部加载到内存中,则需要使用:include标志显式声明您希望包含在初始查询中的对象。例如:
post = Post.find(:first, :include => :comment)
您可能需要重写扩展程序以利用该功能......一种方法是更改“已批准”的函数以迭代附加到每个帖子的注释数组,并返回包含未批准注释的新数组过滤掉了。您已明确定义的“查找”将返回数据库。
答案 1 :(得分:1)
AR对关联扩展方法中的任何finder调用执行新查询。
您可以使用self
来引用缓存的结果集。
has_many :comments, :as => :commentable do
def approved
# uses the cached result set
self.select{|c| c.approved == true}
end
end
答案 2 :(得分:0)
如果您的查询真的很简单,那么您想要的是命名范围:
class Comment
named_scope :approved, :conditions => {:approved => true}
end
然后,你可以这样做:
@post.comments.approved.count #=> 1 DB hit!
@post.comments.count #=> Another DB hit - can't reuse same scope
查看#scope(Rails 2.3中的#named_scope)。