この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
ActiveRecordのwhereの挙動が同じだったり違ったりするのでメモ
例として使うテーブル
# 投稿
class Post < ActiveRecord::Base
has_many :comments
end
# コメント
class Comment < ActiveRecord::Base
belongs_to :post
end
1.whereにhash
Post.where(title: 'タイトル').to_sql
SELECT posts.* FROM posts WHERE posts.name = 'タイトル' ORDER BY posts.id ASC
default_scopeがつく
2.whereにArray
Post.where(['title = ?', 'タイトル']).to_sql
SELECT posts.* FROM posts WHERE (name = 'タイトル') ORDER BY posts.id ASC
whereの条件にテーブル名がつかない。()がつく。
3.Arrayの部分にテーブル名を入れる
Post.where(['posts.title = ?', 'タイトル']).to_sql
SELECT posts.* FROM posts WHERE (posts.name = 'タイトル') ORDER BY posts.id ASC
テーブル名がつく。()がつく。
4.whereに空配列
Post.where([]).to_sql
SELECT posts.* FROM posts ORDER BY posts.id ASC
where条件なし。全件取得。default_scopeがつく。
5.whereに空配列
Post.where([[]]).to_sql
SELECT posts.* FROM posts WHERE () ORDER BY posts.id ASC
全件取得。where ()がつく。
6.whereにString
Post.where("posts.title = 'タイトル'").to_sql
SELECT posts.* FROM posts WHERE (posts.name = 'タイトル') ORDER BY posts.id ASC
Arrayのときとかわらない。
7.whereに空文字
Post.where('').to_sql
SELECT posts.* FROM posts ORDER BY posts.id ASC
where条件なし。全件取得。default_scopeがつく。
8.whereにtrue
Post.where(true).to_sql
RuntimeError: unsupported: TrueClass
例外。
9.whereに’true’
Post.where('true').to_sql
SELECT posts.* FROM posts WHERE (true) ORDER BY posts.id ASC
全件取得。
10.whereに’false’
Post.where('false').to_sql
SELECT posts.* FROM posts WHERE (false) ORDER BY posts.id ASC
0件。
11.joinしてwhereにhash
Post.joins(:comments).where(title: 'タイトル', comments: {title: 'コメントのタイトル'}).to_sql
SELECT posts.* FROM posts INNER JOIN comments ON comments.color_id = posts.id WHERE posts.title = 'タイトル' AND comments.title = 'コメントのタイトル' ORDER BY posts.id ASC
Postのdefault_scopeがつく。
12.joinしてmerge
Post.joins(:comments).where(title: 'タイトル').merge(Comment.where(title: 'コメントのタイトル')).to_sql
SELECT posts.* FROM posts INNER JOIN comments ON comments.color_id = posts.id WHERE posts.title = 'タイトル' AND comments.title = 'コメントのタイトル' ORDER BY posts.id ASC, comments.id ASC
PostとCommentのdefault_scopeつく。