2013-04-01 48 views

回答

69

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

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

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

+8

这是否意味着如果after_commit提高和异常,那么它不会回滚先前提交的查询 –

+9

正确(创建部分?) - 一旦交易已经comitted它不再被回滚 –

+11

注意,当设置一个使用被创建对象的'id'的异步任务(例如通过sidekiq),那么你应该使用'after_commit,... on :: create',因为使用'after_create'你可以得到一个'ActiveRecord :: RecordNotFound'异常。这恰好发生在我们身上。 – Dschee

3

这两者在协会方面有一个主要区别。只要为给定对象插入查询并且在插入查询对象关联之前立即调用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