簡體   English   中英

有條件地渴望加載多態關聯

[英]Conditionally eager loading polymorphic associations

我正在嘗試為我的網站上的用戶Feed刪除一些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

用戶模型也涉及用戶具有多種具有不同屬性的錦標賽和事件。 為用戶加載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)

此查詢嘗試在急切加載錦標賽模型的“游戲”屬性時檢索錦標賽和賽事類型的所有FeedItem。 適用於錦標賽,但在迭代FeedItems時,事件將拋出此屬性不存在的錯誤。

我目前的hack是對每個FeedItem類型執行單獨查詢並將記錄添加到一起。 但是,這會將關聯轉換為我不想做的數組。

有任何想法嗎?

可以為多態關聯預加載嵌套關聯。 您需要向FeedItem添加兩個關聯:

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預加載嵌套關聯:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM