在我的Rails 3.2.13应用程序中,我正在使用Zeus。在测试环境中我使用PostgreSQL。当我运行Cucumber然后运行RSpec(或其他方式)时,10次中有9次我收到消息:
PG::Error: ERROR: database "bp_test" is being accessed by other users
DETAIL: There are 1 other session(s) using the database.
: DROP DATABASE IF EXISTS "bp_test"
Tasks: TOP => db:test:load => db:test:purge
(See full trace by running task with --trace)
如here所述,尝试杀死数据库连接以使其再次起作用需要一个完整的非确定性马戏团。但这并不总是有效,也是一个很大的麻烦。必须有一个更好的解决方案。有谁知道吗?
答案 0 :(得分:1)
受this answer的启发,我们创建了以下database.rake
文件。原始答案仅适用于PostgreSQL 9.1,这个修改后也适用于PostgreSQL 9.2。机制不是最漂亮的:当9.1命令失败时,它只是执行9.2命令。但最重要的是:它有效!
#{Rails.root}/lib/tasks/databases.rake
# monkey patch ActiveRecord to avoid There are n other session(s) using the database.
def drop_database(config)
case config['adapter']
when /mysql/
ActiveRecord::Base.establish_connection(config)
ActiveRecord::Base.connection.drop_database config['database']
when /sqlite/
require 'pathname'
path = Pathname.new(config['database'])
file = path.absolute? ? path.to_s : File.join(Rails.root, path)
FileUtils.rm(file)
when /postgresql/
begin
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by procpid;").each do |x|
if config['database'] == x['datname'] && x['current_query'] =~ /<IDLE>/
ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x['procpid']})")
end
end
ActiveRecord::Base.connection.drop_database config['database']
rescue # in PG 9.2 column procpid was renamed pid and the query status is checked not using 'current_query' but using 'state'
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by pid;").each do |x|
if config['database'] == x['datname'] && x['state'] =~ /idle/
ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x['pid']})")
end
end
ActiveRecord::Base.connection.drop_database config['database']
end
end
end
答案 1 :(得分:0)
namespace :db do
desc 'Clear the database'
task :clear_db => :environment do |t,args|
ActiveRecord::Base.establish_connection
ActiveRecord::Base.connection.tables.each do |table|
next if table == 'schema_migrations'
ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
end
end
desc 'Delete all tables (but not the database)'
task :drop_schema => :environment do |t,args|
ActiveRecord::Base.establish_connection
ActiveRecord::Base.connection.execute("DROP SCHEMA public CASCADE")
ActiveRecord::Base.connection.execute("CREATE SCHEMA public")
ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO postgres")
ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO public")
ActiveRecord::Base.connection.execute("COMMENT ON SCHEMA public IS 'standard public schema'")
end
desc 'Recreate the database and seed'
task :redo_db => :environment do |t,args|
# Executes the dependencies, but only once
Rake::Task["db:drop_schema"].invoke
Rake::Task["db:migrate"].invoke
Rake::Task["db:migrate:status"].invoke
Rake::Task["db:structure:dump"].invoke
Rake::Task["db:seed"].invoke
end
end