1

I have the following method in my model:

class Task < ActiveRecord::Base
 def update_completed_task(task_params, completed_material_params)
    puts 'in update_completed_task method'
    transaction do
        begin
            puts 'inside transaction'
            self.task_finished
            puts 'after task finished'
            self.update_attributes!(task_params)
            puts 'after update_attributes'
            if completed_material_params
                completed_material_params.each do |key, value|
                    @completed_material = CompletedMaterial.where("identity = ?", value).first
                    @completed_material.task = self
                    @completed_material.save
                end
            end
            puts 'affter loop'
            UserNotification.freelancer_has_submitted_documents(self.schedule.project, self)
            puts 'after user notification change'
        rescue
            puts 'in rescue again yolo gandi rollback'
        end
    end
 end
end

I am new to transactions in rails, but my understanding was that if one of the database interactions failed, the whole transaction would be rolled back. In the code above, the line:

self.update_attributes(task_params)

is failing, so the database update that occurs from self.task_finished on the line before should be rolled back. For some reason, it is not rolled back.

For background information, although i don't think it should make a difference, the "self.task_finished" line uses the state_machine gem to change the state of task. It should still rollback though. What is wrong with my transaction

2
  • If I'm not mistaken, you have to use update_attributes!. This will raise an exception, triggering the rollback. Commented Apr 4, 2014 at 18:42
  • Thanks, tried that and it did do the rollback, but it also stops the program from running and the error messages don't display. Commented Apr 4, 2014 at 18:51

1 Answer 1

1

You're misunderstanding what constitutes "failure"; record validations aren't "failure", they're a normal part of using your app, and they don't force any kind of database rollback.

You need to either explicitly cancel the transaction, or leave the transaction block via an exception, for the transaction to fail. Currently, you're successfully reaching the end of the transaction, so everything is happily committed to the database.

As suggested already, the best solution is update_attributes! which makes your validations into real failure by throwing an exception. As for your problem with update_attributes!...

tried that and it did do the rollback, but it also stops the program from running and the error messages don't display

That's the point. If your update_attributes! fails, there's no reason to proceed with the rest of your code, as all that does is create/update new records. The point of the transactions is to roll those changes back anyways, so the exception is doing its job perfectly by preventing that code from running.

If your validation errors aren't displaying, you should handle the exception and render normally to prevent Rails from rendering an error page when the exception leaves your method.

Sign up to request clarification or add additional context in comments.

3 Comments

If your validation errors aren't displaying, you should handle the exception and render normally to prevent Rails from rendering an error page when the exception leaves your method. What does handle the exception mean?
Catch the exception so that it doesn't travel back up the stack to be caught by Rails itself.
Thanks, i tried that and now the validation errors appear but the rollback does not occur. I updated my code above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.