短:
如何在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找到游戏后保存到数据库但是在他们保存到数据库之前。如果有的话,我读过的关于唯一性验证的内容似乎我需要在数据库级别修复它。
提前致谢!
答案 0 :(得分:0)
当然我没有完全阅读导轨指南。这个http://guides.rubyonrails.org/active_record_querying.html#locking-records-for-update
有一节答案 1 :(得分: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