railsでcsvファイルを取り込む際に、トランザクションを使いたいです。(エラー発生時は全ての行の変更を取り消し、元の画面に戻ってエラー表示させる)
railsでwebアプリケーションを作成しています。そこでcsvファイルの取り込み機能の実装を現在しています。csv取り込みはできたのですが、csvファイルを取り込む際に、トランザクションを使いたいです。(エラー発生時は全ての変更を取り消し、元の画面に戻ってエラー表示させたいです) しかし、いまいち実装方法がわからなかったため、質問させていただきました。
$ rails -v
5.0.0
controller/costs_controller.rb
def import
if params[:csv_file].blank?
redirect_to action: 'index', error: '読み込むCSVを選択してください'
elsif File.extname(params[:csv_file].original_filename) != ".csv"
redirect_to action: 'index', notice: 'csvファイルのみ読み込み可能です'
else
num = Cost.import_by_csv(params[:csv_file])
redirect_to action: 'index', notice: "#{ num.to_s }件のデータ情報を追加/更新しました"
end
end
model/cost.rb
require 'csv'
class Cost < ActiveRecord::Base
#csvファイルの内容をDBに登録する
def self.import_by_csv(file)
imported_num = 0
open(file.path, 'r:cp932:utf-8', undef: :replace) do |f|
csv = CSV.new(f, :headers => :first_row)
caches = Cost.all.index_by(&:code)
csv.each do |row|
next if row.header_row?
#CSVの行情報をHASHに変換
table = Hash[[row.headers, row.fields].transpose]
#登録済みデータ情報
#登録されてなければ作成
cost = caches[table['code']]
if cost.nil?
cost = new
end
#データ情報更新
cost.attributes = table.slice(*table.except(:created_at, :updated_at).keys)
#バリデーションokの場合は保存
if cost.valid?
cost.save!
imported_num += 1
end
end
end
#更新件数を返す
imported_num
end
end
views/costs/index.html.slim
= form_tag import_costs_path, method: :post, multipart: true do
= file_field_tag :csv_file
= submit_tag 'CSV読み込み'
route.rb
Rails.application.routes.draw do
resources :costs do
post :import, on: :collection
end
現状のコードは以上になります。トランザクションに関して調べたところ、
Cost.transaction do
------ コード -----
end
のようにトランザクションを実装するとあるのですが、どこのファイルにどのように記すのかがわかっていません....
大変お手数なのですが、ご教示頂けますと幸いです。。
何卒宜しくお願いします。