2009-10-09 11 views
12

Je souhaite une migration pour créer un clone d'une table existante en suffixant simplement le nom, y compris tous les index de la table d'origine. Il y a donc une table "snapshots" et je veux créer "snapshots_temp" comme une copie exacte de la table (pas les données, juste le schéma de la table, mais les index inclus).Comment cloner une table de base de données via la migration Rails?

Je pourrais simplement copier et coller le bloc hors du fichier schema.rb et le renommer manuellement.

Mais je ne suis pas sûr au moment où cette migration est appliquée si la définition de schema.rb sera toujours précise. Un autre développeur a peut-être changé la table et je ne veux pas avoir à mettre à jour mon script de migration.

Alors, comment puis-je obtenir le schéma de la table lors de l'exécution? Essentiellement, comment 'rake schema: dump' reverse-engineering la table afin que je puisse faire la même chose dans ma migration? (mais en changeant le nom de la table).

Répondre

21

Essayez de le faire avec du SQL pur. Cela va faire ce que vous voulez:

CREATE TABLE new_tbl LIKE orig_tbl; 
+0

Bon appel. "Utilisez LIKE pour créer une table vide basée sur la définition d'une autre table, y compris les attributs de colonne et les index définis dans la table d'origine" http://dev.mysql.com/doc/refman/5.1/fr/create-table. html –

+0

Fonctionne avec MySQL (et peut-être la plupart des bases de données) mais si vous utilisez Sqlite, cela ne fonctionnera pas. J'ai rencontré ce problème dans l'environnement de développement. La production est bonne (c'est MySQL). – MiniQuark

+1

Super merci. Notez que votre table copiée recevra les index, mais pas les clés étrangères. Vous devrez les recréer séparément. –

4

Cela fera l'affaire. Ce n'est pas parfait, car il ne copiera pas les options de table ou les index. Si vous avez défini des options de table, vous devrez les ajouter manuellement à cette migration.

Pour copier des index, vous devez formuler une requête SQL pour les sélectionner, puis les traiter dans les nouvelles directives add_index. C'est un peu au-delà de mes connaissances. Mais cela fonctionne pour copier la structure.

class CopyTableSchema < ActiveRecord::Migration 
    def self.up 
    create_table :new_models do |t| 
     Model.columns.each do |column| 
     next if column.name == "id" # already created by create_table 
     t.send(column.type.to_sym, column.name.to_sym, :null => column.null, 
      :limit => column.limit, :default => column.default, :scale => column.scale, 
      :precision => column.precision) 
     end 
    end 

    # copy data 

    Model.all.each do |m| 
     NewModel.create m.attributes 
    end 
    end 

    def self.down 
    drop_table :new_models 
    end 
end 
+0

> il ne copiera pas les options de table ou les index Merci, mais les index sont obligatoires. –

4

Dans Rails 4 & PostgreSQL, créez une nouvelle migration et insérer:

ActiveRecord::Base.connection.execute("CREATE TABLE clone_table_name AS SELECT * FROM source_table_name;") 

Cela va créer le clone avec la structure exacte de la table d'origine, et remplir la nouvelle table avec des anciennes valeurs.

Plus d'info: http://www.postgresql.org/docs/9.0/static/sql-createtableas.html

+1

Attention à cela car il copiera aussi la colonne ID et ne la mettra pas comme primaire dans la nouvelle table. –

0

Copiez les tables d'entrée de vos projets db/schema.rb directement dans votre migration. Il suffit de changer le nom de la table et votre bien à faire.