Rails での例外処理
Rails での例外処理
Rails
での例外処理について簡単に残しておきます。
# lib/csv_reader.rb
module CsvReader
require 'csv'
def import_user(csv_path)
read_csv = CSV.read(csv_path, headers: true)
ActiveRecord::Base.transaction do
read_csv.each do |csv|
user = User.find_or_initialize_by(id: csv['ID'])
user.update!(user_attr(csv))
end
end
true
rescue ActiveRecord::RecordInvalid => e
error_messages = e.record.errors.full_messages.map { |error| "ID: #{e.record.id} の #{error}" }
Rails.logger.debug error_messages
error_messages
end
def user_attr(csv)
{
id: csv['ID'],
first_name: csv['名前'],
last_name: csv['苗字'],
age: csv['年齢']
}
end
end
find_or_initialize_by
find_or_initialize_by
は、引数の条件に該当するデータを探し、
あれば find_by(引数)
、なければ new(引数)
する。
find_or_create_by
は、引数の条件に該当するデータを探し、 あればfind_by(引数)
、なければcreate(引数)
する。
update!
update!
のように、 update
に !
をつけることによって、
update
できなかったときに、例外を発生させることができます。
ActiveRecord::Base.transaction
ActiveRecord::Base.transaction do ~ end
で囲まれた部分で例外が起きると、
transaction
で囲まれた部分でロールバック(処理が行われる前の状態に戻る処理)が走ります。
ActiveRecord::RecordInvlalid
バリデーションに引っかかった時、起きるエラーです。
例外を発生させたときの情報
ActiveRecord
の例外を発生させたときのインスタンスの情報を e.record
で取れます。
エラーメッセージは e.record.errors.full_messages
で取れます。
UsersController で、CsvReader.import_user を呼ぶ
# app/controllers/users_controller.rb
# frozen_string_literal: true
class UsersController < ApplicationController
...
def import
csv_file = params[:csv_file]
if csv_file.present?
@user = CsvReader.import_user(csv_file.path)
if @user == true
flash[:success] = 'インポートに成功しました'
else
flash[:danger] = ['インポートに失敗しました', @user].flatten
end
else
flash[:danger] = 'ファイルが選択されていません'
end
redirect_to new_user_path
end
end
例外を発生させることができるもの
save!
create!
update!