транзакция rails db не откатывается, если одно из обновлений db не удается

В моей модели есть следующий метод:

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

Я новичок в транзакциях в рельсах, но я понимал, что если одно из взаимодействий с базой данных не удастся, вся транзакция будет отменена. В приведенном выше коде строка:

self.update_attributes(task_params)

происходит сбой, поэтому обновление базы данных, которое происходит из self.task_finished в предыдущей строке, следует откатить. Почему-то не откатывается.

Для справочной информации, хотя я не думаю, что это должно иметь значение, строка "self.task_finished" использует гем state_machine для изменения состояния задачи. Однако он все равно должен откатиться. Что не так с моей транзакцией


person Philip7899    schedule 04.04.2014    source источник
comment
Если не ошибаюсь, надо использовать update_attributes!. Это вызовет исключение, запустив откат.   -  person Stefan    schedule 04.04.2014
comment
Спасибо, попробовал, и откат был выполнен, но он также останавливает запуск программы, и сообщения об ошибках не отображаются.   -  person Philip7899    schedule 04.04.2014


Ответы (1)


Вы неправильно понимаете, что представляет собой «неудача»; проверки записей не являются «ошибкой», они являются нормальной частью использования вашего приложения и не вызывают никакого отката базы данных.

Вам нужно либо явно отменить транзакцию, либо выйти из блока транзакции через исключение, чтобы транзакция завершилась ошибкой. В настоящее время вы успешно достигли конца транзакции, поэтому все благополучно зафиксировано в базе данных.

Как уже было предложено, лучшим решением является update_attributes!, который превращает ваши проверки в реальный сбой, вызывая исключение. Что касается вашей проблемы с _2 _...

попробовал это, и он сделал откат, но он также останавливает запуск программы, и сообщения об ошибках не отображаются

В этом-то и дело. Если ваш update_attributes! не работает, нет причин продолжать работу с остальной частью вашего кода, поскольку все, что делает, это создает / обновляет новые записи. Смысл транзакций - в любом случае откатить эти изменения, поэтому исключение отлично выполняет свою работу, предотвращая запуск этого кода.

Если ваши ошибки проверки не отображаются, вы должны обработать исключение и выполнить рендеринг в обычном режиме, чтобы Rails не отображал страницу с ошибкой, когда исключение покидает ваш метод.

person meagar    schedule 04.04.2014
comment
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. Что означает обработка исключения? - person Philip7899; 04.04.2014
comment
Перехватить исключение, чтобы оно не возвращалось вверх по стеку, чтобы его перехватил сам Rails. - person meagar; 04.04.2014
comment
Спасибо, я попробовал, и теперь появляются ошибки проверки, но откат не происходит. Я обновил свой код выше. - person Philip7899; 04.04.2014