私のモデルには次のコードがあります。 2人が同時にレコードを更新する場合、2つのState
のオブジェクトがdefault: true
に設定されてしまう可能性があるため、Rails 4モデルで競合状態を修正してテストする方法
class State < ActiveRecord::Base
def make_default!
State.update_all(default: false)
update!(default: true)
end
end
:誰かが正しくmake_default!
方法が競合状態を引き起こす可能性があることを指摘しました。
class State < ActiveRecord::Base
def make_default!
# Prevent race condition using database-level locks.
State.transaction do
State.where.not(id: id).lock(true).update_all(default: false)
State.where(id: id).lock(true).first.update!(default: true)
end
end
end
誰かが、これは他の潜在的なバグを引き起こす可能性があることを指摘しました。 ロックを実装する最良の方法と、モデルスペック(RSpecを使用して)をテストする方法について知りたいですか?
何か助けがありがとう:)ありがとう!
私は実際にトランザクションでそれをラップするだけで、実際には十分であり、ロックは必要ありません。あなたはそれを実行して、update_allとアップデートの間に大きなスリープを入れ、それを使わずに別のアップデートを実行し、何が起こるかを見てテストすることができます。私は最後のものが勝つはずだと思うし、デフォルトが真でなければならない。また、複数のデフォルトがtrueであることを受け入れることもできます。デフォルトを検索すると、常に最新のものを取ります(updated_atタイムスタンプ付き)。 – jrochkind