2012-01-10 8 views
31

Parece que no puedo encontrar una opción o algo que me permita omitir las migraciones.¿Cómo se saltea las migraciones fallidas? (rake db: migrate)

Sé lo que estás pensando: "nunca debería tener que hacer eso ..."

tengo que saltar una migración que realiza cambios en los registros de usuarios específicos que no existen en mi base de datos de desarrollo . No quiero cambiar la migración porque no es parte de la fuente con la que se supone que debo trabajar. ¿Hay alguna manera de omitir una migración u omitir migraciones fallidas?

¡Gracias de antemano!

Respuesta

53

Creo que debería arreglar las migraciones ofensivas para que sean menos frágiles, supongo que un par de declaraciones if y quizás un rescue serían suficientes.

Pero, si corregir las migraciones realmente no es una opción, puede falsificarlo de varias maneras. En primer lugar, puede comentar los métodos de migración, ejecutar rake db:migrate, y luego descomentar (o revertir) la migración ofensiva.

También puede falsificarlo dentro de la base de datos, pero este tipo de trapacería no es recomendable a menos que sepa lo que está haciendo y no le moleste arreglar manualmente cuando (inevitablemente) comete un error. Hay una tabla en su base de datos llamada schema_migrations que tiene una sola columna varchar(255) llamada version; db:migrate utiliza esta tabla para realizar un seguimiento de las migraciones que se han aplicado. Todo lo que necesita hacer es INSERTAR el valor apropiado version y rake db:migrate pensará que la migración se ha realizado. Encontrar el archivo de migración infractor:

db/migrate/99999999999999_XXXX.rb 

luego ir en su base de datos y dicen:

insert into schema_migrations (version) values ('99999999999999'); 

donde 99999999999999 es, por supuesto, el número de nombre de archivo de la migración. Luego ejecutar rake db:migrate debe omitir esa migración.

Iría con la segunda opción antes de la tercera, solo estoy incluyendo la opción "hackear schema_versions" para que esté completa.

+0

Ya, yo sólo siguieron adelante y cortar las migraciones ofensivos temporalmente. Personalmente, habría creado las sentencias If correctas o simplemente hubiera verificado el entorno de producción, pero aparentemente la persona que maneja las migraciones no cree en usar db: migrate al desarrollar = P Gracias – hmind

+0

@hmind: "la persona que maneja el migrations no cree en usar db: migrate mientras se desarrolla ". Oh mi. ¡Publicar en sus sistemas de producción debe ser un momento de diversión súper feliz! –

+2

afortunadamente, yo no manejo eso tampoco jaja – hmind

1

En lugar de omitir la migración puede hacer su migración inteligente, añadiendo un poco de SI a la misma, para que pueda comprobar "usuarios específicos"

+0

Sí, eso es lo que habría hecho si hubiera escrito la migración. Pero no lo hice y realmente no quiero meterme con parte de la fuente que se supone que no debo tocar, así que terminé cortando temporalmente. – hmind

14

Esta es una buena manera de hacerlo por errores puntuales.

db:migrate:up VERSION=my_version

Esto ejecutará "arriba" las acciones de una migración específica. (También existe el opuesto si lo necesita, simplemente reemplace "arriba" por "abajo"). De esta forma puede ejecutar la migración futura que hace que la anterior (que necesita saltear) funcione, o simplemente ejecutar cada migración por delante selectivamente.

también creo que se puede hacer de nuevo las migraciones de esta manera:

rake db:migrate:redo VERSION=my_version

no he probado personalmente ese método, por lo que tu caso es distinto.

1

veces, es necesario volver a llenar schema_migrations mesa con migraciones definitivamente correctas ... SOLAMENTE PARA ESTE FIN he creado este método

def self.insert_missing_migrations(stop_migration=nil) 
    files = Dir.glob("db/migrate/*") 
    timestamps = files.collect{|f| f.split("/").last.split("_").first} 
    only_n_first_migrations = timestamps.split(stop_migration).first 

    only_n_first_migrations.each do |version| 
    sql = "insert into `schema_migrations` (`version`) values (#{version})" 
    ActiveRecord::Base.connection.execute(sql) rescue nil 
    end 
end 

puede copiar-pegar en cualquier modelo que desee y utilizarla desde la consola

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx") 

(o alguna otra manera)

donde "xxxxxxxxxxxxxx" - es marca de tiempo de migración antes de que desea dejar de inserción (lo puede dejar vacío)

!!! ¡Úselo solo si comprende completamente qué resultado obtendrá!

10

tuve un problema por el que tenía una migración de añadir una tabla que ya existía, por lo que en mi caso tuve que saltar esta migración, así, porque yo estaba consiguiendo el error

SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts" 

simplemente Comentó el contenido del método create table, ejecutó la migración y luego lo descomentó. Es una especie de forma manual para evitarlo, pero funcionó. Consulte a continuación:

class CreatePosts < ActiveRecord::Migration 
    def change 
    # create_table :posts do |t| 
    # t.string :title 
    # t.text :message 
    # t.string :attachment 
    # t.integer :user_id 
    # t.boolean :comment 
    # t.integer :phase_id 

    # t.timestamps 
    # end 
    end 
end 
+0

¡Esto es genial! No puedo creer que no haya pensado en esto. Totalmente trabajado. – helpse

7

Si tiene que hacer eso, ¡las migraciones de su aplicación están en mal estado!

inserciones todas las migraciones faltantes:

def insert(xxx) 
    ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil 
end 

files = Dir.glob("db/migrate/*") 
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) } 
+1

No necesariamente. Por ejemplo, si pg_restaura su base de datos de producción a su máquina de desarrollo para solucionar un problema con los datos de producción. No sea tan rápido decirle a alguien que lo está haciendo mal cuando no tenga toda la información. –

+0

@MikeBethany: en mi caso fue cuando tuve que usarlo, todo fue un gran desastre y no tuve tiempo de entender por qué se puso así. Acerca de pg_restore, también debería restaurar la tabla 'schema_migrations', supongo ¿no? – Dorian

+0

Sí, por supuesto, la tabla 'schema_migrations' es solo una tabla en la base de datos. Releyendo tu título, puedo ver otra interpretación. Originalmente lo leí como "No escribiste tus migraciones correctamente". Lo que creo que en realidad quieres decir es: "Hay un problema con las migraciones". Pero eso es obvio, de ahí la pregunta, así que asumí el significado de "te equivocaste". Mi error. –

Cuestiones relacionadas