Active Record クエリインターフェイス | Rails ガイド
Model.find(options)という操作を要約すると以下のようになります。 与えられたオプションを同等のSQLクエリに変換します。 SQLクエリを発行し、該当する結果をデータベースから取り出します。 得られた結果を行ごとに同等のRubyオブジェクトとしてインスタンス化します。 指定されていれば、after_findを実行し、続いてafter_initializeコールバックを実行します。
find
idで検索 - 見つからない場合、ActiveRecord::RecordNotFound例外が発生
Client.find(10)
SELECT * FROM clients WHERE (clients.id = 10) LIMIT 1
複数のキーを同時に検索
1つでもマッチしないと、ActiveRecord::RecordNotFound例外が発生
Client.find([1, 10])
SELECT * FROM clients WHERE (clients.id IN (1,10))
find のオプション
Rails4で廃止 - 検索条件を指定したい場合は、#where を使うこと
take,first,last
- レコードを1つ取り出す
- 引数でn個取り出せる
- #first は主キーで昇順ソートする
- #last は主キーで降順ソートする
レコードがない場合
- #take : ActiveRecord::RecordNotFound
- #first, #last : nil
- #first!, #last! : ActiveRecord::RecordNotFound
Client.take Client.first Client.last
SELECT * FROM clients LIMIT 1 SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1 SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
LIMITの数を指定する
Client.take(10)
find_by
条件を満たす最初のレコードを返す
Client.find_by(first_name: 'Lifo') Client.where(first_name: 'Lifo').take # 同じ意味
SELECT * FROM clients WHERE (clients.first_name = 'Lifo') LIMIT 1
レコードがない場合
- #find_by : nil
- #find_by! : ActiveRecord::RecordNotFound
複数のオブジェクトをバッチで取り出す
User.all.each
とかやると全レコードをまとめてメモリに入れるので死ぬ
通常やり方は2通り
- #find_each
- #find_in_batches
#find_each
レコードを分割して取得(デフォルト1000)し、1レコードづつ処理をする
User.find_each do |user| NewsMailer.weekly(user).deliver_now end
SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1000 SELECT "users".* FROM "users" WHERE ("users"."id" > 1000) ORDER BY "users"."id" ASC LIMIT 1000 ...
#where 等にチェインもできる
User.where(weekly_subscriber: true).find_each do |user|
オプション
- :start : 処理開始位置
- :batch_size : 1回の処理で実行するレコード数
#find_in_batches
レコードを分割して取得(デフォルト1000)し、配列に渡して処理をする
Invoice.find_in_batches do |invoices| export.add_invoices(invoices) end