查找没有 has_many 的记录:通过记录匹配条件

Find records with no has_many :through record matching criteria

使用Rails4,并给出以下模型:

class Draft < ActiveRecord::Base
  has_many :drafters
  has_many :users, through: :drafters
end

class Drafter < ActiveRecord::Base
  belongs_to :draft
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :drafters
  has_many :drafts, through: :drafters
end

如何检索与用户实例 current_user 无关的所有草稿?也就是说,没有属于 dcurrent_user.

的草稿人的所有草稿 d

如果有帮助,我有Squeel可用。

你可以用includes实现它:

Draft.includes(:drafters)
     .where('(drafters.user_id <> ? or drafters.user_id is null)', current_user.id})
     .references(:drafters)
Draft.includes(:drafters).where(:drafters => { :draft_id => nil } ) 

将 return 所有没有起草人的草稿。

Draft.includes(:drafters).where.not(:drafter => { user_id => current_user.od })

将 return 所有不属于 current_user 的草稿。

有关详细信息,请查看 the difference between outer an inner join

使用 Squeel,您可以:

Draft.joins{drafters.outer}.where{(drafters.user_id != current_user.id) | (drafters.user_id.eq nil)}

这将生成:

SELECT "drafts".* FROM "drafts" LEFT OUTER JOIN "drafters" ON "drafters"."draft_id" = "drafts"."id" WHERE ("drafters"."user_id" != 1 OR "drafters"."user_id" IS NULL)

我找到了基于以下嵌套查询的答案(带有 squeel):

SELECT "drafts"."id" FROM "drafts"
    WHERE "drafts"."id" NOT IN 
        (SELECT "drafters"."draft_id" FROM "drafters" 
            WHERE (("drafters"."draft_id" = "drafters"."id" 
                    AND "drafters"."user_id" = 2)))

可转换为 Rails+squeel 查询:

Draft.where{ id.not_in(Drafter.select(:draft_id).where{
        (draft_id == drafts.id) & (user_id == omit_user_id)})}