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???)
listrecv wrote:
ActiveRecord’s standard procedure for transactions is to send a block,
and throw an exception to roll it back (
Peak Obsession
). 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.
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
). 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
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…)
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…
[email protected] 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
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