概要 & お願い
今回 gem activerecord-import を使って感動した話を書き綴る。
導入部分は bundle insatll
するだけなので省略する。
ご存知の方はスルー&間違っていたら指摘お願いします
activerecord-import ってなに
ActiveRecordを使用してデータを一括挿入するためのライブラリ。
each でぐるぐる回して1件ずつレコード追加更新は負荷がかかるため、バルクインサート/バルクアップデート を使おう。
ここがナイス
- N + 1 対策してくれる
- 以下リンクの通り、
on_duplicate_key_update:
を設定することにより、新規追加か更新かのロジックを意識せずに実装ができる
勘違いしていたこと
- 以下
target_users
を作成際に、新規作成と更新でロジックを変えないといけないのかと思っていた(わかりにくいが before 参照のこと)
before(動作は未検証 )
hoge.rb
target_users = []
# 一括で登録したいユーザー情報
user_lists = [{key: 'hoge', name: 'ほげ'}, {key: 'fuga', name: 'ふが'}, {key: 'piyo', name: 'ぴよ'}]
users = User.all
# 新規作成
if users.blank?
user_lists.each do |user_list|
target_users << User.new(
key: user_list['key'],
name: user_list['name']
)
end
# 更新の場合は
else
user_lists.each do |user_list|
users.each do |user|
next unless user.key == user_list.key
user.name = user_list.name
target_users << user
end
end
end
User.import target_users, on_duplicate_key_update:[:name]
あ”あ”あ”あ”あ”あ”あ”あ”あ”長い長い長い
after
hoge.rb
target_users = []
user_lists = [{key: 'hoge', name: 'ほげ'}, {key: 'fuga', name: 'ふが'}, {key: 'piyo', name: 'ぴよ'}]
user_lists.each do |user_list|
target_users << User.new(
key: user_list['key'],
name: user_list['name']
)
end
User.import target_users, on_duplicate_key_update:[:name]
実はこれだけで新規追加も更新もよしなにしてくれた
きもいきもいと思っていたコードが全部なくなってくれて感動した
! on_duplicate_key_update:
は、MySQL、PostgreSQL(9.5以降)、SQLite(3.24.0以降)で設定がサポートされているが、PostgreSQL は微妙に書き方が違うので注意が必要。
最後に
Rails6でinsert_all、insert_all!、upsert_all追加されたから、activerecord-import は使われなくなってしまうのかな...
雑だけどおわり。