Ruby on Railsトランザクションを設計する5つのヒント


データ完全性問題は、Rails開発者が直面する最も一般的なデータベースの一つです.正しく設計されたトランザクションブロックを許可するほかに、データブロックが部分的に作成または更新されていないことを確認します.
しかし、トランザクションはまた、あなたのアプリケーションを傷つけることができます-あるいは、あなたのデータベース全体を降ろしてください.
この記事はトランザクションを扱うための良いプラクティスのセットを提供します.ヒントはかなり簡単ですが、彼らはあなたのトランザクションの防弾、読みやすく、比較的安全に役立ちます.
飛び込みましょう!

1 .可能な場合にRailsでBangメソッドを使用する


Railsでは、! 何かが間違っているときにエラーが発生するという自信を与えることができます.
例えば、#save メソッドも存在しますsave! バージョン.任意のエラーを発生させたくない場合は、このバージョンをコントローラに使用します.
def create
  user = User.new(user_params)

  if user.save
    # redirect
  else
    render :new
  end
end
上記のアプローチはトランザクションでうまく動作しません.使用によってsave , エラーが発生するとプロセスをロールバックできません.そういうわけで、それはとても重要です! メソッドのバージョン:
ActiveRecord::Base.transaction do
  user = User.create(user_attributes)
  user.memberships.create(membership_attributes)
end
上記では、メンバーシップレコードが作成されていなくてもトランザクションが成功し、データベース内のデータ構造が台無しになります.
次のバージョンを使用すると、トランザクションはActiveRecord::RecordNotSaved エラー
ActiveRecord::Base.transaction do
  user = User.create!(user_attributes)
  user.memberships.create!(membership_attributes)
end

2 .適切にRailsトランザクションでエラーを処理する


トランザクションのエラーに関しては、あなたが尊重すべき規則がいくつかあります.これらの規則に従うことによって、他の開発者やデバッグするのが困難な奇妙な動作の間で混乱を起こさないコードを読みやすく、うまく動作させることができます.

からの救助をしないでください

ActiveRecord::StatementInvalid データベースレベルの何かが間違っているときに発生する特別なエラーです.このエラーから決して救出しないでください.データベースクエリで何かがうまくいかないときは、常に明示的に通知する必要があります.
次のコードを避けます.
def perform_action(...)
  User.transaction do
    # perform transaction
  end
rescue ActiveRecord::StatementInvalid
  # do something
end

正しいレベルでレスキューを使用してください


次のレベルでレスキューを使用すると、エラーが発生します.
User.transaction do
  user.perform_action!
  user.perform_another_action!
rescue SomeError
  # rescue
end
エラーが発生したためトランザクションはロールバックしません.エラーを送出し、トランザクションブロックの外でキャッチします.
def some_method
  User.transaction do
    user.perform_action!
    user.perform_another_action!
  end
rescue SomeError
  # rescue
end
上記のアプローチでは、トランザクションがエラーの場合にロールバックし、エラーをキャッチします.トランザクション動作を上書きせずにトランザクション内で発生したエラーをキャッチする正しい方法です.

汎用エラーをキャッチしない


一般的なエラーを避けるのを避けるべきですStandardError or ArgumentError . これは読みやすく、簡単に検証可能なコードの一般的な規則のようですが、言及する価値があります.
これらのエラーを捕捉すると、コードの他の場所がエラーを引き起こす可能性がありますので、デバッグを難しくすることができます.これは必ずしもあなたがそれらを救出する場所に関連していないあなたのアプリケーションでいくつかの深刻な問題を沈黙する可能性があります.

ActiveRecordのデフォルトのロールバックエラーを賢明に使用します


ActiveRecordは、サイレントロールバックを行うトランザクション内で使用できる特定のエラークラスを提供します.を上げることによってトランザクションをロールバックしますActiveRecord::Rollback エラーですが、エラーは発生しません.この行動を念頭に置いて賢明に使用します.

3 . Railsでトランザクションを使用するのを避けるために


何かのように、コードのトランザクションをオーバーユースしてはいけません.たとえば、一般的な間違いは、1つのクエリだけをあなたのトランザクションにラップすることです.これは、クエリが成功しない場合は、何もロールバックする必要はないので、意味をなさない.
別の一般的な間違いは、トランザクションにデータベースコールに関連しないコードをラップすることです.ブロック内のコードが実行されない限り、トランザクションは接続を保持するので、そのようなアプローチを避ける必要があります.可能ならば、あなたのデータベースだけを呼ぶために、ブロックの中でコードを制限してください.

4 .取引の不利益を理解する


トランザクションは、データベース内のデータの整合性を維持するのに役立ちますが、また、それらの欠点を認識する必要があります.たとえば、トランザクションブロックにラップされたクエリは、単一のクエリよりも多くのDBリソースを取得します.
トランザクションを使用する別の欠点は、より複雑なコードにつながることです.トランザクションを誤って使用するときにコードを読みにくくすることができます.

トランザクションのブロックを正しいコンテキストで使用する


クラスが継承するときに、トランザクションメソッドを使用できますActiveRecord クラス.これは、使用するバージョンが重要ではないことを意味しません.それは機能的な観点から問題ではないかもしれませんが、それはあなたのコードを読みやすくすることに関して重要です.
つの一般的なバージョンはトランザクションメソッドを使用します.
ActiveRecord::Base.transaction
Model.transaction
Model.new.transaction
ブロック内のクラスで多くのモデルを使用してインスタンスメソッドの呼び出しをミックスする場合は、ActiveRecord::Base.transaction :
ActiveRecord::Base.transaction do
  attributes = user.prepare_attributes(account)
  membership = Membership.create(attributes)
  LogService.log_creation(user, membership)
end
指定したモデルに属するコードを扱う場合は、クラスのトランザクションメソッドを呼び出します.
User.transaction do
  user = User.create!(attributes)
  user.log_activity(creation)
end
モデルインスタンスで操作すると、インスタンスレベルでトランザクションメソッドを呼び出すことができます.
user.transaction do
  user.make_transaction(attributes)
  user.log_activity(transaction)
end
もちろん、これらの規則は公式ではありません.彼らはコードをより読みやすくするための提案です.

次の手順:Ruby on Railsプロジェクトのレビュートランザクション


Ruby on Railsでのトランザクションの役に立つヒントを見つけました.
我々は、データの整合性を改善し、あなたのプロセスが驚くべき副作用なしで実行することを保証するために適切にRailsトランザクションを設計することの重要性をカバーしました.
ただし、適切なエラー処理ポリシーは、トランザクションを使用するときにのみ有益ではありません-それはまた、あなたの全体のコードベースを改善します.あなたのコードがいくつかのエラーをスローすることを期待していることを覚えておいてください.
エラーを避けるためにRuby on Railsプロジェクトデザインのトランザクションを確認するのに最適な時間です.あなたのアプリケーションをより安定させるためにあなたのデータベースと効率的で信頼性の高いコミュニケーションのためのデザイン.
ハッピーコーディング!
P . S .あなたが彼らがプレスから降りるとすぐに、ルビー魔法のポストを読みたいならば.subscribe to our Ruby Magic newsletter and never miss a single post !