Database transaction in Rails

A transaction is a sequence of operations performed as a single logical unit of work. A logical unit of work must exhibit four properties called the atomicity, consistency, isolation and durability (ACID) properties, to qualify as a transaction. We use database transactions to make sure that all the instructions we send to database are successful, and would cause changes to the database only if they are successful. Let’s say that you are working on a banking application which would withdraw money from one account and deposit into another account. The code for it would look like below

User.find(156).withdraw(1000)
User.find(157).deposit(1000)
But for some reason, the withdrawal was successful but the deposit was not, the amount was taken out but never deposited to the other user.To avoid these kind of issues, database has a functionality called transactions, in which you can  build up each sql query. But if for any reason, any of the sql statements fails or an exception rises in the block, all the transactions are rolled back to their original form.
User.transaction do
  User.find(156).withdraw(1000)
  User.find(157).deposit(1000)
end
In rails, the transaction method is available as class method and instance method, but the functionality for both is same. There is no difference when you will use.
@user.transaction do
end
and
User.transaction do
end
The reason why rails provides this, is for better readability. One can also mix various model types in a transaction, as the transaction are bound to a database connection. So there is no issue in writing code like below.
User.transaction do
  Order.create order_attributes
  Purchase.create purchase_attribute
end
  Nested Transactions: It is possible to write nested transactions. But it is to be noted that, it would just make each child transaction a part of the parent transaction. Taking the example from the Rails documentation. The below code
User.transaction do
  User.create(username: 'Kotori')
  User.transaction do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end
Creates both “Kotori” and “Nemu”. Reason is the ActiveRecord::Rollback exception in the nested block does not issue a ROLLBACK. Since these exceptions are captured in transaction blocks, the parent block does not see it and the real transaction is committed. Reference: https://technet.microsoft.com/en-us/library/ms190612(v=sql.105).aspx]]>