You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Game模型调用update_attribute返回true,但部分属性未实际更新

排查Game模型turn属性未更新的问题

我来帮你分析下这个问题~你提到opponent能成功更新,但turn没变化,而且update_attribute还返回true,这种情况通常是这几个原因导致的,咱们一步步排查:

1. 先确认owner的值是否正确

你代码里owner = @game.owner.id.to_i,首先要确保@game.owner不是nil——如果游戏还没设置owner,那@game.owner.id会报错,但你说方法返回true,所以大概率owner是存在的,但可以加个日志验证下:

def update
  @game = Game.find(params[:id])
  owner = @game.owner.id.to_i
  Rails.logger.debug "当前游戏owner的ID是:#{owner}" # 去日志里看这个值是不是你预期的
  @game.update_attribute(:opponent, current_user)
  turn_update_result = @game.update_attribute(:turn, owner)
  Rails.logger.debug "更新turn的结果:#{turn_update_result},更新后turn的值:#{@game.turn}"
end

如果日志里显示owner是0或者非预期的数值,那问题就出在这里,得先确保@game.owner是正确的用户对象。

2. 检查模型是否有回调覆盖了turn的值

如果owner值没问题,那很可能是Game模型里的回调(比如after_save、before_save)在你更新后又修改了turn。比如模型里如果有类似这样的代码:

after_save :reset_turn

def reset_turn
  self.turn = 1 # 每次保存后把turn重置为1,就会覆盖你的更新
end

这种情况下,你更新turn后,回调会再次修改它。可以暂时注释掉这类回调,测试下是否能正常更新。

3. 合并更新操作,避免多次保存的问题

你现在用两次update_attribute,每次都会触发一次数据库保存,不如合并成一次更新,既高效又能避免中间回调的干扰:

  • 如果需要触发验证和回调,用update:
def update
  @game = Game.find(params[:id])
  owner_id = @game.owner.id
  # 一次更新两个属性
  @game.update(opponent: current_user, turn: owner_id)
end
  • 如果不需要触发验证和回调(比如确定数据没问题,不想触发多余的回调),用update_columns(注意关联属性要写字段名,比如opponent_id而不是opponent):
def update
  @game = Game.find(params[:id])
  owner_id = @game.owner.id
  @game.update_columns(opponent_id: current_user.id, turn: owner_id)
end

4. 检查数据库字段约束

最后可以去数据库里看看turn字段的设置:比如是不是设置了默认值,或者有NOT NULL约束导致更新失败?不过update_attribute返回true说明ActiveRecord认为保存成功了,所以这个概率较低,但也可以确认下。

另外,如果你在更新后立刻查看@game.turn,有时候需要调用@game.reload才能拿到数据库里的最新值,因为内存里的对象可能还没同步~

内容的提问来源于stack exchange,提问作者swilliams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:24:54