为什么不更改DB,如何重新重新回滚对象



此代码不寻常。
我正在编程长期运行的交易(使用Web API)。
所以,我需要棘手的程序。
我想重新放置回滚对象(piyo2)。

piyo2 = nil
ActiveRecord::Base.transaction do
  piyo1 = Piyo.find_by(id: 1)
  piyo1.name = 'hoge'
  piyo1.save!
  piyo2 = Piyo.find_by(id: 2)
  piyo2.name = 'foo'
  piyo2.save!
  raise ActiveRecord::Rollback
end
piyo2.save! # log show BEGIN COMMIT. But Not show execute SQL.
piyo2.name # keep foo. But DB no change.

我的解决方案。

piyo2 = nil
ActiveRecord::Base.transaction do
  piyo1 = Piyo.find_by(id: 1)
  piyo1.name = 'hoge'
  piyo1.save!
  piyo2 = Piyo.find_by(id: 2)
  piyo2.name = 'foo'
  piyo2.save!
  raise ActiveRecord::Rollback
end
piyo2_retry = Piyo.find_by(id: piyo2.id) # one more find_by
piyo2_retry.update!(name: piyo2.name)

这是最好的解决方案?
为什么piyo2.save! # log show BEGIN COMMIT. But No execute SQL.此代码不锅?

您基本上是在做正确的事,尽管您的示例会使我感到困惑。

这是您所看到的为什么

您必须刷新您手头的实例的状态。

即使您将交易滚回去,您的手中的实例仍然认为 它持续存在并具有新名称。您可以通过致电:

来证明这一点
puts piyo2.name        # foo
puts piyo2.persisted?  # true
puts piyo2.changed?    # falses

Rails足够聪明,如果对象当前持续存在并且没有更改,则不会实际运行SQL。您可以通过加载任何对象并立即尝试保存它来向自己证明这一点。您将在日志/输出中看到没有其他SQL的开始/提交。

有效地,您的对象不再与数据库同步。为了使实例的状态与DB同步,您必须重新加载它:

piyo2.reload

这是您正在有效地做的事情。Piyo.find piyo2.id生成与重新加载相同的精确SQL。重新加载在语义上更清晰。

最新更新