获取具有书签状态的记录列表

时间:2017-07-26 11:55:29

标签: sql ruby-on-rails activerecord

我有一个应用程序,用户可以在其中为帖子添加书签。为了处理书签,我创建了一个名为Bookmark的多态模型。

现在我需要显示所有帖子的列表(让我们说每页50个,分页),其中包含当前登录用户的标题和书签状态。

我脑子里有两个场景我怎么能实现这个目标。而且我不喜欢他们中的任何一个。

  1. 在渲染列表时检查每个帖子的书签状态 - 这会产生N + 1个查询,基本上是一个可怕的想法
  2. 获取当前页面的帖子ID列表,获取当前用户bookmarkable_id IN post_ids_of_current_page的所有书签,检查可收藏列表中的帖子,并根据此显示书签状态。
  3. 这第二个是非常合理的,但我真的想把它全部合并到一个SQL查询中(如果可能的话,我不确定是否可以使用joins完成)。这是因为事实上,我并没有在常规的rails视图中使用它,而是在graphql API端点+ SPA应用程序中使用它,并且获取集合ID和比较并不是一件容易的事情。他们。它只会导致更多的api请求,我很乐意避免。

1 个答案:

答案 0 :(得分: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]