やりたいこと
csvファイルをアップロードして、必要なデータを抽出し、DBに保存
データが重複している際は既存データにアップロードしたデータを上書きする
前提条件
rails7系
DB作成済み
実装手順
① gemを追加
gem 'roo'
Gemfileにcsvを読み込むためのgemを追加し、bundle installする。
② ルーティングの設定
config/routes.rb
get 'data_upload' => 'data_upload#index'
post 'data_upload' => 'data_upload#create'
③ 標準ライブラリを追加
config/application.rb
require 'csv'
④ viewにアップロード用のformを作成
Rails5.1より導入されたform_withを使ってアップロード用のフォームを作成します。
指定したpathに対してpostリクエストを投げます。
app/views/data_upload/index.html.erb
<%= form_with url: data_upload_path do |f| %>
<%= f.file_field(:upload_file) %>
<%= submit_tag "インポートする" %>
<% end %>
⑤ controllerにactionを追加
app/controllers/data_upload_controller.rb
class DataUploadController < ApplicationController
# get => data_upload
def index
upload_file = params[:upload_file]
end
# post => data_upload
def create
if params[:upload_file].present?
upload_file = params[:upload_file].tempfile
# ファイルの内容によってはEncodingErrorが出ますので適宜調整してください
CSV.foreach(upload_file.path, headers: true, encoding: 'cp932') do |row|
# recruiting_idがあった場合はレコードを呼び出す、ない場合は新しく作成
recruiting = Recruiting.find_by(recruiting_id: row["求人ID"]) || Recruiting.new
recruiting.attributes = convert_csv_to_hash(row)
recruiting.save
end
redirect_to root_path
end
end
private
# csvの欲しいデータがある列とDBのカラムを指定してデータを入れます。
def convert_csv_to_hash(row)
params = {
recruiting_id: row['求人ID'],
title: row['求人名(募集職種)'],
salary: row['給与'],
office_hours: row['勤務時間'],
skills: row['必須スキル'],
place: row['勤務地']
}
return params
end
end
参考文献