Active Recordでトランザクション処理
RubyのActive Recordでトランザクションを利用する場合の基本的なコードです。
別の言語に手を出したりするとすぐに忘れるのでメモしておきます。
コード
以下は、ある記事(tbl_articles)に対して1件のコメント(tbl_comments)が送信された際に、コメントの登録とコメント件数を更新する処理の例になります。
begin
ActiveRecord::Base.transaction do
# 更新対象のデータを取得してロック(下記のような悲観的ロックはMySQLとPostgresのみ可能)
article = tblArticles.find(1)
article.lock!
# コメント登録
comment = tblComments.new
comment.content = 'コメントの内容'
comment.save!
# コメント件数の更新
article.comment_count = article.comment_count + 1
article.save!
# 明示的にロールバックさせる場合は「raise」を使用する
raise 'ロールバックさせる'
end
# コミット
rescue => ex
# ロールバック
end
処理の内容によっては5行目のロック処理は必要ありません。
コミットやロールバックは自動的に実行されます。明示的にロールバックさせたい場合は、17行目のようにトランザクション処理内で例外を発生させます。
データを保存する際に「save!」ではなく「save」を使用すると、保存できない場合に「例外の発生」ではなく「false」が戻り値で帰ってくるだけなので、理由がなければ「save!」を利用した方がいいです。