🙆

Rails で関連先と紐付いていないレコードを取得する

2024/08/22に公開

例えば『まだコメントしていないユーザを絞り込む』みたいなことをしたい場合に以下のように .left_joins + .where で絞り込む、で実現することができます。

class User < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :user
end

# 必要なデータを生成
User.create(name: "homu").tap {
  _1.comments.build(text: "OK").save!
  _1.comments.build(text: "NICE").save!
}
User.create(name: "saya").tap {
  _1.comments.build(text: "oops").save!
}
User.create(name: "mami")
User.create(name: "mado")


# こんな感じで『comments が存在しない user』を絞り込むことができる
User.left_joins(:comments).where(comments: { id: nil }).tap {
  puts _1.to_sql
  # => SELECT "users".*
  #      FROM "users"
  #      LEFT OUTER JOIN "comments"
  #        ON "comments"."user_id" = "users"."id"
  #     WHERE "comments"."id" IS NULL

  pp _1.pluck(:name)
  # => ["mami", "mado"]
}

また Rails 6.1 以降では where.missing が利用できます。

# User.left_joins(:comments).where(comments: { id: nil }) と同等
User.where.missing(:comments).tap {
  puts _1.to_sql
  # => SELECT "users".*
  #      FROM "users"
  #      LEFT OUTER JOIN "comments"
  #        ON "comments"."user_id" = "users"."id"
  #     WHERE "comments"."id" IS NULL

  pp _1.pluck(:name)
  # => ["mami", "mado"]
}
GitHubで編集を提案

Discussion