Rails开发细节《四》Transactions事务
事务在数据库应用开发中是相当重要的,尤其是在关系数据库中。典型的例子就是银行在转账,在两个账户之间转账。
- account1.deposite(100)
- account2.withdraw(100)
在ActiveRecord中使用transaction方法执行一段block来实现事务。在block的最后,会提交事务,更新数据库,如果在block中发生异常,数据库会回滚所有改变。
- Account.transaction do
- account1.deposite(100)
- account2.withdraw(100)
- end
下面是一个完整的例子,我们创建一个表格,有两个字段:账号和余额。
定义一个Account类,包含deposit存钱和withdraw取钱两个方法。
- create_table :accounts, :force => true do |t|
- t.string :number
- t.decimal :balance, :precision => 10, :scale => 2, :default => 0
- end
- class Account < ActiveRecord::Base
- validate :price_must_be_at_least_a_cent
- def withdarw(amount)
- adjust_balance_and_save(-amount)
- end
- def deposit(amount)
- adjust_balance_and_save(amount)
- end
- def adjust_balance_and_save(amount)
- self.balance += amount
- save!
- end
- def price_must_be_at_least_a_cent
- errors.add(:balance, "is negative") if balance < 0
- end
- end
- peter = Account.create(:balance => 100, :number => "12345")
- paul = Account.create(:balance => 200, :number => "23456")
- Account.transaction do
- paul.deposit(10)
- peter.withdraw(10)
- end
我们可以通过
select * from accounts
查询一下数据,看看账户信息是否正确。
- peter = Account.create(:balance => 100, :number => "12345")
- paul = Account.create(:balance => 200, :number => "23456")
- Account.transaction do
- paul.deposit(350)
- peter.withdraw(350)
- end
再来试试异常的情况,再来查查数据库,看看数据有没有回滚到初始值。
在异常的情况下,我们输出model对象的值看看。
- puts "Paul has #{paul.balance}"
- puts "Peter has #{peter.balance}"
我们会发现虽然数据库没有破坏,但是model对象的值被修改了。这是因为ActiveRecord没有跟踪对象的状态变化,事实上它也做不到。如果在你的应用中这是一个问题的话,你可以求助于object_transactions插件。
转载于:https://blog.51cto.com/virusswb/1016556