本記事ではよく使うSQLの条件のActiveRecordでの書き方をまとめます
AND条件で検索
シンプルにwhereメソッドにカンマで条件を追加するとAND条件になります。
コード1
Tag.where(name: "南インド", position: 1)
結果1
app(dev):002> Tag.where(name: "南インド", position: 1) Tag Load (6.6ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" = '南インド' AND "tags"."position" = 1 /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff82fd1420 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>]
コード2
whereを連結させても同じ挙動になります。where条件をif文で分けたい場合や後述の大小比較のように1つのwhereメソッドの中身が煩雑になる場合はこちらの書き方がよさそうです。
Tag.where(name: "南インド").where(position: 1)
結果2
app(dev):010> Tag.where(name: "南インド").where(position: 1) Tag Load (15.5ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" = '南インド' AND "tags"."position" = 1 /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff80685c88 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>]
OR条件で検索
OR条件の方が書き方が複雑です。orメソッド内にクエリをもう1つ書きます。
https://railsguides.jp/active_record_querying.html#or条件
コード
Tag.where(name: "南インド").or(Tag.where(position: 3))
結果
app(dev):004> Tag.where(name: "南インド").or(Tag.where(position: 3)) Tag Load (0.7ms) SELECT "tags".* FROM "tags" WHERE ("tags"."name" = '南インド' OR "tags"."position" = 3) /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff77460510 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>, #<Tag:0x0000ffff774603d0 id: 2, created_at: "2025-11-03 00:42:55.770481000 +0000", name: "ビリヤニ", position: 3, updated_at: "2025-11-03 01:57:44.855153000 +0000", tag_group_id: 3>]
IS NULL
whereにnilを渡すだけでOKです。
コード
Tag.where(name: nil)
結果
app(dev):022> Tag.where(name: nil) Tag Load (43.0ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" IS NULL /* loading for pp */ LIMIT 11 /*application='App'*/ => []
IN句
whereに渡す値をスカラーから配列にするだけでIN句を実現できます。
コード
Tag.where(name: ["南インド","ビリヤニ"])
結果
app(dev):018> Tag.where(name: ["南インド","ビリヤニ"]) Tag Load (4.4ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" IN ('南インド', 'ビリヤニ') /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff80682088 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>, #<Tag:0x0000ffff80681f48 id: 2, created_at: "2025-11-03 00:42:55.770481000 +0000", name: "ビリヤニ", position: 3, updated_at: "2025-11-03 01:57:44.855153000 +0000", tag_group_id: 3>]
結合先のテーブルのwhere条件で絞り込む
以下のような書き方をします。
joinsの引数のtags: アソシエーション名whereのキーのtags: テーブル名
なのがポイントです。
コード1
TagGroup.joins(:tags).where(tags: { name: "南インド" })
結果
app(dev):015> TagGroup.joins(:tags).where(tags: { name: "南インド" }) TagGroup Load (6.8ms) SELECT "tag_groups".* FROM "tag_groups" INNER JOIN "tags" ON "tags"."tag_group_id" = "tag_groups"."id" WHERE "tags"."name" = '南インド' /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<TagGroup:0x0000ffff77e0c690 id: 1, name: "テスト", position: 1, created_at: "2025-11-02 14:58:36.249161000 +0000", updated_at: "2025-11-02 14:58:36.249161000 +0000">]
コード2
1対Nの関連の場合は、joinsに渡す引数がテーブル名の単数系のシンボルになります。
Restaurant.joins(:prefecture).where(prefectures: {name: "東京都"})
whereの大小比較(<, =<)
大小比較を直接表現するメソッドは用意されていないので、条件を文字で書いてプレースホルダーで比較対象の値を渡します。
コード1
Tag.where("position < ?", 2)
結果
app(dev):006> Tag.where("position < ?", 2) Tag Load (1.4ms) SELECT "tags".* FROM "tags" WHERE (position < 2) /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff7744c1c8 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>]
コード2
小なりイコールにしたい場合は、<を<=にします。
Tag.where("position <= ?", 2)
LIKE検索
LIKE検索も同様に直接表現するメソッドは用意されていないので、条件を文字で書いてプレースホルダーで比較対象の値を渡します。
コード
Tag.where("name LIKE ?", "%インド")
結果
app(dev):013> Tag.where("name LIKE ?", "%インド") Tag Load (0.5ms) SELECT "tags".* FROM "tags" WHERE (name LIKE '%インド') /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff77449248 id: 1, created_at: "2025-11-03 00:17:07.271876000 +0000", name: "南インド", position: 1, updated_at: "2025-11-03 00:17:07.271876000 +0000", tag_group_id: 1>]
否定系
notメソッドを使います。
コード
Tag.where.not(name: "南インド")
結果
app(dev):023> Tag.where.not(name: "南インド") Tag Load (11.0ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" != '南インド' /* loading for pp */ LIMIT 11 /*application='App'*/ => [#<Tag:0x0000ffff77463c10 id: 2, created_at: "2025-11-03 00:42:55.770481000 +0000", name: "ビリヤニ", position: 3, updated_at: "2025-11-03 01:57:44.855153000 +0000", tag_group_id: 3>]