Come si scrive una migrazione per rinominare un modello ActiveRecord e la sua tabella in Rails?


408

Sono terribile nel nominare e mi rendo conto che ci sono un set migliore di nomi per i miei modelli nella mia app Rails.
Esiste un modo per utilizzare una migrazione per rinominare un modello e la tabella corrispondente?


11
Ho suggerito di aggiungere "ActiveRecord" a questa domanda per migliorare le corrispondenze dei motori di ricerca. Ho cercato questo usando "ActiveRecord rename table".
Landon Kuhn,

6
Se si utilizzano le migrazioni, questo problema è più complicato di quanto sembri. La soluzione selezionata dice di tornare indietro e rinominare manualmente il modello, il controller, ecc. Dopo aver modificato il nome della tabella. In tal caso, tutte le migrazioni precedenti che fanno riferimento al modello in base al nome precedente avranno esito negativo. Quindi, quando qualcuno clona il tuo repository e cerca di eseguire rake db:migrate, fallirà. Potresti tornare indietro e cambiare quei nomi nella migrazione, ma diventerà disordinato. Potresti stare meglio semplicemente creando un modello completamente nuovo piuttosto che rinominarlo.
Andrew,

4
@andrewhannigan: Il tuo punto è controverso se qualcuno clona il tuo repository e corre rake db:schema:load?
istrasci

3
@istrasci: assolutamente. In effetti, correre rake db:migrateper creare un database da zero è attivamente scoraggiato, proprio a causa delle preoccupazioni evidenziate da Andrew.
Giuseppe,

Risposte:


584

Ecco un esempio:

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

Ho dovuto andare e rinominare il file di dichiarazione del modello manualmente.

Modificare:

In Rails 3.1 e 4, ActiveRecord::Migration::CommandRecordersa come invertire le migrazioni rename_table, quindi puoi farlo:

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

(Devi ancora passare e rinominare manualmente i tuoi file.)


6
@mathee: sì, devi cambiarlo manualmente o usando un IDE che può eseguire il refactoring di Ruby e impegnarlo nel tuo sistema di controllo della versione.
pupeno,

13
git grep è tuo amico. Sto rinominando un'attività in un'abitudine in questo momento: git grep -i activitè molto rivelatore.
Felix Rabe,

1
devi anche cambiare il contenuto del tuo controller, giusto?
alemur,

5
E non dimenticare i tuoi percorsi.rb!
Dan Herman,

26
Inoltre, proprio come un avvertimento, si desidera utilizzare la versione plurale del nome della tabella nella chiamata rename_table.
Han,

66

In Rails 4 tutto quello che dovevo fare era il cambio di def

def change
  rename_table :old_table_name, :new_table_name
end

E tutti i miei indici sono stati curati per me. Non ho avuto bisogno di aggiornare manualmente gli indici rimuovendo quelli vecchi e aggiungendone di nuovi.

E funziona usando la modifica per salire o scendere anche per quanto riguarda gli indici.


47

Le altre risposte e commenti hanno riguardato la ridenominazione della tabella, la ridenominazione dei file e il grepping nel codice.

Vorrei aggiungere qualche avvertimento in più:

Facciamo un esempio del mondo reale che ho affrontato oggi: rinominare un modello da "Commerciante" a "Affari".

  • Non dimenticare di modificare i nomi delle tabelle e dei modelli dipendenti nella stessa migrazione. Ho cambiato contemporaneamente i miei modelli Merchant e MerchantStat in Business e BusinessStat. Altrimenti avrei dovuto fare troppa raccolta e scelta durante l'esecuzione di ricerca e sostituzione.
  • Per tutti gli altri modelli che dipendono dal modello tramite chiavi esterne, i nomi delle colonne delle chiavi esterne delle altre tabelle verranno derivati ​​dal nome del modello originale. Quindi vorrai anche fare alcune chiamate rename_column su questi modelli dipendenti. Ad esempio, ho dovuto rinominare la colonna "merchant_id" in "business_id" in varie tabelle di join (per relazioni has_and_belongs_to_many) e altre tabelle dipendenti (per normali relazioni has_one e has_many). Altrimenti sarei finito con colonne come "business_stat.merchant_id" che punta a "business.id". Ecco una buona risposta su come rinominare le colonne.
  • Quando si esegue il grepping, ricordarsi di cercare versioni singolari, plurali, maiuscole, minuscole e persino MAIUSCOLE (che possono verificarsi nei commenti) delle stringhe.
  • È meglio cercare prima le versioni plurale, quindi singolari. In questo modo se hai un plurale irregolare - come nell'esempio dei miei commercianti :: imprese - puoi ottenere tutti i plurali irregolari corretti. Altrimenti potresti finire, ad esempio, con le "imprese" (3 secondi) come stato intermedio, ottenendo ancora più ricerca e sostituzione.
  • Non sostituire ciecamente ogni ricorrenza. Se i nomi dei tuoi modelli si scontrano con termini di programmazione comuni, con valori in altri modelli o con contenuti testuali nelle tue viste, potresti finire per essere troppo entusiasta. Nel mio esempio, volevo cambiare il nome del mio modello in "Business" ma ancora fare riferimento a loro come "commercianti" nel contenuto dell'interfaccia utente. Ho anche avuto un ruolo di "commerciante" per i miei utenti in CanCan: è stata la confusione tra il ruolo di commerciante e il modello del commerciante che mi ha portato a rinominare il modello in primo luogo.

26

Devi anche sostituire i tuoi indici:

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

E rinomina i tuoi file ecc. Manualmente, come descrivono le altre risposte qui.

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

Assicurati di poter eseguire il rollback e il rollforward dopo aver scritto questa migrazione. Può diventare complicato se sbagli qualcosa e rimani bloccato con una migrazione che tenta di effettuare qualcosa che non esiste più. È consigliabile eliminare l'intero database e ricominciare se non è possibile eseguire il rollback. Quindi tieni presente che potresti dover eseguire il backup di qualcosa.

Inoltre: controlla schema_db per eventuali nomi di colonna pertinenti in altre tabelle definite da has_ ​​o appartiene_to o qualcosa del genere. Probabilmente dovrai modificare anche quelli.

E infine, fare questo senza una suite di test di regressione sarebbe folle.


11
Per quanto riguarda le migrazioni di rails 4.0.0.beta1, non è necessario aggiornare gli indici manualmente. AR lo aggiorna da solo.
freemanoid,

1

Puoi eseguire questo comando: rails g migrazione rename_ {old_table_name} in {new_table_name}

dopo aver modificato il file e aggiunto questo codice nella modifica del metodo

rename_table: {old_table_name},: {new_table_name}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.