2012-10-31 8 views
19

Der vollständige Fehler istActive Fehler: SAVE active_record_1 existiert nicht

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

ich einen Unit-Test schreibe und immer diese Fehlermeldung, wenn ich versuche, ein neues Active Objekt zu erstellen - aber erst nach einem gewissen Punkt. Dies geschieht nach diesen Zeilen:

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

(Die ‚foo‘ Tabelle mit Daten gefüllt werden, wenn mein Test erfolgreich)

Vor den obigen Zeilen, ich so etwas wie

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

schreiben und alles funktioniert gut. Wenn ich jedoch versuche, die obige Zeile nach meinem Aufruf von ActiveRecord :: Base.connection.execute zu schreiben, erhalte ich den oben beschriebenen SAVEPOINT-Fehler. Ich habe auch versucht, meine Execute-Anweisungen innerhalb einer Transaktion zu setzen, aber das hat nicht geholfen. Ich bin ratlos.

FYI - Ich bin mit Rails 3.2.8

Antwort

16

Sie verwenden Mysql DDE-Anweisungen (create/drop/truncate table) was zu einem implicit commit führt.

Aufgrund des impliziten Commits werden alle Sicherungspunkte der aktuellen Transaktion gelöscht (siehe obige Dokumentation).

Um dies zu umgehen, können Sie turn off transactions und DatabaseCleaner (Trunkierungsmodus) verwenden.

1

Sie können "TEMPORARY" verwenden, wenn Sie Tabellen erstellen/löschen.

http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html ALTER TABLE, CREATE TABLE und DROP TABLE übernehmen keine Transaktion, wenn das TEMPORARY-Schlüsselwort verwendet wird. (Dies gilt nicht für andere Operationen in temporären Tabellen wie CREATE INDEX, die eine Festschreibung verursachen.) Obwohl keine implizite Festschreibung erfolgt, kann die Anweisung jedoch auch nicht rückgängig gemacht werden. Daher wird die Verwendung von solchen Anweisungen die Atomizität von Transaktionen verletzen: Wenn Sie beispielsweise CREATE TEMPORARY TABLE verwenden und dann die Transaktion rückgängig machen, bleibt die Tabelle bestehen.

7

Um dieses Problem zu lösen ..

config.use_transactional_fixtures = false

1

Nur um zu klären. Sie können Tests isolieren, die MySql DDE-Anweisungen in ihre eigene Datei auslösen und dann config.use_transactional_fixtures = false in diese Datei stopfen. Auf diese Weise werden all Ihre anderen Tests nicht beeinträchtigt. Jetzt sind Sie für die Bereinigung in dieser isolierten Testdatei verantwortlich.

+0

Wie machst du das? –

Verwandte Themen