0

短い:

Ruby on RailsでActiveRecordオブジェクトを保存する際の競合状態からどのように保護しますか? または、競合が検出された場合にエラーを取得する方法は少なくともありますか?

長いです:

このモデルがあると仮定します

class Game < ActiveRecord::Base
  belongs_to :current_user, :class_name => "User", 
                  :foreign_key => "current_user_id"
  belongs_to :other_user, :class_name => "User", 
                  :foreign_key => "other_user_id
end

コントローラーでゲームを作成するとき、:other_user_id が nil である最初のゲームを見つけて、ゲームを作成しようとしているユーザーに設定し、更新されたゲームを保存します。そのようなゲームが見つからない場合は、要求しているユーザーで新しいゲームを作成しますcurrent_user として。

更新されたゲームを保存する際の競合から保護する方法を示すActiveRecordのドキュメントには何も見つかりません。つまり、ユーザーbが空のゲームを見つけて、ユーザーaがゲームを見つけた後、データベースに保存することができます。データベースに保存しました。どちらかといえば、一意性の検証について読んだことは、データベース レベルでこれを修正する必要があるようです。

前もって感謝します!

4

2 に答える 2

0

基本的に、楽観的ロックが必要です。これは、ゲームにlock_version列を設定することで有効になります。したがって、移行では、次の行に沿って何かを追加します。

 class AddLockedVersionToGames < ActiveRecord::Migration
   def changes
     add_column :games, :lock_version, :integer, :default => 0
   end
 end

そしてゲームモデルでは:

  def self.add_user_to_game(current_user)
    game = Game.find_by_other_user(nil)
    if game
      game.other_user = current_user
    else
      game = Game.new(current_user: current_user)
    end
    game.save
  rescue ActiveRecord::StaleObjectError
    game = Game.new(current_user: current_user)
    game.save
  end
于 2012-08-29T07:14:07.567 に答える
0

もちろん、Rails ガイドを完全に読んだわけではありません。このhttp://guides.rubyonrails.org/active_record_querying.html#locking-records-for-updateに関するセクションがあります

于 2012-08-29T05:22:26.093 に答える