Database Transactions

L

listrecv

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
). 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???)
 
A

Andreas Schwarz

listrecv said:
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
). 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.
 
R

Robert Klemme

Andreas said:
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
 
L

listrecv

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...)
 
R

Robert Klemme

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

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

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
 
L

listrecv

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...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top