Rails 3:a​​fter_create的回滚

时间:2012-07-27 17:02:21

标签: ruby-on-rails ruby

我有一份报名表。

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

所以我在考虑在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表中回滚并销毁刚刚保存的数据?

4 个答案:

答案 0 :(得分:11)

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

如果你想模拟这个,请将它添加到你的after_create中,看看是否一切都按预期工作:

raise Exception.new("CRASH")

答案 1 :(得分:9)

false返回after_create将无效。

  

整个回调链包含在一个事务中。如果在回调方法之前返回任何错误或引发异常,则执行链将停止并发出ROLLBACK;回调之后只能通过引发异常来实现。

此外,您必须raise ActiveRecord::Rollback

  

在回调链暂停后,Rails将重新引发任何非ActiveRecord :: Rollback异常。引发除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

答案 2 :(得分:1)

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

Enrollment.transaction do
  @enrollment.save!
end

这就是你真正需要做的,如果注册保存失败或者用户保存失败,它将回滚你的整个交易。以下是更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

答案 3 :(得分:0)

在Rails 5中,您需要使用throw :abort来回滚ActiveRecord链。

enter image description here

您可以看到不同版本的Rails中的操作处理列表以及回调之前和之后。为了更好的说明,请查看暂停执行的概念。请点击下面的给定链接。

https://guides.rubyonrails.org/active_record_callbacks.html#halting-execution