4

データモデルが次のようになっているオンライン書店にいるとしましょう。

ここに画像の説明を入力してください

新規注文を作成する前に、十分な在庫があることを確認したいので、次のような方法があります

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. 新しい注文がデータベースに書き込まれます(検証に合格した場合)

1.と2.の間で、別のプロセス(同時アクセス、別のスレッドなど)が同じ本の在庫属性に変更を加えた場合はどうなりますか?例外は発生しますか?

より一般的には、検証とデータベースへの保存の間に何かが発生した場合にどのように対処しますか?

データベースにも検証を入れるべきだと思いますが、それがパフォーマンスにどのような影響を与えるかはわかりません。このような状況に対処するための賢い方法はありますか?

編集

ここで説明するようにトランザクションをロックすると、株式への書き込みアクセスができなくなりますが、Bookモデルに「public」または「private」の値をとることができる「published」属性もある場合はどうなりますか。プライベートな本を買うことはできません。

しかし、外部プロセスによって株価を変更できるのと同じように、公開されている値も変更できます。この場合、ロックは役に立ちませんね。

ここに画像の説明を入力してください

4

1 に答える 1

2

Railsは通常、検証と保存をトランザクション内でラップします。したがって、実行する必要があるのは、ロックインを使用してクエリを実行することだけですensure_enough_in_stock。ロックは、他のリクエストによってデータが変更されるのを防ぎます。ロックを使用してクエリを実行する方法については、こちらをご覧ください。

于 2012-11-07T12:05:14.837 に答える