# Database Transactions

**URL:** <https://www.ruby-forum.com/t/database-transactions/48624>\
**Category:** Ruby\
**Created:** [November 15, 2005, 9:28am UTC](https://www.ruby-forum.com/t/database-transactions/48624 "2005-11-15T09:28:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 9:28am UTC](https://www.ruby-forum.com/t/database-transactions/48624/1 "2005-11-15T09:28:08Z")

</div>

ActiveRecord’s standard procedure for transactions is to send a block,  
and throw an exception to roll it back (  
[http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html](http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html)  
). I found this rather uncomfortable. I’d like to be able to begin  
transactions, commit them, or roll them back from within (fairly)  
complex control structures - and having to do everything within a  
block, with one way out, is no good.

Any suggestions?

PS This question concerns ActiveRecord, an O/R mapper which can be used  
for lots of things. It’s _not_ a _rails_ questions (what’s rails???)

---

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 12:34pm UTC](https://www.ruby-forum.com/t/database-transactions/48624/2 "2005-11-15T12:34:11Z")

</div>

listrecv wrote:

> ActiveRecord’s standard procedure for transactions is to send a block,  
> and throw an exception to roll it back (  
> [Peak Obsession](http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html)  
> ). I found this rather uncomfortable. I’d like to be able to begin  
> transactions, commit them, or roll them back from within (fairly)  
> complex control structures - and having to do everything within a  
> block, with one way out, is no good.

You can start/commit/rollback transactions manually  
(ActiveRecord::Base.connection.start\_transaction, IIRC). Though I don’t  
see why using a block should be a problem for your control structure.

---

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 1:04pm UTC](https://www.ruby-forum.com/t/database-transactions/48624/3 "2005-11-15T13:04:52Z")

</div>

Andreas S. wrote:

> listrecv wrote:
> 
> > ActiveRecord’s standard procedure for transactions is to send a  
> > block, and throw an exception to roll it back (

[http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html](http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html)

> > ). I found this rather uncomfortable. I’d like to be able to begin  
> > transactions, commit them, or roll them back from within (fairly)  
> > complex control structures - and having to do everything within a  
> > block, with one way out, is no good.
> 
> You can start/commit/rollback transactions manually  
> (ActiveRecord::Base.connection.start\_transaction, IIRC). Though I  
> don’t see why using a block should be a problem for your control  
> structure.

+1

Using the block is definitely superior and less error prone. Hint: you  
can call methods from the block. 🙂

Kind regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 6:09pm UTC](https://www.ruby-forum.com/t/database-transactions/48624/4 "2005-11-15T18:09:28Z")

</div>

Okay, I’ll trust you guys know better than I do.  
How do I do this with a block?

def signup

# It gets a little tricky, since we want to create either both an

account and user or neither

```
@account = Account.new(params[:account])
@user = User.new(params[:user])
@user.login = @account.code	# For now, we keep a 1-to-1 between

```

these  
@user.real\_name = @account.name

```
begin
    # TODO begin transaction
    if (@user.valid?)
    	@account.user = @user	# Don't assign until we know it is valid -

```

ActiveRecord sometimes saves on assign  
if (@account.valid?) # We need to do this in two steps, since  
@account won’t be valid without a user  
@user.save!  
@account.save!  
# TODO end transaction  
flash[:notice] = ‘Account added.’  
redirect\_to :action =\> ‘list’  
return  
end  
end  
# TODO rollback transaction  
render :action =\> ‘new’  
# TODO rescue exceptions  
end  
end

(Okay, I admit it, yes, this is part of a rails app…)

---

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 9:37pm UTC](https://www.ruby-forum.com/t/database-transactions/48624/5 "2005-11-15T21:37:40Z")

</div>

> Why do you want to do a rollback here?

It’s not to catch exceptions. It’s to make sure that no account is  
saved without a user or vice versa (which would happen to be very  
bad…). Especially confusing since I know AR sometimes saves  
associations before we ask…

---

<div class="post-metadata">

**Author:** ![listrecv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/f17d59/32.png) [@listrecv](https://www.ruby-forum.com/u/listrecv)\
**Post date:** [November 15, 2005, 6:27pm UTC](https://www.ruby-forum.com/t/database-transactions/48624/6 "2005-11-15T18:27:32Z")

</div>

removed\_email\_address@domain.invalid wrote:

> Okay, I’ll trust you guys know better than I do.  
> How do I do this with a block?

[http://wiki.rubyonrails.com/rails/pages/HowToUseTransactions](http://wiki.rubyonrails.com/rails/pages/HowToUseTransactions)

> ```
> begin
> redirect_to :action => 'list'
> return
> end
> end
> # TODO rollback transaction
> 
> ```

Why do you want to do a rollback here? There is no rescue clause nor  
any  
indication that an error has occurred. If you use a block then you  
don’t  
need explicit commit and rollback. It’s handled in the method that  
receives the block (#transaction).

> ```
> render :action => 'new'
> 
> ```
> 
> # TODO rescue exceptions
> 
> end  
> end
> 
> (Okay, I admit it, yes, this is part of a rails app…)

I know only little about RoR so there might as well be other answers.

Kind regards

```
robert

```
