ActiveRecord::Migration
tiene el siguiente método privado que es llamada cuando se ejecuta migraciones:
def ddl_transaction(&block)
if Base.connection.supports_ddl_transactions?
Base.transaction { block.call }
else
block.call
end
end
Como se puede ver esto va a envolver la migración en una transacción si la conexión es compatible con ella.
En ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
tiene:
def supports_ddl_transactions?
true
end
SQLite versión 2.0 y más allá también apoyan las operaciones de migración. En ActiveRecord::ConnectionAdapters::SQLiteAdapter
tiene:
def supports_ddl_transactions?
sqlite_version >= '2.0.0'
end
Así pues, para saltar transacciones, tiene que sortear de alguna manera esto. Algo como esto podría funcionar, aunque no lo he probado:
class ActiveRecord::Migration
class << self
def no_transaction
@no_transaction = true
end
def no_transaction?
@no_transaction == true
end
end
private
def ddl_transaction(&block)
if Base.connection.supports_ddl_transactions? && !self.class.no_transaction?
Base.transaction { block.call }
else
block.call
end
end
end
A continuación, puede configurar la migración de la siguiente manera:
class SomeMigration < ActiveRecord::Migration
no_transaction
def self.up
# Do something
end
def self.down
# Do something
end
end
Informe a un poco más sobre la migración que se está ejecutando, la base de datos que está usando y qué adaptador en caso de que no sea el predeterminado mysql/sqlite. De esa manera, creo que una respuesta más útil seguirá su pregunta. – Ariejan
Lo siento, acabo de ver que estás usando Postgres. – Ariejan
En el caso de esta migración en particular, descubrí que el comando 'VACUUM' no es realmente necesario (solo hace la recolección de basura), por lo que eliminar esa llamada funcionó, pero todavía tengo curiosidad por saber cómo instruir a Rails para ejecutar migraciones sin transacciones. – hsribei