データモデルが次のようになっているオンライン書店にいるとしましょう。
新規注文を作成する前に、十分な在庫があることを確認したいので、次のような方法があります
def ensure_enough_in_stock
errors.add(:quantity, "not enough in stock") if quantity > book.stock
end
データベースに保存する前にこのメソッドが呼び出されることを確認するために、検証を使用します。
validate :ensure_enough_in_stock, :on => create
要約すると、注文を作成するときは次のようになります。
- 検証メソッドが呼び出されます
- 新しい注文がデータベースに書き込まれます(検証に合格した場合)
1.と2.の間で、別のプロセス(同時アクセス、別のスレッドなど)が同じ本の在庫属性に変更を加えた場合はどうなりますか?例外は発生しますか?
より一般的には、検証とデータベースへの保存の間に何かが発生した場合にどのように対処しますか?
データベースにも検証を入れるべきだと思いますが、それがパフォーマンスにどのような影響を与えるかはわかりません。このような状況に対処するための賢い方法はありますか?
編集
ここで説明するようにトランザクションをロックすると、株式への書き込みアクセスができなくなりますが、Bookモデルに「public」または「private」の値をとることができる「published」属性もある場合はどうなりますか。プライベートな本を買うことはできません。
しかし、外部プロセスによって株価を変更できるのと同じように、公開されている値も変更できます。この場合、ロックは役に立ちませんね。