Транзакция Rails не откат
Почему бы не откат этой транзакции, если даже один создать! потерпит неудачу?
Это в контроллере, если это имеет значение.
def process_photos(photos)
ActiveRecord::Base.transaction do
begin
photos.each do |photo|
Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
end
rescue
raise ActiveRecord::Rollback
end
end
end
Я явно отправляю массив с некоторыми плохими записями. Хорошие создаются, а плохие - нет, но мне нужно все, чтобы откат, если даже один не удается.
Здесь мой rspec-тест (передача json-массива фотографий) и его увеличение.
expect { post :create, json }.not_to change(Photo, :count)
Ответы
Ответ 1
Это была просто проблема тестирования с rspec, потому что вы уже выполняете транзакцию в тесте. Это та же самая проблема вложенных транзакций, которая обсуждалась здесь here.
Чтобы тест прошел, вам нужно добавить…
requires_new: true
на вызов транзакции.
Это исправило тест.
def process_photos(photos)
ActiveRecord::Base.transaction(requires_new: true) do
begin
photos.each do |photo|
Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
end
rescue
raise ActiveRecord::Rollback
end
end
end
Важно: Откаты будут работать только в том случае, если ваша база данных их поддерживает! Например, MySQL с MyISAM не поддерживает транзакции, а MySQL с Inno DB их поддерживает.
Ответ 2
Вам нужно поставить начало вне блока, как это
def process_photos(photos)
begin
ActiveRecord::Base.transaction do
photos.each do |photo|
Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
end
rescue
raise ActiveRecord::Rollback
end
end
end
Ответ 3
Это также работает, без необходимости распространять исключение ActiveRecord :: Rollback.
def process_photos(photos)
begin
ActiveRecord::Base.transaction do
photos.each do |photo|
Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
end
end
rescue ActiveRecord::RecordInvalid
puts 'Transaction failed'
end
end