如何在活动记录的父对象中记忆



如何在父对象中记住昂贵的查询并在子对象中重用它?我面临的问题是,每次我从孩子到父级: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查询来查找 因为关联的记录已经存在

最新更新