ActiveRecord::Migration
ha il seguente metodo privato che viene chiamato durante l'esecuzione di migrazioni:
def ddl_transaction(&block)
if Base.connection.supports_ddl_transactions?
Base.transaction { block.call }
else
block.call
end
end
Come si può vedere questo andrà a capo la migrazione in una transazione se la connessione supporta.
In ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
si hanno:
def supports_ddl_transactions?
true
end
SQLite versione 2.0 e al di là anche supportare le transazioni di migrazione. In ActiveRecord::ConnectionAdapters::SQLiteAdapter
si hanno:
def supports_ddl_transactions?
sqlite_version >= '2.0.0'
end
Allora, per saltare le transazioni, è necessario aggirare in qualche modo questo. Qualcosa di simile potrebbe funzionare, anche se non ho provato:
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
È quindi possibile impostare la migrazione come segue:
class SomeMigration < ActiveRecord::Migration
no_transaction
def self.up
# Do something
end
def self.down
# Do something
end
end
fonte
2009-10-04 21:45:36
Informi un po 'di più la migrazione è in esecuzione, il database sei usando e quale adattatore nel caso non sia quello predefinito mysql/sqlite. In questo modo penso che una risposta più utilizzabile seguirà la tua domanda. – Ariejan
Mi dispiace, ho appena visto che stai usando Postgres. – Ariejan
Nel caso di questa particolare migrazione ho scoperto che il comando 'VACUUM' non è realmente necessario (fa solo la garbage collection), quindi la rimozione della chiamata ha funzionato, ma sono comunque curioso di sapere come istruire Rails a funzionare migrazioni senza transazioni. – hsribei