We have following code in our out_logs controller for saving into two tables in rails 3.1.3 app. In order to make sure the two savings are done with completion or none, a transaction is used.
@out_log.transaction do
if @out_log.save && @part.save
redirect_to part_path(@part), :notice => "Saved!"
else
flash.now[:error] = "Not saved!"
render 'new'
end
end
The code seems working. Our questions are:
- Is the code above good practice for transaction?
- There are redirect_to and render in transaction loop, will these redirect_to or render increase the execution time for transaction loop and therefore will lock the database (we use sqlite3) for too long?
Thanks so much.
First off:
redirect_toorrenderdon’t act like areturnstatement. They just assign some headers in a response that is currently being prepared.About transactions:
The above code is sure to lead to inconsistent states in your DB: what if first
saveis successful and the second one isn’t? It’s even hard to imagine.The solution is quite simple: use
save!(with the exclamation at the end). This way if your validation fails your whole transaction will be rolled back (an exception will be raised bysave!instead of returningfalseas thesavedoes).