如何在父对象中记住昂贵的查询并在子对象中重用它?我面临的问题是,每次我从孩子到父级:child1.parent或child2.parent引用时,它都会给出不同的对象ID,并且不会发生记忆。
class Post
has_many :comments
def total_comments
unless @total_comments
puts "Loading comments"
@total_comments = comments.count
end
@total_comments
end
end
class Comment
belongs_to :post
def total_comments
post.total_comments
end
end
post.comments[0].total_comments
post.comments[1].total_comments
这应该只查询一次注释,但由于它没有在同一对象上被记住,所以它加载了两次
Loading comments...
Loading comments...
几种方法:
1. 使用活动记录关联扩展
class Post
has_many :comments do
def total
proxy_association.target.size
end
end
end
允许您调用proxy_association
对象,并将该方法附加到comments
的实例中(以便您可以调用@post.comments.total
)
2. 使用:inverse_of
#app/models/post.rb
Class Post < ActiveRecord::Base
has_many :comments, inverse_of: :post
end
#app/models/comment.rb
Class Comment < ActiveRecord::Base
belongs_to :post, inverse_of: :comments
end
允许您从self
引用父对象 ( self.post.total_comments
)
3. 使用"预先加载"(将对象保留在内存中)
这是查询级别的,并在NitinJ的回答和这个RailsCast中提到:
Post.includes(:comments)
我认为 NitinJ 的评论在这里比我的要好,因为我只有使用 .includes
创建数据库调用的经验(不以关联身份使用它)
奖励 - 计数器缓存 - 使用它代替comments.count
- 它将计数存储在内存中,这将删除昂贵的数据库调用!
试试这篇文章 = Post.last(include: :comments)
此语句急切加载关系 现在执行操作post.comments[0]
这不会触发任何SQL
查询来查找 因为关联的记录已经存在