# Database transactions

**URL:** <https://www.ruby-forum.com/t/database-transactions/101909>\
**Category:** Rails\
**Created:** [August 8, 2006, 5:14pm UTC](https://www.ruby-forum.com/t/database-transactions/101909 "2006-08-08T17:14:35Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthew](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@matthew](https://www.ruby-forum.com/u/matthew)\
**Post date:** [August 8, 2006, 5:14pm UTC](https://www.ruby-forum.com/t/database-transactions/101909/1 "2006-08-08T17:14:35Z")

</div>

Hello,

I have an application where I need to create two records in a database  
transaction.

ie:

begin  
User.transaction(user) do  
User\_details.transaction(user\_details) do  
user.save  
user\_details.save  
end  
end  
end

rescue  
flash[:notice] “Insert rolled back… but why…??”  
end

From reading the Agile book, I gather that once I wrap the request in a  
transaction I loose the validation state, so I have no easy what of  
knowing what went wrong.

I am just wonder what the best practise is…??

Is this something people would recommend?

user.validate  
if user.errors.count == 0  
user\_details.validate  
if user\_details.errors.count == 0  
perform transaction\_routine(user, user\_details)  
end  
end

rgds,

- matt.

---

<div class="post-metadata">

**Author:** ![matthew](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@matthew](https://www.ruby-forum.com/u/matthew)\
**Post date:** [August 8, 2006, 11:12pm UTC](https://www.ruby-forum.com/t/database-transactions/101909/2 "2006-08-08T23:12:41Z")

</div>

On Aug 8, 2006, at 8:14 AM, Matt S. wrote:

Not clear on your actual problem, but you could  
simplify the code as below. As written, I’m not  
sure that rescue clause was valid at all.

> end  
> –  
> – Tom M.

---

<div class="post-metadata">

**Author:** ![matthew](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@matthew](https://www.ruby-forum.com/u/matthew)\
**Post date:** [August 15, 2006, 2:17pm UTC](https://www.ruby-forum.com/t/database-transactions/101909/3 "2006-08-15T14:17:13Z")

</div>

On 8 Aug 2006, at 16:14, Matt S. wrote:

> ```
> user.save
> 
> ```
> 
> > From reading the Agile book, I gather that once I wrap the request  
> > in a  
> > transaction I loose the validation state, so I have no easy what of  
> > knowing what went wrong.  
> > You only lose the validation if you also have the transaction roll  
> > back the active record object as well as the database.

If you do this:

> 

> begin  
> User.transaction(user) do  
> Use.transaction do  
> User\_details.transaction(user\_details) do  
> user.save  
> You probably want to do  
> user.save! here  
> The transaction aborts if an exception is thrown, not if the save  
> fails. So you need to use save! to get the RecordInvalid exception  
> thrown out.

> ```
> user_details.save
> end
> end
> 
> ```
> 
> end
> 
> rescue  
> user has not been rolled back, so contains all the errors from when  
> it was saved

> ```
> flash[:notice] "Insert rolled back... but why..??"
> 
> ```
> 
> end

> Is this something people would recommend?
> 
> user.validate  
> if user.errors.count == 0  
> user\_details.validate  
> if user\_details.errors.count == 0  
> perform transaction\_routine(user, user\_details)  
> end  
> end

Use the transaction if you need thread-safety (you don’t need thread  
safety if you are only serving with a single process, but that  
doesn’t mean it’s not worth thinking about upfront). The transaction  
in itself won’t magically make things threadsafe though; you need to  
think carefully about your failure scenarios and whether all of them  
cause an exception. For example, your case above creates a user  
record, then a user\_details record. Suppose a separate thread updates  
the user record before the user\_details record has been saved. Is  
this a problem?

Ben

–  
Ben B. - Director  
Airsource Ltd  
Tel: 01223 708370 / 07786 916043

---

<div class="post-metadata">

**Author:** ![matthew](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@matthew](https://www.ruby-forum.com/u/matthew)\
**Post date:** [August 15, 2006, 2:18pm UTC](https://www.ruby-forum.com/t/database-transactions/101909/4 "2006-08-15T14:18:28Z")

</div>

On Aug 8, 2006, at 8:14 AM, Matt S. wrote:

> end
> 
> end  
> (Transactions are per database connection, not per class or object,  
> so you only need to call it once - the transaction method is  
> available on all of them for convenience.)

def update  
User.transaction do  
@user.save!  
@user\_details.save!  
end  
rescue ActiveRecord::RecordInvalid  
flash.now[:error] = “error saving #{@user.name}”  
render :action =\> ‘edit’  
end

\<%= error\_messages\_for ‘user’ %\>  
\<%= error\_messages\_for ‘user\_details’ %\>

Though it’s likely more appropriate to manage this in your model,  
particularly if one object is dependent on the other.

jeremy
