完整错误是
ActiveRecord::StatementInvalid: Mysql2::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1
我正在编写一个单元测试,每当我尝试创建一个新的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 => 'foo@bar.com')
一切正常。但是,如果我在调用ActiveRecord :: Base.connection.execute之后尝试编写上面的行,那么我会得到上面描述的SAVEPOINT错误。我也尝试将我的执行语句放在一个事务中,但这没有帮助。我很难过。
仅供参考 - 我正在使用Rails 3.2.8
答案 0 :(得分:20)
您正在使用Mysql DDE语句(create / drop / truncate table),这将导致implicit commit。
由于隐式提交,当前事务的所有保存点都被删除(参见上面的文档)。
要解决此问题,您可以turn off transactions并使用DatabaseCleaner(截断模式)。
答案 1 :(得分:7)
要解决这个问题..
config.use_transactional_fixtures = false
答案 2 :(得分:2)
创建/删除表时可以使用“TEMPORARY”。
http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html 如果使用TEMPORARY关键字,则ALTER TABLE,CREATE TABLE和DROP TABLE不提交事务。 (这不适用于临时表上的其他操作,例如CREATE INDEX,它会导致提交。)但是,虽然没有发生隐式提交,但是语句都不能回滚。因此,使用此类语句将违反事务原子性:例如,如果使用CREATE TEMPORARY TABLE然后回滚事务,则该表仍然存在。
答案 3 :(得分:1)
只是澄清一下。您可以将触发MySql DDE语句的测试隔离到他们自己的文件中,然后在该文件中填写config.use_transactional_fixtures = false
。这样,所有其他测试都不会受到影响。现在,您负责清理隔离的测试文件。
答案 4 :(得分:0)
我找到了以下帮助我的链接:
答案 5 :(得分:0)
首先确保您已安装DatabaseCleaner gem,这将使您可以选择数据库清理策略。我们收到的错误意味着最好使用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