2012-07-27 71 views
6

我有一个注册表单。Rails 3:rollback for after_create

当用户注册时,应用程序应该将数据保存在enrollments表和users表中。 (我需要这种分离,因为用户的个人资料可能会改变,但是他为特定注册输入的数据必须存档,所以即使后来用户改变了他的姓氏,在注册表中我也会得到他的初始信息。)

所以我想在enrollments表保存数据,然后有一个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 

的问题是,如果节省了用户由于某种原因失败。我如何回滚和销毁enrollments表中刚刚保存的数据?

+0

用户可以注册几次?如果不是,我只是直接在users表中添加额外的字段。 – 2012-07-27 17:15:47

+0

呃,实际上,这是一名家长/监护人将一名孩子招入日托。所以是的,家长可以多次注册一个孩子。 – leonel 2012-07-27 17:22:39

+0

对我来说,似乎把save_corresponding_user放在after_create中会成为一个问题。当用户再次注册时会发生什么?你不想为它们创建一个新的用户对象。另外,注册表中可能没有user_id列吗?这不会在上面的代码中填充。如果是我,我只是将注册和用户的创建包装在一个事务中,这将处理在发生错误时两者的回滚。 – 2012-07-27 17:23:23

回答

12

after_create是保存当前模型的事务的一部分。因此,如果代码崩溃或者after_create返回false,它应该回滚当前事务并使保存失效。

如果要模拟此,添加到您的after_create,看看是否一切正常:

raise Exception.new("CRASH") 
+0

如果您使用的是非事务数据库(如mongodb),则不会发生回滚 – 2013-10-03 09:07:37

+3

如果after_create返回false,则不会显示回滚事务(只是异常)。至少在Rails 4中。 – djburdick 2014-10-15 22:40:15

+0

@djburdick默认情况下事务只在引发异常时才应该回滚。所以这是预期的行为。我认为这个答案在细节方面略有不正确。 – leishman 2015-03-03 08:55:33

1

正如@anthonyalberto提到,after_create已经是交易的一部分。要定义一个事务,你会使用这样的事情在你的控制器:

Enrollment.transaction do 
    @enrollment.save! 
end 

这真的是你需要做的,如果保存报名失败或保存的用户无法将回滚整个事务。以下是更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

7

after_create返回false什么都不会做。

整个回调链被封装在一个事务中。如果在回调方法返回完全为false或引发异常之前,执行链会暂停并发出ROLLBACK;回调之后只能通过引发异常来实现。

此外,还必须raise ActiveRecord::Rollback

任何异常未的ActiveRecord ::回滚将被Rails的回调链暂停后重新升起。引发除ActiveRecord :: Rollback以外的异常可能会破坏不希望save和update_attributes(通常尝试返回true或false)方法来引发异常的代码。

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