在更新数据库提交后运行rails代码,没有after_commit

我正在尝试与我的后台任务经理对抗一些种族案件。 基本上,我有一个Thing对象(已经存在)并为其分配一些属性,然后保存它。 使用新属性保存后,我将其排入Resque,并传入ID。

 thing = Thing.find(1) puts thing.foo # outputs "old value" thing.foo = "new value" thing.save ThingProcessor.queue_job(thing.id) 

后台作业将使用Thing.find(thing_id)从数据库加载对象。

问题是我们发现Resque在获取作业和从ID加载Thing对象方面非常快,它加载了一个陈旧的对象。 因此,在工作中,调用thing.foo仍将返回“旧值”,如1/100次(不是真实数据,但它不会经常发生)。

我们知道这是一个竞赛案例,因为在数据实际提交到数据库之前 ,rails将从thing.save返回(在本例中为postgresql)。

Rails中有一种方法只能在数据库操作提交后执行代码吗? 基本上我想确保在Resque加载对象时,它会得到最新鲜的对象。 我知道这可以使用Thing模型上的after_commit钩子来实现,但我不想在那里。 我只需要在这个特定的上下文中发生这种情况,而不是每次模型都提交更改为DB。

您也可以进行交易。 就像下面的例子:

 transaction do thing = Thing.find(1) puts thing.foo # outputs "old value" thing.foo = "new value" thing.save end ThingProcessor.queue_job(thing.id) 

更新:有一个调用After Transaction的gem,你可以解决这个问题。 这是链接: http : //xtargets.com/2012/03/08/understanding-and-solving-race-conditions-with-ruby-rails-and-background-workers/

如果围绕transaction进行try ,那么只有在事务成功时才将作业排队?