[Rails]insert_allの返り値に注意しないといけないよって話

2024/07/04

Rails

こんにちは。

最近、Railsでinsert_allを使う機会があったのですが、その際に返り値に注意しないといけないことがあったので、その話をします。

insert_allの返り値

insert_allは、その名の通り、複数のレコードを一度に挿入するためのメソッドです。

# 例としてUserモデルがあるとします。
# Userテーブルにはnameカラムとemailカラムがあるとします。

users = [
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' },
  { name: 'Charlie', email: 'charlie@example.com' }
]

result = User.insert_all(users)

# 結果の確認
puts result.inspect

このメソッドの返り値は、ActiveRecord::Resultオブジェクトです。

#<ActiveRecord::Result:0x00007f832d10b8c0
 @columns=["id"],
 @rows=[[1], [2], [3]],
 @hash_rows=[{"id"=>1}, {"id"=>2}, {"id"=>3}],
 @column_types={"id"=>#<ActiveModel::Type::Integer:0x00007f832c3ef508>}
>

このオブジェクトには、挿入されたレコードのIDが含まれています。
逆にいうと、ID以外のカラムの値は含まれていません。

そのため、insert_allの返り値を使って、挿入されたレコードの情報を取得するには、別途クエリを発行する必要があります。

# 例として、挿入されたレコードの情報を取得するためのクエリを発行する
inserted_ids = result.rows.flatten
inserted_users = User.where(id: inserted_ids)

まとめ

insert_allの返り値は、挿入されたレコードのIDのみを含んでいるため、挿入されたレコードの情報を取得するには別途クエリを発行する必要があります。

謎挙動じゃん…と思ってしまいましたが、そういうものだと覚えておくためにも、この記事を書いてみました。

Related Posts

[Rails] 特定の条件でデータを取得する時のサブクエリの書き方

[Rails] 特定の条件でデータを取得する時のサブクエリの書き方

[Rails] ActionCableを活用してSocket通信する

[Rails] ActionCableを活用してSocket通信する