当我需要在after_commit, :on => :create
期间更新属性时,我创建了一个无限回调循环。但是,只有在我需要在此回调期间更新对象的属性时才会发生这种情况。有办法防止这种情况吗?我可以以某种方式强制模型重新加载自己,因此它知道它正在执行更新而不是创建吗?
class Doc < ActiveRecord::Base
after_commit :generate, :on => :create
...
def generate
# some logic here that requires this model to be saved in the db
self.update_attributes(:filename => filename) # Infinite loop begins here.
end
end
答案 0 :(得分:20)
您可以使用将跳过模型的所有回调的方法update_column
:
self.update_column(:filename, filename)
或者你可以使用方法update_all
,它遵循相同的行为
self.class.where('id = ?', self.id).update_all(:filename => filename)
最后但并非最不重要的,我个人的最爱:
self.filename = filename
self.send(:update_without_callbacks)
这个很清楚,所有的回调都被忽略了,这是非常有用的
此外,作为另一种选择,如果您只想在保存新记录时运行after_create
方法,则可以使用after_commit
代替generate
答案 1 :(得分:1)
问题是update_attributes
将启动您已使用过的after_commit
回调
如Rafael所述,您需要使用不是由update_attributes
触发的回调,或使用否定回调的更新方法:
update_column
无法发起回调 - self.update_column(filename: filename)
after_create
仅在您创建记录(而不是更新)时触发 - after_create :generate
答案 2 :(得分:0)
这是一个错误,请参阅Github问题https://github.com/rails/rails/issues/16286