Railsのinsert_allで少し詰まった話

Rails6から追加されたinsert_allをつかってて、少し詰まったのでメモ程度に残しとく。

insert_allはデータを一括で登録する際に使用でき、
ハッシュを渡せば簡単にバルクインサート(DBに入れたいデータをまとめて指定できる)ができるメソッドです。

今までnewでいちいち保存したい値をインサートしていたので、必要なSQLクエリが1つになるからめちゃいいやんって思いながら使っていましたが、いくつか注意点があるので、それをしらないとハマります。以下に注意点をまとめます。

  • created_atとupdated_atを明示的に指定しないとエラーになる。
  • コールバックやモデルで指定しているバリデーションが効かない。
  • on_duplicateがskipになっているので、重複したデータが入力されている場合、エラーを出さずにスキップされる。

上記の注意事項の中にある3つ目注意点の部分が私が少しハマったところです・・。
insert_allのメソッドを見に行くと、on_duplicate: :skipとなっているので、
重複したものはエラー出さずにskipされることを知りませんでした・・悲しみ

      def insert_all(attributes, returning: nil, unique_by: nil)
        InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by).execute
      end

重複したらエラーを出して欲しい!!と思って、insert_allが書かれているファイルの中を見ていると、insert_all!というものが・・
中身を見てみると、on_duplicate: :raiseとなっていたので、
実行してみると、重複したものをインサートしたらエラーが🤗

def insert_all!(attributes, returning: nil) InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning).execute end

ちゃんとrubyのコードちゃんと読んで行かないとなぁと思った次第・・。

コメント

タイトルとURLをコピーしました