3

レンダリングに時間がかかるページがあります。時間の半分 (3 秒) は、熱心にロードされたアソシエーションの束を持つ .find 呼び出しに費やされます。私が実際に必要とするのは、テーブルに表示するために、それぞれの場合に関連付けられたレコードの数だけです。実際のレコード自体は必要ありません。カウントを熱心にロードする方法はありますか? 簡単な例を次に示します。

@subjects = Subject.find(:all, :include => [:questions])

私のテーブルでは、各行 (つまり、各科目) について、科目フィールドの値と、各科目に関連する質問の数を表示するだけです。これらの要件に合わせて上記の検索呼び出しを最適化できますか?

グループフィールドを使用することを考えましたが、完全な呼び出しにはいくつかの異なる関連付けが含まれており、いくつかの二次関連付けが含まれているため、group by は機能しないと思います。

@subjects = Subject.find(:all, :include => [{:questions => :tags}, {:quizzes => :tags}], :order => "subjects.name")

この場合の :tags は、タグ付けによる二次的な関連付けです。何が起こっているのかはっきりしない場合に備えて、ここに私の関連付けを示します。

Subject
  has_many :questions
  has_many :quizzes

Question
  belongs_to :subject
  has_many :taggings
  has_many :tags, :through => :taggings

Quiz
  belongs_to :subject
  has_many :taggings
  has_many :tags, :through => :taggings

アドバイスに感謝します-最大

4

3 に答える 3

3

:counter_cache関連付けを使用するのが最善だと思いますbelongs_to

class Subject < ActiveRecord::Base
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :subject, :counter_cache => true
end

使用するには、テーブルに列をcounter_cache追加する必要もあります。questions_countsubjects

からrailsapi.com:

:counter_cache
increment_counter と decrement_counter を使用して、関連付けられたクラスに属するオブジェクトの数をキャッシュします。カウンタ キャッシュは、このクラスのオブジェクトが作成されると増加し、破棄されると減少します [...]

于 2010-05-12T13:11:31.943 に答える
1

この目的のためにカウンター キャッシュを実装できます。関連付けられている写真の数を追跡する Albums モデルのカウンターを維持しています。私のプロセスは次のようになります (この方法はどこかのブログで見つけたと思いますので、元のコードは信用しません)。

写真モデル:

after_save :update_counter_caches
after_destroy :update_counter_caches

def update_counter_caches
  self.albums.each { |a| a.update_count } unless self.albums.empty?
end

アルバム モデル:

def update_count
  update_attribute(:photographs_count, self.photographs.length)
end

アルバムで必要な移行:

class AddCounterCacheColumnToModels < ActiveRecord::Migration
  def self.up
    add_column :albums, :photographs_count, :integer, :default => 0
  end

  def self.down
    remove_column :albums, :photographs_count
  end
end

私があなたの質問を誤解していない限り、それはあなたが望むものを達成するためのかなりきちんとした方法であるはずです. 現在のプロジェクトではうまく機能します。:)


編集: 注意として、デフォルトの :counter_cache メソッドではなくこのセットアップを使用する理由は、1 つのモデルで複数の関連付けに対して複数のカウンターを維持する必要があるためです。私の知る限り、:counter_cache ではそれを達成できません。

于 2010-05-12T11:50:13.447 に答える
0

私が考える最速の方法:

@subjects = Subject.count(:joins => :questions, :select => 'DISTINCT(questions.id)')

そして、より複雑なクエリについてはわかりません(テストされていません):

@subjects = Subject.count(:joins => [{:questions => :tags}, {:quizzes => :tags}], :select => 'DISTINCT(tags.id)'
于 2010-05-12T12:50:01.780 に答える