ruby-on-rails postgresql rspec cucumber zeus

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