Rails 3:after_create的回滚
我有一份报名表。
当用户注册时,应用程序应该将数据保存在enrollments
和users
表中。 (我需要这种分离,因为用户的个人资料可以更改,但他为该特定注册输入的数据必须存档。因此,即使稍后用户更改了他的姓氏,我也会在注册表单中获得他的初始信息。)
所以我在考虑在注册表中保存数据,然后进行after_create调用,就像这样……
class Enrollment < ActiveRecord::Base after_create :save_corresponding_user def save_corresponding_user user = User.new user.full_name = self.user_full_name user.email = self.user_email user.mobile_phone = self.user_mobile_phone user.save end end
问题是,如果因任何原因保存用户失败该怎么办? 如何从注册表中回滚和销毁刚刚保存的数据?
after_create是保存当前模型的事务的一部分。 因此,如果您的代码崩溃或者after_create返回false,它应该回滚当前事务并使enrollment
保存无效。
如果你想模拟它,将它添加到你的after_create中,看看是否一切都按预期工作:
raise Exception.new("CRASH")
从after_create
返回false
将after_create
。
整个回调链包含在一个事务中。 如果在回调方法之前返回任何错误或引发exception,则执行链将暂停并发出ROLLBACK; 回调之后只能通过引发exception来实现。
此外,您必须raise ActiveRecord::Rollback
:
在回调链暂停后,Rails将重新引发任何非ActiveRecord :: Rollbackexception。 引发除ActiveRecord :: Rollback之外的exception可能会破坏不期望save和update_attributes(通常尝试返回true或false)等方法引发exception的代码。
http://guides.rubyonrails.org/active_record_callbacks.html#halting-execution
我做这样的事情:
after_create do if condition errors.add(:attr, 'Blah blah blah.') raise ActiveRecord::Rollback end end
对于Rails 3: http : //guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#halting-execution
正如@anthonyalberto所提到的,after_create已经是交易的一部分。 要定义事务,您可以在控制器中使用以下内容:
Enrollment.transaction do @enrollment.save! end
这真的是你需要做的,如果注册保存失败或者用户保存失败,它将回滚整个事务。 以下是更多信息: http : //api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html