LoginSignup
2
1

【Rails】ActiveRecord::Base.transactionについて

Last updated at Posted at 2024-02-06

どうもこんにちは。

今回はRailsでDB操作をする時に便利なActiveRecord::Base.transactionについてメモします。

トランザクションって何?

トランザクションをネットで検索すると、「ここからここまでワンセット」な処理単位が「トランザクション」 というわかりやすく説明してありました。

まさにその通りです。

この考えをDBの操作でも活用しているものがRailsにおけるトランザクションです。

使い方

基本的に、データの登録、更新、削除する時のメソッドとして使われます。

ActiveRecord::Base.transaction do ... endブロックでsaveメソッドやupdateメソッド処理の箇所を囲うようにして使用します。

def create
    ## データを登録するためのデータを作成
    user = User.find(params[:id])
    profile = Profile.new(user_id: user.id, hobby: '野球をすること', favorite_food: 'カレーライス')
    post = Post.new(user_id: user.id, title: '自己紹介', content: '今日は野球の試合に行ってきました。')

    ## saveメソッドやupdateメソッドをtransactionブロックで囲う
    ActiveRecord::Base.transaction do
        user.save
        profile.save
        post.save
    end
    redirect_to posts_path
end

transactionブロックの中でエラーが発生しなければ何事もありませんが、どこかでエラーが起きたとします。

今回はPostモデルに以下のバリデーションが定義されているとして、インスタンスのtitleをnilとしましょう。

validates :title, presence: true
def create
    ## データを登録するためのデータを作成
    user = User.find(params[:id])
    profile = Profile.new(user_id: user.id, hobby: '野球をすること', favorite_food: 'カレーライス')
    ## エラーを発生させるためにtitleをnilとします
    post = Post.new(user_id: user.id, title: nil, content: '今日は野球の試合に行ってきました。')

    ## saveメソッドやupdateメソッドをtransactionブロックで囲う
    ActiveRecord::Base.transaction do
        user.save
        profile.save
        post.save
    end
    redirect_to posts_path
end

そうすると、post.saveのところでエラーが発生するはずです。

transactionブロックで囲っていないと、userとprofileはデータベースに保存されるがpostが保存されないという状態になります。アプリケーションの要件によってはそれは良くない場合があります。

ただ、今回のコードではtransactionブロックで囲っているので、一度保存されたuserとprofileのデータはロールバックされ、どのデータも保存されていない状態になります。

これによってDBの整合性が保たれます。

transactionブロックを使用していると、開発も楽なのでおすすめです。

以上

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1