1

I would like to override ActiveRecord's association methods in some instances (related to caching the foreign keys of indirect belongs_to relationships. A typical example is a QuoteStop has a Stop and a Stop has a PostalCode and I want to cache the postal_code_id at the QuoteStop level also.

For this example, I'd like to add something like the following:

class QuoteStop
  attr_accessible :stop_id, :postal_code_id
  belongs_to :stop
  belongs_to :postal_code

  def postal_code_id
    self[:postal_code_id] or postal_code_id!
  end

  def postal_code_id!
    self.postal_code_id = stop.postal_code_id
  end

  def postal_code
    self[:postal_code_id] ? super : PostalCode.find(postal_code_id) if postal_code_id
  end

end

class Stop
  attr_accessible :postal_code_id
end

The problem is that this seems to bypass the cache for postal_code. For example, the following will result in n+1 queries where it should just result in 2.

QuoteStop.includes(:postal_code).limit(n).collect { |qs| qs.postal_code.name }

How do I use this technique without sacrificing the performance gains of ActiveRecord caching?

4

1 に答える 1

0

あなたのコードが正しいかどうか確信が持てず、あなたのコードは何もキャッシュしません。私なら次のように書きます。

def postal_code_id 
  @postal_code_id ||= stop.postal_code_id
end

def postal_code
  if self.postal_code_id
    @cached_postal_code ||= PostalCode.find(self.postal_code_id)
  else
    super
  end
end

しかし、これが大きな改善になるかどうかはわかりません。を行うことPostalCode.findは、 を行うこととまったく同じだからstop.postal_codeです。

postal_code_idでは、キャッシングによってキャッシングがどのように改善されると思いますか? アイデンティティ マップの線に沿って考えている場合を除き、それぞれPostalCodeが 1 回だけ取得されます。ただし、クラス レベルでさらに複雑なことを行う必要があります。QuoteStopそれ自体 (インスタンス) の any は、以前に取得された a を認識しないためですPostalCode

お役に立てれば。

于 2012-08-26T22:34:10.607 に答える