减去两个 ActiveRecord::Relation 对象

3

我希望给我的应用程序用户提供机会从他们的微博中删除不想要的微博。默认情况下,微博包括用户自己的微博和所关注用户的微博:

def feed
  following_ids = "SELECT followed_id FROM relationships
                   WHERE  follower_id = :user_id"
  Micropost.where("user_id IN (#{following_ids})
                   OR user_id = :user_id", user_id: id)
end

我创建了一个名为Quarantine的模型,将用户和不需要的微博关联起来。然后我查找了一个ActiveRecord::Relation方法,允许我从上述where中减去以下where

microposts_ids = "SELECT micropost_id FROM quarantines
                  WHERE  user_id = :user_id"

Micropost.where("micropost_id IN (#{microposts_ids})", user_id: id)

我找不到对应于-数组操作符的任何方法。但是我在一个 Stackoverflow 的问题中找到了merge方法:合并两个 ActiveRecord::Relation 对象,据我所知,这将允许我像下面这样链接wheres

Micropost.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id).merge(Micropost.where.not("micropost_id IN (#{microposts_ids})", user_id: id))

区别在于我将第二个where改为了where.not
这种解决方案的问题是,where.not会加载所有未被隔离的微博,这对数据库来说比仅加载被隔离的微博更加繁重。是否有其他替代方法可以使用,例如从原始动态中减去被隔离的微博的方法?
2个回答

3
针对特定的用户
microsposts_not_to_show = Micropost.joins(:quarantines).where("quarantines.user_id" => user.id)
all_microposts = Micropost.where("user_id" => user.id) + Micropost.joins(:user => : relationships).where("relationships.follower_id" => user.id)
microposts_to_show = all_microposts - microposts_not_to_show

我们正在连接这些表。除非使用select方法明确指定,否则不会显示Quarantine对象。 - moyinho20
你能告诉我隔离表中有哪些列吗? - moyinho20
user_idmicropost_id。然而,Micropost.joins(:quarantines)是一个Micropost对象,而不是Quarantine对象,这就是为什么Active Record会抱怨:Micropost对象没有user_id列:ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column microposts.user_id does not exist - Asarluhi
到底是什么错误? ActiveRecord::StatementInvalid:PG :: UndefinedColumn:ERROR:column quarantines.user_id 不存在ActiveRecord::StatementInvalid:PG :: UndefinedColumn:ERROR:column microposts.user_id 不存在 - moyinho20
让我们在聊天中继续这个讨论 - Asarluhi
显示剩余2条评论

0

对于Rails 5,它可能看起来像:

class User < ApplicationRecord
  has_many :relationships
  # ...
  def feed
    Micropost
      .where(user_id: relationships.select(:followed_id))
      .or(Micropost.where(user_id: id))
      .where.not(id: Quarantine.select(:micropost_id).where(user_id: id))
  end
end

feed返回relation,它只生成一个数据库请求,并且可以与其他过滤、排序等操作链接使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接