トランザクション処理

実装

同時に保存すべき項目があったのでトランザクション処理にしてみた。

def create
  Teacher.transaction do
    @teacher = Teacher.new(teacher_params)
    @school = @teacher.build_school(school_params)
    @teacher.save!
    @school.save!
  end
  reset_session
  session[:teacher] = @teacher.id
  redirect_to @teacher
  rescue => e
    render plain: e.message
end

構文

transactionメソッドはモデルクラス経由で呼び出す。

transactionのブロック内にDBにアクセスする処理(例外が起こりうる処理)を書く。

ブロック内の処理が成功したら実行したい処理をブロックの後に続けて書く。

最後に rescue => e に続けてブロック内の例外が発生した場合の処理を書く。

ポイント

  • ブロック内のDBへの保存の処理はsaveでなく、save! にする。

    save の返り値は true/false だけど、save! の場合は失敗すると例外が返る。トランザクション処理のロールバックは例外がトリガーになるので成功以外の場合は例外になるようにする必要がある。

  • 例外処理を用意する

    ruby では bigin ~ rescue ~ end で例外を捕捉する構文があるけどここでも同じことをしている。

    rescue => e で 変数e に例外オブジェクトを格納している。

    例外が起きた時は e.message が rendering される。

追記

今回のパターンだと accepts_nested_attributes_for を使った方が良さそうです。下記のページでまとめました。

accepts_nested_attributes_forの使い方