1. 使用事物的缘由数据库
保证数据一致性, 当其中出现一个失败的时候,操做能够回滚app
好比:框架
ActiveRecord::Base.transaction do david.withdrawal(100) # withdrawal失败必须触发 exception mary.deposit(100) # deposit失败必须触发 exception end
return false 不会出发操做回滚, 因此事物中要使用!的方法, 好比 save! update!ide
before_save 等callback也包含在事物中, 若是但愿触发事物回滚, 须要能抛出异常测试
若是不希回滚则不抛出异常 或者放在事物以外 用after_commit等callbacl来处理spa
不要在事务内部去捕捉 ActiveRecord::RecordInvalid 异常。由于某些数据库下,这个异常会致使事务失效,好比 Postgres。一旦事务失效,要想让代码正确工做,就必须从头从新执行事务。翻译
另外,测试回滚或者事务回滚相关的回调时,最好关掉 transactional_fixtures 选项,通常的测试框架中,这个选项是打开的。rest
Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you should be ready to catch those in your application code.code
One exception is the ActiveRecord::Rollback
exception, which will trigger a ROLLBACK when raised, but not be re-raised by the transaction block.blog
Warning: one should not catch ActiveRecord::StatementInvalid
exceptions inside a transaction block. ActiveRecord::StatementInvalid
exceptions indicate that an error occurred at the database level, for example when a unique constraint is violated. On some database systems, such as PostgreSQL, database errors inside a transaction cause the entire transaction to become unusable until it's restarted from the beginning. Here is an example which demonstrates the problem:
# Suppose that we have a Number model with a unique column called 'i'. Number.transaction do Number.create(i: 0) begin # This will raise a unique constraint error... Number.create(i: 0) rescue ActiveRecord::StatementInvalid # ...which we ignore. end # On PostgreSQL, the transaction is now unusable. The following # statement will cause a PostgreSQL error, even though the unique # constraint is no longer violated: Number.create(i: 1) # => "PGError: ERROR: current transaction is aborted, commands # ignored until end of transaction block" end