2012-08-29 44 views
0

Short:在保存ActiveRecord競賽時節省空間

如何防止在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爲零,將其設置爲用戶試圖創建遊戲然後保存更新後的遊戲。如果沒有找到這樣的遊戲,則以詢問用戶爲current_user創建一個新遊戲。

我在ActiveRecord的文檔中找不到任何內容,說明如何在保存更新的遊戲時防止比賽,即用戶b可以在用戶a找到遊戲後找到空遊戲並保存到數據庫但在他們保存到數據庫之前。如果有的話,我讀過的唯一性驗證看起來像我需要在數據庫級別解決這個問題。

在此先感謝!

回答

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 
所以在遷移沿線的添加的東西