Transactions

Get an idea of how database transactions work with an Active Record.

Database transactions

A database transaction groups a series of changes in such a way that either the database applies all of the changes or it applies none of the changes. The classic example of the need for transactions, which is used in Active Record’s own documentation is transferring money between two bank accounts. The basic logic is straightforward:

account1.deposit(100) 
account2.withdraw(100)

However, we have to be careful. What happens if the deposit succeeds but, for some reason, the withdrawal fails. Perhaps the customer is overdrawn? We’ll have added $100 to the balance in account1 without a corresponding deduction from account2. In effect, we’ll have created $100 out of thin air.

Luckily, transactions come to the rescue. A transaction is something like the Three Musketeers with their motto “All for one and one for all.” Within the scope of a transaction, either every SQL statement succeeds or they all have no effect. To put that another way, if any statement fails, the entire transaction has no effect on the database.

Transactions with active record

In Active Record, we use the transaction() method to execute a block in the context of a particular database transaction. At the end of the block, the transaction is committed and updates the database unless an exception is raised within the block. In that case, the database rolls back all of the changes. Since transactions exist in the context of a database connection, we have to invoke them with an Active Record class as a receiver.

Thus, we could write this:

Account.transaction do 
  account1.deposit(100) 
  account2.withdraw(100)
end

Let’s experiment with transactions. We’ll start by creating a new database table.

Note: Make sure your database supports transactions, or this code won’t work for you.

Get hands-on with 1200+ tech skills courses.