LoginSignup
178
164

More than 5 years have passed since last update.

【Rails】絶対に抑えたいTransactionのポイントを三つにまとめてみた。【必須】

Last updated at Posted at 2015-03-14

※Rails公式ドキュメントから、平易な日本語でポイントとプラスαまとめています。(公式ドキュメント: http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)

Transaction - 失敗→Save前

Transactionは、複数のSQL文を囲んで、そのSQLそれぞれが成功した場合のみに、すべてのSQLの変更を反映するよというもの。典型的な例は銀行口座の例で、片方の口座からの引き落としに成功した時のみ、もう片方の口座にお金がプラスされるよ、みたいなね。
こんな感じで、Transactionはデータベースの統一性をプログラムやdbのエラーから守るもの。一緒に処理されなきゃいけない処理の塊を持ってる時は絶対に使わなきゃいけない。

例えば、以下の例ではkevinの口座からの引き落としに成功した時のみ、kenに100depositeが行くようになってる。例外(error)が時発生した場合にはROLLBACKが発生し、今までの処理をTransaction前の状態に戻してくれる。

ActiveRecord::Base.transaction do
  kevin.withdrawal(100)
  ken.deposit(100)
end

1クラスのTransactionで複数まとめる

TransactionはActiveRecordのクラスメソッドなので、どのActiveRecordのクラスからも同じものがTransactionが呼び出される。だからTransactionのブロック内のrecordのインスタンスが必ずしもそのtransactionのクラスに属す必要はない。

以下の例では、BalanceクラスとAccountクラスがブロック内にあるが、AccountのTransActionのみで囲われてる。もちろんこれでおk。

Account.transaction do
  balance.save!
  account.save!
end

ちなみに、クラスメソッドで使うことが多い気はするが、インスタンスメソッドとしてインタンスからアクセスすることもできる。

balance.transaction do
  balance.save!
  account.save!
end

複数databaseにまたがってtransaction監視はできない

これまでの例で、複数レコードに対して一つのtransactionでカバーできることを述べてきたが、それはdatabaseを同一のものを使っている条件下での話である。
もし、レコードごとに別のdatabaseを使っている場合、そのdatabaseをまたがる処理に関して一つのclassのtransactionではカバーしきれない。でもそれじゃ困るので、そういう時は以下のように書きましょう。

StudentクラスとCourseクラスで異なるdbを使用してる時。
両方をtransactionで囲ってあげましょう。

Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end

両方のクラスのtransactionで囲まなきゃいけないのはかっこわるいけど、これで両方のdbに対してtransaction保証される。公式ドキュメントにこうしろと書いてあるので、おそらくこれ以上の策は現状のところないのでしょう。

ありがちなミスに注意

transactionでこのrecordの処理ミスったらROLLBACK発生させたい!ってやつにはsave!destroy!みたいにビックリマーク!をつけることをお忘れなく!!transactionはerrorに反応してROLLBACK起こすので!

some_record.save # true/falseを返す
some_record.save! # 失敗時にerrorを返す

transactionで囲んだぜって一安心した時にこちらきちんと見直しておきましょう!

以上、railsを書く上で是っていに抑えなきゃいけないtransactionのポイント3つでした。callbackなど、もっと深堀したい方は以下など参照。


参考
- http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

178
164
2

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
178
164