Working with transactions in Rails
I’ve been playing around with transactions a little bit, and it seems like it will work nicely for something I need to do at work. But I’m somewhat confused with the model prefix.
For example, I have to read in folders from a directory, parse out the folder name as a generic title for the database, then go into that folder and save all of the sub-folders as a has_many relationship to the parent folder, in the same manner. But I don’t want to save the parent folder or any of its sub-folders if an exception is thrown. The content has to be tracked, so I need the information in the database.
So what I’m doing is allowing an admin to view the available content (folders in a directory that aren’t yet in the database) versus the active content (what’s already in the database). I’m allowing the content to be toggled (activated/deactivated) based on these two methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # call to 'activate' a course def load_course @course = Course.new @course.title = params[:title] if params[:title] Course.transaction do @course.save! read_directory(@course.folder_title).each do |f| lo = LearningObject.new lo.course_id, lo.title = @course.id, f.gsub('_',' ') lo.save! end end end # call to 'deactivate' a course def unload_course unless params[:id].nil? @domid, @title = "available_#{params[:id]}", Course.find(params[:id]).title Course.transaction do LearningObject.destroy_all "course_id = #{params[:id]}" Course.destroy(params[:id]) end end end |
Based on this, it would make sense to me if only the Courses table would ROLLBACK on an exception; however, I’ve tested this and it seems as though, if an exception is thrown in either case, neither the course nor the learning objects are saved. Granted, that is what I want to happen, I’m not completely convinced this will ROLLBACK the learning_objects table everytime. Do I need some sort of nested transaction, or is qualifying the block with Course good enough?

Jay Thursday, 08 Feb, 2007 Posted at 08:12PM
Looks good to me.
Ryan Thursday, 08 Feb, 2007 Posted at 08:14PM
Well, it seems to work fine, so I’ll keep it as is for now.
Shannon -jj Behrens Thursday, 10 Sep, 2009 Posted at 09:22PM
Let me see if I understand your question correctly. You’re wondering why you have to say Course.transaction and if that transaction will affect LearningObject. Is that right? You have to specify the model because Rails can be configured so that each model executes within a different database. Hence, you’re saying that you want the transaction to run in whatever database Course uses. However, the transaction spans the entire database. Hence, if LearningObject is in the same database as Course (which is really the norm), then it’s in the same transaction (which is really what people usually want).
Ryan Thursday, 29 Jul, 2010 Posted at 12:33PM
The code looks good to me, but if it doesn’t work I’d check if the database supports transactions