ruby on rails - Prueba de pepino y RSpec con zeus: otros usuarios acceden a Postgres
ruby-on-rails postgresql (2)
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
En mi aplicación Rails 3.2.13, estoy usando Zeus. En el entorno de prueba uso PostgreSQL. Cuando ejecuto Cucumber y luego RSpec (o al revés), 9 de cada 10 veces recibo el mensaje:
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)
Se necesita todo un circo no determinista de tratar de eliminar las conexiones de la base de datos para que esto vuelva a funcionar, como se describe aquí . Pero esto no siempre funciona y es una gran molestia también. Debe haber una mejor solución para esto. ¿Alguien sabe?
Inspirado por esta respuesta , creamos el siguiente archivo database.rake
. Donde la respuesta original funcionó solo para PostgreSQL 9.1, esta también se modificó para funcionar con PostgreSQL 9.2. El mecanismo no es el más bonito: cuando falla el comando 9.1, simplemente ejecuta el comando 9.2. Pero lo más importante: ¡funciona!
#{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