LoginSignup
55
40

More than 5 years have passed since last update.

ActiveRecord::Base.transactionで囲うタイミング

Last updated at Posted at 2016-06-20

分けることができない処理

ActiveRecord::Base.transaction do
end

で囲うのはもちろんとして、

Railsは

ActiveRecord::Base.transaction do
end

で囲っていなくても、DBをコミットしたりロールバックする処理が自動で走るのだが、
後から見て自動で走るポイントがわかりずらいので、明示的に

ActiveRecord::Base.transaction do
end

で囲ったほうがよいかも。

なので、下記のような形にすることがあるかな。

def hoge
  ActiveRecord::Base.transaction do
    foo.save!
  end

  ActiveRecord::Base.transaction do
    bar.save!
  end
rescue ActiveRecord::RecordInvalid
  # エラーハンドリング
end

でも、本当は、明示的に囲うのではなく、分けてもよい処理なら

def hoge
  unless foo.save
    # エラーハンドリング
    return
  end

  unless bar.save
    # エラーハンドリング
    return
  end
end

もありかな。 上記は別のオブジェクトへのsaveが2回以上でてくる例なので、
トランザクションで囲ってrescue ActiveRecord::RecordInvalidでエラーハンドリングするのか、
unlessでエラーハンドリングするのか悩みどころだが、saveが1個のみなら、

def hoge
  unless foo.save
    # エラーハンドリング
    return
  end
end

unless形1択で、

def hoge
  ActiveRecord::Base.transaction do
    foo.save!
  end
rescue ActiveRecord::RecordInvalid
  # エラーハンドリング
end

とはしないのが普通かな?

eachとかで何回も保存するときは、要件的に分けられない処理と考えられることが多いので、

def hoge
  ActiveRecord::Base.transaction do
    foos.each do|foo|
      foo.save!
    end
  end
rescue ActiveRecord::RecordInvalid
  # エラーハンドリング
end

の形になることが多い気がする。

んー、後からみて自動で走るポイントがわかりずらいと、始めに書いたが、

おそらく、savesave!を何も考えずに書けば、都度コミットが走って、save!のときはロールバックも走るのだと推測している。

55
40
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
55
40