2017-07-26 23 views
0

我有一個應用程序,用戶可以在該應用程序中爲書籤添加書籤。爲了處理書籤,我創建了一個名爲Bookmark的多態模型。獲取帶有書籤狀態的記錄列表

現在我需要顯示當前登錄用戶的標題和書籤狀態的所有帖子(比如說,每頁50個,分頁)的列表。

我有兩種情況在我的腦海中,我怎麼能做到這一點。我不喜歡他們中的任何一個。渲染列表時,每個帖子

  1. 檢查書籤狀態 - 這會產生N + 1個查詢,基本上是一般
  2. 一個可怕的想法得到一個當前頁面的後ID的列表,獲取所有的書籤當前用戶,其中bookmarkable_id IN post_ids_of_current_page,檢查哪個帖子出現在可收藏列表中,並基於此顯示書籤狀態。

這第二是非常合理的,但我真的想將它全部合併到一個SQL查詢(如果可能的話,我不知道是否可以使用joins來完成)。這是因爲事實上,我沒有在常規的rails視圖中使用它,而是在graphql API endpoint + SPA應用程序中使用它,並且它並不是輕易獲取集合ID並比較它們。這隻會導致對我很想避免的api的更多請求。

回答

0

原來,我可以使用includes方法(這將產生兩個查詢,但它仍然比N + 1好)。如果任何人都可以與joins共享一個查詢版本,我將非常樂意接受它的答案,但到目前爲止,我發佈了足以滿足我需求的解決方案。

class User 
    has_many :bookmarks, as: :bookmarker 
end 

class Post 
    has_many :bookmarks_as_bookmarkable, as: :bookmarkable, class_name: :Bookmark 

    def bookmarked_by?(bookmarker) 
    self.bookmarks_as_bookmarkable.to_a.select do |b| 
     b.bookmarker_type == bookmarker.class.name && 
     b.bookmarker_id == bookmarker.id 
    end.any? 
    end 
end 

而且結果:

Post.includes(:bookmarks_as_bookmarkable).map { |p| u.bookmarked_by?(current_user) }` 
# SELECT "posts".* FROM "posts" 
# SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."bookmarkable_type" = ? AND "bookmarks"."bookmarkable_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30) 
# 
# => [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true]