2016-04-18 2 views
2

J'ai une table de requêtes;Rails annule, change de type et migre à nouveau

class CreateRequests < ActiveRecord::Migration 
    def change 
    create_table :requests do |t| 
     t.string :from 
     t.string :to 

     t.timestamps null: false 
    end 
    end 
end 

Je voudrais rollback la base de données avec rake db:rollback STEP = 5 détruire le modèle de demande et de créer table de demande avec;

t.datetime :from 
t.datetime :to 

Cependant, j'ai une table de migration pour demander modèle de STEP = 2,

class AddStatusToRequest < ActiveRecord::Migration 
    def change 
    add_column :requests, :status, :string, :default => "Pending" 
    end 
end 

Le problème est, si je détruirai Demande table et créer un nouveau tableau de demande avec des types datetime il crée après l'étape = 2 et lorsque I rake db:migrate rails n'ajoute pas la colonne Etat à la table de requête. Comment puis-je surmonter cela?

+0

Qu'advient-il si vous exécutez la migration à partir de zéro? Avez-vous une erreur sur la migration 'AddStatusToRequest' car' requests' n'existe pas encore? –

+0

@AnthonyE, exactement. –

Répondre

3

Vous pouvez créer une nouvelle migration pour changer le type de colonne à l'aide change_column:

ligne de commande

: rails g migration change_request_to_from_column_types'

nouvelle migration:

class ChangeRequestToFromColumnTypes < ActiveRecord::Migration 
    def change 
    change_column :requests, :from, :datetime 
    change_column :requests, :to, :datetime 
    end 
end 
+0

J'ai utilisé cette méthode mais existe-t-il un autre moyen? –

+0

Si vous ne travaillez pas sur des données réelles, vous pouvez faire quelque chose comme 'rake db: migrer: redo VERSION = ' et répéter pour le fichier depuis l'étape = 2. Mais comme l'a souligné Anthony E., il est généralement préférable de ne pas modifier les migrations existantes. –

2

Il est préférable de ne pas modifier rétroactivement les migrations après leur application pour éviter les conflits d'état comme celui que vous avez. Peut-être la solution la plus simple est de créer une nouvelle migration pour ajouter les types à la table requests à l'aide d'un garde de ne rien faire si la colonne existe déjà:

class AddStatusToRequestIfNotExists < ActiveRecord::Migration 
    def change 
    unless column_exists? :requests, :status 
     add_column :requests, :status, :string, :default => "Pending" 
    end 
    end 
end 

EDIT

Vous voulez aussi assurez-vous que vous pouvez exécuter les migrations à partir de zéro, de sorte que vous pouvez mettre à jour votre migration existante pour se prémunir contre une table manquante comme suit:

class AddStatusToRequest < ActiveRecord::Migration 
    def change 
    unless table_exists? :requests 
     add_column :requests, :status, :string, :default => "Pending" 
    end 
    end 
end 

Pas idéal, mais il est probablement le plus sûr approche.