2013-10-21 14 views
7

私は自分のサイトでユーザーフィードのいくつかのN + 1クエリを削除しようとしています。 FeedItemモデルへのポリモーフィックな関連を持っている様々なモデル条件付きで多型関連の読み込み

class Event < ActiveRecord::Base 
    has_many :feed_items, as: :feedable 
end 

class Tournament < ActiveRecord::Base 
    has_many :feed_items, as: :feedable 
end 

class FeedItem < ActiveRecord::Base 
    belongs_to :feedable, :polymorphic => true 
end 

ユーザモデルはまた、両方のは、異なる属性を持つユーザーhas_manyのトーナメントやイベント関与しているがあります。ユーザーのFeedItemsを読み込む際に、FeedItemの型に基づいてネストされた属性を条件付きで読み込む方法を教えてください。

私は(squeelのDSLで)何を意味するかの例:

FeedItem.where{ (feedable_id.in(@user.tournaments.ids}) & feedable_type.eq('Tournament')) |  
       (feedable_id.in(@user.events.ids) & feedable_type.eq('Event')) }.includes(:feedable => :game) 

このクエリでは、熱心にトーナメントモデルの「ゲーム」属性のロード中にタイプ大会やイベントのすべてFeedItemsを取得しようとします。トーナメントでうまく動作しますが、FeedItemsを反復処理すると、イベントはこの属性が存在しないというエラーをスローします。

私の現在のハックは、すべてのFeedItemタイプに対して個別のクエリを実行し、レコードを一緒に追加することです。しかし、これは関連付けを、私がしたくない配列に変換します。

アイデア?

+0

あなたは依然として個別のクエリを実行できますが、何かを読み込むのではなく、FeedItem IDをそれぞれ抜き取ることができます。あなたが収集したすべてのIDの配列を作成し、それを単一のクエリに渡します。 – Humza

答えて

1

ポリモーフィックな関連付けのネストされた関連付けを事前にロードすることは可能です。

class FeedItem < ActiveRecord::Base 
    belongs_to :feedable, :polymorphic => true 

    belongs_to :event, -> { where(feedable_type: 'Event') }, foreign_key: :feedable_id 
    belongs_to :tournament, -> { where(feedable_type: 'Tournament') }, foreign_key: :feedable_id 
end 

だけtournamentため、ネストされた関連付けをプリロードすることができた後:あなたはFeedItemにさらに2つの関連付けを追加する必要が

feeds = 
    FeedItem.where(" 
    (feedable_id IN (?) AND feedable_type = 'Tournament') OR 
    (feedable_id IN (?) AND feedable_type = 'Event')", @user.tournament_ids, @user.event_ids). 
    includes(:feedable, tournament: :game) 

今、あなたは追加のクエリせずにトーナメントの試合を関連することがあります。

feeds.each do |feed| 
    puts feed.feedable.inspect 
    puts feed.tournament.game.inspect if feed.feedable_type == "Tournament" 
end 
+0

このバージョンはRails 4.2で動作します –

関連する問題