Comment écrivez-vous une migration pour renommer un modèle ActiveRecord et sa table dans Rails?

Je suis terrible à nommer et je me rends compte qu'il y a un meilleur ensemble de noms pour mes modèles dans mon application Rails.
Existe-t-il un moyen d'utiliser une migration pour renommer un modèle et sa table correspondante?

381
demandé sur user2262149 2009-01-23 03:25:42

4 réponses

Voici un exemple:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

J'ai dû renommer manuellement le fichier de déclaration du modèle.

Modifier:

Dans Rails 3.1 & 4, ActiveRecord::Migration::CommandRecorder sait comment inverser les migrations rename_table, vous pouvez donc faire ceci:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def change
    rename_table :old_table_name, :new_table_name
  end 
end

(vous devez toujours parcourir et renommer manuellement vos fichiers.)

548
répondu Readonly 2016-11-17 07:01:58

Dans Rails 4 Tout ce que j'avais à faire était le changement def

def change
  rename_table :old_table_name, :new_table_name
end

Et tous mes index ont été pris en charge pour moi. Je n'avais pas besoin de mettre à jour manuellement les index en supprimant les anciens et en ajoutant de nouveaux.

Et cela fonctionne en utilisant le changement pour monter ou descendre en ce qui concerne les index.

60
répondu bfcoder 2013-12-17 01:27:55

Les autres réponses et commentaires ont couvert le renommage de la table, le renommage du fichier et le passage de votre code.

Je voudrais ajouter quelques bémols:

Utilisons un exemple réel auquel j'ai fait face aujourd'hui: renommer un modèle de 'Merchant' en 'Business.'

  • N'oubliez pas de changer les noms des tables et des modèles dépendants la même migration. J'ai changé mes modèles Merchant et MerchantStat en Business et BusinessStat en même temps. Sinon j'aurais dû le faire aussi beaucoup de cueillette et de choix lors de la recherche-et-remplacer.
  • pour tous les autres modèles qui dépendent de votre modèle via des clés étrangères, les noms de colonnes de clés étrangères des autres tables seront dérivés de votre nom de modèle d'origine. Vous voudrez donc également faire des appels rename_column sur ces modèles dépendants. Par exemple, j'ai dû renommer la colonne 'merchant_id' en 'business_id' dans diverses tables de jointure (pour la relation has_and_belongs_to_many) et d'autres tables dépendantes (pour has_one normal et has_many relations). Sinon j'aurais fini avec des colonnes comme " business_stat.merchant_id ' pointant vers 'business.id'. Voici une bonne réponse à propos des renommages de colonnes.
  • lorsque grepping, n'oubliez pas de rechercher singulier, pluriel, majuscule, versions en minuscules et même en majuscules (ce qui peut se produire dans les commentaires) de vos chaînes.
  • Il est préférable de rechercher d'abord les versions plurielles, puis singulières. Que façon si vous avez un pluriel irrégulier - comme dans Mes marchands :: exemples d'entreprises - vous pouvez obtenir tous les pluriels irréguliers corrects. Sinon vous pouvez vous retrouver avec, par exemple, 'businesss' (3 s) comme un état intermédiaire, entraînant encore plus de recherche et remplacement.
  • ne remplacez pas aveuglément chaque occurrence. Si vos noms de modèle entrent en collision commune termes de programmation, avec des valeurs dans d'autres modèles, ou avec contenu textuel dans vos points de vue, vous pouvez finir par être trop impatient. Dans mon exemple, je voulais changer le nom de mon modèle en 'Business' mais toujours se référer à comme les "marchands" dans le contenu de mon INTERFACE. J'avais aussi un rôle "marchand" pour mes utilisateurs à CanCan - c'est la confusion entre le rôle marchand et le modèle marchand qui m'a amené à renommer le modèle en premier lieu.
43
répondu armchairdj 2017-05-23 10:31:39

Vous devez également remplacer vos index:

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

Et renommez vos fichiers, etc., manuellement comme le décrivent les autres réponses ici.

Voir: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

Assurez-vous que vous pouvez restaurer et rouler vers l'avant après avoir écrit cette migration. Cela peut devenir difficile si vous obtenez quelque chose de mal et que vous êtes coincé avec une migration qui essaie d'effectuer quelque chose qui n'existe plus. Mieux vaut vider toute la base de données et recommencer si vous ne le pouvez pas faire reculer. Alors soyez conscient que vous pourriez avoir besoin de sauvegarder quelque chose.

Aussi: Vérifiez schema_db pour tous les noms de colonnes pertinents dans d'autres tables définies par un has_ ou belongs_to ou quelque chose. Vous aurez probablement besoin de les éditer aussi.

Et enfin, faire cela sans une suite de tests de régression serait fou.

23
répondu Rimian 2012-12-05 22:24:04