after_create:foo vs after_commit:bar,:on =>:create

Bil*_*ill 47 ruby-on-rails

之间有什么区别:

after_create :after_createafter_commit :after_commit_on_create, :on => :create

这些可以互换使用吗?

Fre*_*ung 90

它们不可互换.关键的区别在于回调运行时.在这种情况下after_create,这将始终在调用save(或create)之前返回.

Rails save在事务内部包装每个内容,并且在该事务内部运行之前/之后的创建回调(这样做的结果是,如果在after_create中引发异常,则将回滚保存).使用after_commit,直到最外层事务提交后,您的代码才会运行.这可以是创建的事务轨道或由您创建的事务轨道(例如,如果您想在单个事务中进行多处更改).

after_save/create运行时,您的保存仍然可以回滚,并且(默认情况下)对其他数据库连接不可见(例如,诸如sidekiq之类的后台任务).这些2的某些组合通常是使用的动机after_commit.

  • 请注意,当设置使用正在创建的对象的`id`的异步任务(例如通过sidekiq)时,你应该使用`after_commit,... on :: create`,因为使用`after_create`你可以得到一个`ActiveRecord: :RecordNotFound`异常.这恰好发生在我们身上. (19认同)
  • 正确 - 一旦交易完成,它就不能再回滚了 (9认同)
  • 这是否意味着如果after_commit引发异常,则它不会回滚先前提交的查询(创建部分?) (8认同)

小智 5

这两者在关联方面存在一个主要区别.只要为给定对象触发插入查询,并在插入对象关联的查询之前调用after_create.这意味着可以在没有更新查询的after_create回调中直接更改关联对象的值.

class Post < ActiveRecord::Base
  has_one :post_body
  after_create :change_post_body

  def change_post_body
    self.post_body.content = "haha"
    #No need to save
  end 
end
Run Code Online (Sandbox Code Playgroud)