fumi blog

【Ruby on Rails】中級者なら押さえておきたいTransactionについて

「Ruby on Railsで仕事を得るために実務に使える知識が欲しい」

「Progateで学んだ知識からさらにもう一歩ステップアップしたい」

本記事では中級者になるために必ず押さえておきたい「Transaction (トランザクション)」について解説します。

Transactionとは


Transactionとは「ある範囲を1セットの処理とし, どこかで処理が失敗したら全ての処理を巻き戻す」機能です。

具体的な書き方を見てみましょう。

ActiveRecord::Base.transaction do
  # 処理の内容
end


ActiveRecord::Base.transaction doendの間に1セットにしたい処理を書いていきます。

これだけだと「どういう場面でつかうの...?」という疑問が出てきますね。
次から詳しく解説していきます。

具体的な使い道

Transaction処理を書いていない場合の失敗例


ではいつ「全ての処理を巻き戻さなくてはならない」シーンが出てくるのでしょうか?

今回は、銀行のシステムを例に考えていきます。

[前提]
(1) 口座のモデル名はAccount,預金額のカラム名はdeposit

ここで「Aさんの口座からBさんの口座に送金する」例を考えてみましょう。
まずは2人の預金額をみてみます。

account_a = Account.find_by(user_id: 'id_a')
account_b = Account.find_by(user_id: 'id_b')

account_a_deposit = account_a.depsit # Aさんの元々の預金額
account_b_deposit = account_b.depsit # Bさんの元々の預金額

p "Aさんの預金額は#{account_a_deposit}円, Bさんの預金額は#{account_b_deposit}円 です"


[実行結果]

Aさんの預金額は40000円, Bさんの預金額は40000円 です


2人とも預金額は40,000円のようです。
ではここから送金の処理を書いていきます。今回は20000円を送金してみましょう。

remittance = 20000 # 送金額

account_a.update!(deposit: account_a_deposit - remittance )
account_b.update!(deposit: account_a_deposit + remittance )


[実行結果]

ActiveRecord::RecordInvalid: Validation failed: 預金額は50000円までです


実行した結果、処理が失敗してしまいました。この銀行では預金額は50000円以上にはできないようです。 (変な銀行ですね)


ここで、再度Aさんの口座とBさんの口座の預金額を見てみましょう。

[実行結果]

Aさんの預金額は20000円, Bさんの預金額は40000円 です


なんと、Aさんの口座からお金が減っています!! これは送金失敗にもかかわらず、Aさんの預金口座の減額処理が巻き戻っていないからですね。

Transaction処理を使った例


ではこのコードを正しく書き直してみましょう。
「Aさんの口座からの減額処理」と「Bさんの口座からの減額処理」は1セットにならないといけないので、これをTransactionで囲います。

ActiveRecord::Base.transaction do
  remittance = 20000 # 送金額

  # 以下の処理は1まとめ
  account_a.update!(deposit: account_a_deposit - remittance )
  account_b.update!(deposit: account_a_deposit + remittance )
end


[実行結果]

ActiveRecord::RecordInvalid: Validation failed: 預金額は50000円までです


実行すると同じように処理が失敗します。(預金額の上限は変えていないため)
さて、Aさんの口座とBさんの口座の預金額を見てみましょう。

[実行結果]

Aさんの預金額は40000円, Bさんの預金額は40000円 です


2人ともお金が減っていないことが確認できました 🎉

まとめ

本記事では中級者以上なら必ず押さえておきたいTransactionについて解説しました!
安全なシステムを作るために、必ず押さえておきましょう。