Подтвердить что ты не робот

Ошибка ActiveRecord: SAVEPOINT active_record_1 не существует

Полная ошибка

ActiveRecord::StatementInvalid: Mysql2::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1

Я пишу unit test и получаю эту ошибку всякий раз, когда пытаюсь создать новый объект ActiveRecord, но только после определенного момента. Это происходит после следующих строк:

ActiveRecord::Base.connection.execute "DROP TABLE IF EXISTS foo"
ActiveRecord::Base.connection.execute "CREATE TABLE foo (id INTEGER PRIMARY KEY)"

(Таблица "foo" будет заполнена данными, если мой тест завершится успешно)

Перед вышеприведенными строками я могу написать что-то вроде

User.create(email => '[email protected]')

и все работает отлично. Однако, если я попытаюсь написать вышеприведенную строку после моего вызова ActiveRecord:: Base.connection.execute, я получу эту ошибку SAVEPOINT, описанную выше. Я также попытался помещать свои операторы выполнения в транзакцию, но это не помогло. Я в тупике.

FYI - я использую Rails 3.2.8

4b9b3361

Ответ 1

Вы используете операторы Mysql DDE (создать/удалить/усечь таблицу), которые приведут к неявной фиксации.

Из-за неявной фиксации все точки сохранения текущей транзакции удаляются (см. Документацию выше).

Чтобы обойти это, вы можете отключить транзакции и использовать DatabaseCleaner (режим усечения).

Ответ 2

Чтобы решить эту проблему..

config.use_transactional_fixtures = false

Ответ 3

Вы можете использовать "ВРЕМЕННОЕ" при создании/удалении таблиц.

http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html ALTER TABLE, CREATE TABLE и DROP TABLE не выполняют транзакцию, если используется ключевое слово TEMPORARY. (Это не относится к другим операциям во временных таблицах, таких как CREATE INDEX, которые вызывают фиксацию.) Однако, хотя неявное совершение не происходит, ни один из операторов не может быть откат. Поэтому использование таких операторов будет нарушать атомарность транзакции: например, если вы используете CREATE TEMPORARY TABLE и затем откатываете транзакцию, таблица остается в силе.

Ответ 4

Просто уточнить. Вы можете изолировать тесты, которые запускают заявления MySql DDE в свой собственный файл, а затем вставить config.use_transactional_fixtures = false в этот файл. Таким образом, все ваши другие тесты не будут затронуты. Теперь вы отвечаете за очистку в этом изолированном тестовом файле.

Ответ 6

Сначала убедитесь, что у вас установлен гем DatabaseCleaner, который позволит вам выбрать стратегию очистки БД. Ошибка, которую мы получаем, означает, что будет лучше использовать стратегию truncation.

# file: Gemfile

group :test do
  gem ‘database_cleaner
end

Добавьте конфигурацию DatabaseCleaner в каталог функций (см. Ниже).

#file: features/support/database_cleaner.rb

begin
  require 'database_cleaner'
  require 'database_cleaner/cucumber'

  DatabaseCleaner.strategy = :truncation
rescue NameError
  raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end

Around do |scenario, block|
  DatabaseCleaner.cleaning(&block)
end