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) endIn 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 endand
User.transaction do endThe 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 endNested 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 endCreates 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]]>