`
together
  • 浏览: 217651 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

对rails里transaction的嵌套处理方式不解

    博客分类:
  • ruby
阅读更多
本来要问的是下面这一段,自己看完文档明白了。
引用

#before do it:  a.name="a"
a = A.find(1)
a.name="b"
a.save

上面这段代码在普通的rb文件里,是可以正常更新数据的。
在test.rb里,每次执行完以后数据都没有更新,也就是说rollback事务了。

在test_helper.rb里是这样说的:
#Transactional fixtures accelerate your tests by wrapping each test method
  # in a transaction that's rolled back on completion.  This ensures that the
  # test database remains unchanged so your fixtures don't have to be reloaded
  # between every test method.  Fewer database queries means faster tests.

修改  self.use_transactional_fixtures = false 就可以更新数据了。


但还有另外一个问题,就是说我手工控制事务的回滚和提交该如何做呢?
现在是这样用事务:
ActiveRecord::Base.transaction do
  SELECTAA
  UPDATEAA
  SELECTBB
  UPDATEBB
rescue
ensure
end

我想实现的是,当查找到BB的时候,由于某种原因需要回滚整个事务。但是在上面的语句中,是只有在出现异常的时候才回滚的吧?如果在里面加上raise "xxxx",也可以实现回滚。但是除此之外,有没有可以手工控制的语句呢?
就像在TEST中,可以设置事务是否自动回滚一样。

后记:cookoo的回复
ActiveRecord::Base.connection.begin/commit/rollback_db_transaction

再测试一下事务嵌套效果:
ActiveRecord::Base.connection.begin_db_transaction
  ActiveRecord::Base.transaction do
  end
ActiveRecord::Base.connection.commit_db_transaction
执行结果是:begin begin commit commit

反过来:
ActiveRecord::Base.transaction do
  ActiveRecord::Base.connection.begin_db_transaction
  ActiveRecord::Base.connection.commit_db_transaction
end
执行结果是:begin begin commit commit

但是在_test.rb中加入
ActiveRecord::Base.transaction do
end
语句时,却仅执行外围的begin/commit/rollback,上面这条transaction do end中根本没有开启事务语句。相当于被外围接管了
分享到:
评论
2 楼 together 2006-12-30  
thanks!
继续学习,越来越感觉到RAILS的强大和巧妙了。除了语法上暂时有些不好适应。
1 楼 cookoo 2006-12-29  
你说的对,只能自己触发异常来回滚,因为AR的回滚是隐式的,不能显式控制。回滚完了异常会继续传播,可以立即rescue或者以后再处理。

transactional fixture里面用的是底层的ActiveRecord::Base.connection.rollback_db_transaction,如果你想绕过AR直接用connection adapter操作数据库的话。

相关推荐

Global site tag (gtag.js) - Google Analytics