CSVを使った一括インポート機能を作成する際に確認するポイント

先日、CSVファイルを使ったデータの一括インポート機能を作成する機会がありました。 一連の実装を振り返ると、気にすることや決めるべきことが色々あるなーと思ったので、メモしておきます。

異常系への対応

✅ ファイルの形式が間違っているケースの対応をする

  • HTMLのaccept属性で制限するのとは別に、csvファイル以外がアップロードされた場合のサーバーサイドでの対策が必要です
  • 例えばrubycsvライブラリでは、CSV::MalformedCSVErrorが発生するので、それをrescueする処理を書いておくのが1つの方法です
begin 
  CSV.parse(...)
rescue CSV::MalformedCSVError
  flash.now[:alert] = 'CSVファイルをアップロードしてください'
end

✅ インポートできるデータの上限数を決めておく

  • 無制限にしてしまうと、サーバーの圧迫などを招く可能性があります
  • したがって、例えば以下の要素を検討し、適切な上限を設定する必要があります
    • ユーザーが不便に感じない上限数
    • パフォーマンス上問題ない上限数
    • プレビュー画面で表示した際にユーザーが見やすい上限数

✅ インポートされたデータが0件のケースの対応をする

  • 意外と忘れがちなのが、ユーザーがテンプレートをそのままアップロードしてしまった場合など、登録するべきデータが0件の場合です。
  • 何も対策していないと、バリデーションなどを通過してしまい、保存処理時に500エラーが起きる、といったこともあり得るので、0件の場合はきちんとエラーを返して保存処理に進ませない対策が必要です

ユーザービリティ関係の対応

✅ 何を記入したらいいかわからないようになっていないか

  • 電話やメールアドレスなどは明らかですが、DBの制約上、複数の選択肢から選んで欲しい場合(例えば「職種」など)などもあります
  • 何も説明がないと、自由記述とユーザーは思ってしまうので、何かしらの対策が必要です
  • 選択肢が少ない場合は、行のところに「職種(エンジニア or その他 で入力)」など書いておけばいいですが、選択肢が多い場合は非常に悩ましいです

✅ (記入例行がある場合)記入例行を削除するユーザーに対応できているか

  • 「何を記入したらいいかわからないようになっていないか」とも関連しますが、例えばテンプレートに記入例行を設けておく場合などは取り扱いに注意が必要です
  • 機械的に「上から1行は記入例だから無視」としてしまうと、記入例に上書き・削除して記載するユーザがいた時に、最悪保存できたつもりが保存できていない、という状況に陥り、不具合報告につながる可能性があります
  • 記入例行が記入例と違えば登録処理の対象に入れる、という仕様もありますが、仕様が複雑になったり、ユーザーのわかりづらさにつながるので、個人的には、可能な限り記入例行を作らずにテンプレートは作成できると良いのかなーと思っています

✅ バックグラウンド処理を使わずに実装できないか

  • 一括インポートは当然処理時間が長くなりがちのため、バックグラウンド処理が1つの選択肢となります
  • ただし、バックグラウンド処理をすると、考えるとが増えるので、できればbulk insertなどを有効活用しながら、同期処理で行うのが良いと思います
    • この点については、morihirokさんのKaigi on Rails 2025での発表が非常に参考になります

speakerdeck.com