yel*_*ign 1 ruby ruby-on-rails
我遇到了stack level too deep一个无限循环,但我无法弄明白为什么,所以我希望别人能发现它.
我的游戏模型中有这个方法:
def self.record_win_or_tie(game_id)
game = Game.find(game_id)
if game.home_team_score > game.away_team_score
game.home_team_won = true
game.save
end
end
Run Code Online (Sandbox Code Playgroud)
当我从控制台运行条件为真的游戏(即game.home_team_score大于game.away_team_score)时,如果一遍又一遍地运行相同的查询.
SELECT `games`.* FROM `games` WHERE `games`.`id` = 1 LIMIT 1
Run Code Online (Sandbox Code Playgroud)
如果我运行条件为false的game_id的代码,则查找游戏的查询只发生一次并且没有无限循环.
*更新*
我发现问题是我从GameObserver调用方法:
class GameObserver < ActiveRecord::Observer
def after_save(game)
Game.record_win_or_tie(game.id)
end
end
Run Code Online (Sandbox Code Playgroud)
但是,我不知道如何调整我的代码.要求是自动更新或者game.home_team_won或game.away_team_won有人更新后game.home_team_score或game.away_team_score.
好像我不能用观察者来做这件事.
使用实例变量确保它只保存一次.但是,因为这是一个类方法,所以它不是线程安全的.而是使这个实例方法如下:
def record_win_or_tie
return if @inside_callback
@inside_callback = true
if home_team_score > away_team_score
update_attributes(:home_team_won => true)
end
end
Run Code Online (Sandbox Code Playgroud)
现在你可以让你的观察者像这样触发instance_method:
class GameObserver < ActiveRecord::Observer
observe :game
def after_save(game)
game.record_win_or_tie
end
end
Run Code Online (Sandbox Code Playgroud)
请注意,如果在before_save回调中执行此逻辑(不实际保存在回调中)而不是after_save:
class Game < ActiveRecord::Base
def record_win_or_tie
self.home_team_won = true if home_team_score > away_team_score
end
end
class GameObserver < ActiveRecord::Observer
observe :game
def before_save(game)
game.record_win_or_tie
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3511 次 |
| 最近记录: |