Reputation: 8158
I would like to add the following code in a transaction to be able to rollback if there are errors in any of the inserts.
def create
m = params[:message]
# EmailThread.transaction do #<=== is this correct?
if m[:parent_id].nil?
thread = EmailThread.new :title => m[:subject]
thread.save
else
thread = EmailThread.find m[:parent_id]
end
message = thread.messages.build :content => m[:content], :author_id => current_user.id
message.save
from = thread.participants.build :user_id => current_user.id
to = thread.participants.build :user_id => m[:to_user_id]
from.save
to.save
#end #<=== to here
render :json => {:success=>true,:message=>"Message sent"}
end
I read that defining a transaction in a controller is not a good practice, can anyone help me solving this?
Regards
Upvotes: 0
Views: 123
Reputation: 4606
I think Danny's answer is the correct one. But, If you need to do the transaction anyway the controller it's not the place to do it. You can create a method in your model to achieve this.
For example:
class Model < ActiveRecord::Base
def self.some_method some_params
Model.transaction do
#do your stuff
#return true if ok.
end
end
end
Then in your controller:
def create
if Model.some_method #with the params you want to pass
#render success
else
#render error
end
end
Upvotes: 0
Reputation: 6025
As described in http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html, it is not necessary to explicitly save associations separately from their parents object.
In your case, as all objects created in your controller are "dependent", it is sufficient to first create all associations, using build, then finally save the parent object. This will automatically save all dependent associations.
Starting a transaction in a controller is only necessary when two or more totally independent, but somehow related, objects are created in the same action. The best example I can think of is a money transfer, with a debet and subsequent credit of two bank accounts. Both accounts are not "connected", but are very much dependent on each other: if one fails, the other should fail as well. That's when transactiond are the only solution!
Upvotes: 1