在after_commit,:on =>:create中更新属性时防止无限循环

时间:2022-01-13 01:20:11

I create an infinite callback loop when I need to update an attribute during an after_commit, :on => :create. It only occurs if I need to update an attribute of the object during this callback, though. Is there a way to prevent this? Can I somehow force a model to reload itself so it knows that it is performing an update rather than a create?

当我需要在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

3 个解决方案

#1


17  

You can use the method update_column that will skip all callbacks of your model:

您可以使用update_column方法,该方法将跳过模型的所有回调:

self.update_column(:filename, filename)

Or you could use the method update_all, wich follows the same behavior

或者你可以使用update_all方法,它遵循相同的行为

self.class.where('id = ?', self.id).update_all(:filename => filename)

And last but not least, my personal favorite:

最后但并非最不重要的,我个人的最爱:

self.filename = filename
self.send(:update_without_callbacks)

This one makes it pretty clear that all callbacks are been ignored, what is very helpful

这个很清楚,所有回调都被忽略了,这非常有帮助


Also, as a different alternative, you coud use after_create instead of after_commit if you want to run the generate method only when a new record is saved

此外,作为一种不同的替代方法,如果只想在保存新记录时运行generate方法,则可以使用after_create而不是after_commit

#2


1  

The problem will be update_attributes will initiate the after_commit callback you've used

问题是update_attributes会启动你使用过的after_commit回调

As mentioned by Rafael, you'd either need to use a callback not triggered by update_attributes, or use an update method which negates callbacks:

正如Rafael所提到的,您需要使用不是由update_attributes触发的回调,或者使用否定回调的更新方法:


update_column does not initiate callbacks - self.update_column(filename: filename)

update_column不会启动回调 - self.update_column(filename:filename)


after_create only fires when you create a record (not update) - after_create :generate

after_create仅在创建记录(不更新)时触发 - after_create:generate

#3


0  

It's a bug, see the Github issue https://github.com/rails/rails/issues/16286

这是一个错误,请参阅Github问题https://github.com/rails/rails/issues/16286

#1


17  

You can use the method update_column that will skip all callbacks of your model:

您可以使用update_column方法,该方法将跳过模型的所有回调:

self.update_column(:filename, filename)

Or you could use the method update_all, wich follows the same behavior

或者你可以使用update_all方法,它遵循相同的行为

self.class.where('id = ?', self.id).update_all(:filename => filename)

And last but not least, my personal favorite:

最后但并非最不重要的,我个人的最爱:

self.filename = filename
self.send(:update_without_callbacks)

This one makes it pretty clear that all callbacks are been ignored, what is very helpful

这个很清楚,所有回调都被忽略了,这非常有帮助


Also, as a different alternative, you coud use after_create instead of after_commit if you want to run the generate method only when a new record is saved

此外,作为一种不同的替代方法,如果只想在保存新记录时运行generate方法,则可以使用after_create而不是after_commit

#2


1  

The problem will be update_attributes will initiate the after_commit callback you've used

问题是update_attributes会启动你使用过的after_commit回调

As mentioned by Rafael, you'd either need to use a callback not triggered by update_attributes, or use an update method which negates callbacks:

正如Rafael所提到的,您需要使用不是由update_attributes触发的回调,或者使用否定回调的更新方法:


update_column does not initiate callbacks - self.update_column(filename: filename)

update_column不会启动回调 - self.update_column(filename:filename)


after_create only fires when you create a record (not update) - after_create :generate

after_create仅在创建记录(不更新)时触发 - after_create:generate

#3


0  

It's a bug, see the Github issue https://github.com/rails/rails/issues/16286

这是一个错误,请参阅Github问题https://github.com/rails/rails/issues/16286