【问题标题】:How to memoize in parent object of ActiveRecord?如何在 ActiveRecord 的父对象中记忆?
【发布时间】:2014-02-01 00:13:26
【问题描述】:

我如何在父对象中记忆一个昂贵的查询并在子对象中重用它?我面临的问题是,每次我从子级到父级进行引用: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

这应该只查询一次 cmets,但因为它没有在加载两次的同一个对象上记忆

Loading comments...
Loading comments...

【问题讨论】:

    标签: ruby-on-rails activerecord memoization


    【解决方案1】:

    几种方法:

    1.使用ActiveRecord Association Extensions

    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 的回答和this RailsCast 中有所提及:

    Post.includes(:comments)
    

    我认为 NitinJ 的 cmets 比我的要好,因为我只有使用 .includes 创建数据库调用的经验(不以关联容量使用它)


    奖励 - Counter-Cache - 使用它而不是 comments.count - 它将计数存储在内存中,这将消除昂贵的数据库调用!

    【讨论】:

      【解决方案2】:

      试试这个帖子=Post.last(include: :comments)这个语句急切加载关系现在执行操作post.comments[0]这不会触发任何SQL查询来发现关联记录已经存在

      【讨论】:

        猜你喜欢
        • 2020-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多