关于ActiveRecord::Rollbak异常

浏览:810 发布日期:2016-02-05 06:13:13

Rails事务通过是否抛出异常来决定是否回滚操作,事务回滚后,同时将异常继续传递,我们通常要在begin resuce end中来捕获异常。

Rails还有一个ActiveRecord::Rollback异常,当使用raise ActiveRecord::Rollback, "..."后,只执行回滚操作,而不抛出异常。例如:

# 引发ActiveRecord::RollBack异常
  def exception_t1
      ActiveRecord::Base.transaction do 
          card = Card.find(122348)
          card.coin = 55
          card.save!

          raise ActiveRecord::Rollback, "故意抛出异常"
      end
  end
  
  def test_exception
      begin
          ActiveRecord::Base.transaction do 
              exception_t1()
              puts "顺利执行"
          end
          
      rescue
          puts "发生异常"
          p $!
      end
      

      render :text => 123
  end

上面第一个方法,是一个私有方法,它抛出ActiveRecord::Rollback,将会造成回滚,而不向外抛出异常,当外部也使用事务的话,将形成嵌套事务,嵌套事务会将父事务代码与子事务合并到一个事务中,所以这样就会造成一些很奇怪的结果,如果父事务代码不会造成回滚,那么子事务的代码也会正常执行,这违背了我们的本意。


我们可以在子事务中使用:requires_new => true,来规避它,这样,嵌套时,子事务可以按我们的意图进行回滚。