Come posso rinominare una colonna del database in una migrazione Ruby on Rails?


Risposte:


2309
rename_column :table, :old_column, :new_column

Probabilmente vorrai creare una migrazione separata per farlo. (Rinomina FixColumnNamecome vuoi.):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Quindi modifica la migrazione per fare la tua volontà:

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Per Rails 3.1 utilizzare:

Mentre i metodi upe downcontinuano a essere validi, Rails 3.1 riceve un changemetodo che "sa come migrare il database e invertirlo quando la migrazione viene ripristinata senza la necessità di scrivere un metodo down separato".

Vedere " Migrazioni di record attivi " per ulteriori informazioni.

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

Se ti capita di avere un sacco di colonne da rinominare, o qualcosa che avrebbe richiesto la ripetizione ripetuta del nome della tabella:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

Puoi usare change_tableper mantenere le cose un po 'più ordinate:

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Quindi db:migratecome al solito o comunque fai i tuoi affari.


Per Rails 4:

Durante la creazione di a Migrationper rinominare una colonna, Rails 4 genera un changemetodo anziché upe downcome indicato nella sezione precedente. Il changemetodo generato è:

$ > rails g migration ChangeColumnName

che creerà un file di migrazione simile a:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

24
self.down dovrebbe sempre essere l'opposto di self.up, quindi "se hai bisogno o fai qualcos'altro o non fai nulla" non è davvero raccomandato. Basta fare: rename_column: table_name,: new_column,: old_column
Luke Griffiths,

3
Mentre è prassi normale ripristinare ciò che hai fatto self.upnon direi self.down"dovrei sempre essere contrario". In dipende dal contesto della migrazione. Mettere il "contrario" potrebbe non essere la "giusta" down migrazione.
nowk,

23
In Rails 3.1 è possibile sostituire def self.upe def self.downcon def changee saprà eseguire il rollback.
Turadg,

2
Turadg - * saprà eseguire il rollback la maggior parte delle volte. Trovo che il changemetodo non sia una prova completa, quindi tendo a usare upe downmetodi per migrazioni complesse.
JellyFishBoy,

6
La ridenominazione rimuove l'indice?
Cantato Cho

68

A mio avviso, in questo caso, è meglio usare rake db:rollback, quindi modificare la migrazione ed eseguire nuovamente rake db:migrate.

Tuttavia, se nella colonna sono presenti dati che non si desidera perdere, utilizzare rename_column.


34
Anche in un "team di uno", se hai più istanze della tua app in esecuzione, diciamo in ambienti diversi o su più computer, ecc., Gestire le migrazioni modificate è un grosso problema. Modifico una migrazione solo se l'ho appena creata e ho capito che era sbagliata e non l'ho ancora eseguita letteralmente altrove.
Yetanotherjosh,

1
Dopo di ciò ho dovuto riavviare il server.
Muhammad Hewedy,

7
Questa tecnica dovrebbe essere utilizzata solo in una situazione in cui le modifiche non sono state ancora unite al ramo di produzione e altre non dipendono dalla persistenza dei dati. Nella maggior parte delle circostanze di produzione, questo NON è il metodo preferito.
Collin Graves,

4
mai e poi mai fare questo tipo di cose.
new2cpp,

4
Mi piace dire al mio team: "Le migrazioni sono gratuite" Il costo di modifica di una migrazione che è stata rilasciata in natura è elevato: una volta ho trascorso alcune ore a capire perché il mio codice non funzionava prima di realizzare un altro membro del team era tornato indietro e aveva modificato una migrazione che avevo già eseguito. Quindi non modificare una migrazione esistente, usane una nuova per cambiare lo schema, perché ... ... "Le migrazioni sono gratuite!" (Non è rigorosamente vero, ma chiarisce il punto)
TerryS,

31

Se la colonna è già popolata con dati e vive in produzione, consiglierei un approccio graduale, in modo da evitare tempi di inattività nella produzione in attesa delle migrazioni.

Innanzitutto creerei una migrazione db per aggiungere colonne con i nuovi nomi e popolarli con i valori dal vecchio nome di colonna.

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Quindi commetterei proprio quel cambiamento e spingerei il cambiamento in produzione.

git commit -m 'adding columns with correct name'

Quindi, una volta che il commit è stato messo in produzione, corro.

Production $ bundle exec rake db:migrate

Quindi aggiornerei tutte le viste / i controller che facevano riferimento al vecchio nome di colonna al nuovo nome di colonna. Esegui la mia suite di test e apporta solo quelle modifiche. (Dopo essersi accertato che funzionasse localmente e prima avesse superato tutti i test!)

git commit -m 'using correct column name instead of old stinky bad column name'

Quindi spingerei questo impegno nella produzione.

A questo punto puoi rimuovere la colonna originale senza preoccuparti di alcun tipo di downtime associato alla migrazione stessa.

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Quindi spingere quest'ultima migrazione verso la produzione ed eseguirla bundle exec rake db:migratein background.

Mi rendo conto che questo è un po 'più coinvolto in un processo, ma preferirei farlo piuttosto che avere problemi con la mia migrazione di produzione.


2
Mi piace pensare dietro questo, e farei +1 sulla tua risposta, ma l'aggiornamento dei dati richiederebbe molto tempo per essere eseguito poiché passa attraverso le rotaie e fa una riga alla volta. La migrazione verrebbe eseguita molto più velocemente con istruzioni sql non elaborate per aggiornare le colonne con nome corretto. Ad esempio, nel primo script di migrazione db, dopo aver aggiunto i nomi delle colonne duplicate, execute "Update table_name set correct_name_column_one = old_name_column_one"
Gui Weinmann,

1
@ mr.ruh.roh ^ Completamente d'accordo, avrei dovuto scriverlo in primo luogo. Ho modificato per riflettere una singola istruzione sql efficiente. Grazie per il controllo di sanità mentale.
Paul Pettengill,

2
Che cosa succede con le voci tra lo spostamento nella nuova tabella e l'aggiornamento del codice per utilizzare la nuova tabella? Non potresti avere dati potenzialmente non migrati rimasti?
Stefan Dorunga,

1
mentre questa è una risposta "sicura", ritengo che sia incompleta. Molte persone qui dicono di non farlo, perché? persistenza dei dati. E questo è valido. Probabilmente il modo meno doloroso per raggiungere l'obiettivo è creare i nuovi campi, popolarli con i dati delle vecchie colonne, regolare i controller. Se vuoi eliminare le vecchie colonne, dovrai sicuramente modificare le viste. Il costo per mantenerli è uno spazio aggiuntivo in db e qualche sforzo duplicato nel controller. I compromessi sono quindi chiari.
Jerome,


18

Esegui il comando seguente per creare un file di migrazione:

rails g migration ChangeHasedPasswordToHashedPassword

Quindi nel file generato nella db/migratecartella, scrivi rename_columncome di seguito:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

14

Dall'API:

rename_column(table_name, column_name, new_column_name)

Rinomina una colonna ma mantiene il tipo e il contenuto rimane lo stesso.


12

Alcune versioni di Ruby on Rails supportano il metodo su / giù per la migrazione e se hai un metodo su / giù nella tua migrazione, allora:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

Se hai il changemetodo nella tua migrazione, allora:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

Per ulteriori informazioni è possibile spostare: Ruby on Rails: migrazioni o migrazioni di record attivi .


11

Se il tuo codice non è condiviso con un altro, l'opzione migliore è fare semplicemente rake db:rollback modificare il nome della colonna durante la migrazione e rake db:migrate. Questo è tutto

E puoi scrivere un'altra migrazione per rinominare la colonna

 def change
    rename_column :table_name, :old_name, :new_name
  end

Questo è tutto.


rake db:rollbackè un ottimo suggerimento. Ma come hai detto, solo se la migrazione non è stata ancora spinta.
danielricecodes

9

In alternativa, se non sei sposato con l'idea delle migrazioni, esiste una gemma avvincente per ActiveRecord che gestirà automaticamente le modifiche del nome, stile Datamapper. Tutto quello che fai è cambiare il nome della colonna nel tuo modello (e assicurati di mettere Model.auto_upgrade! Nella parte inferiore del tuo modello.rb) e viola! Il database viene aggiornato al volo.

https://github.com/DAddYE/mini_record

Nota: è necessario eseguire il nuke di db / schema.rb per prevenire conflitti

Ancora in fase beta e ovviamente non per tutti ma comunque una scelta convincente (lo sto attualmente utilizzando in due app di produzione non banali senza problemi)


8

Se è necessario cambiare i nomi delle colonne, sarà necessario creare un segnaposto per evitare un errore di nome della colonna duplicato . Ecco un esempio:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end

7

Se i dati attuali non sono importanti per te, puoi semplicemente annullare la migrazione originale usando:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

Senza le virgolette, quindi apportare modifiche alla migrazione originale ed eseguire nuovamente la migrazione verso l'alto:

rake db:migrate

6

Basta creare una nuova migrazione e, in un blocco, utilizzare rename_columncome di seguito.

rename_column :your_table_name, :hased_password, :hashed_password

6

Per Ruby on Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end

5

Manualmente possiamo usare il metodo seguente:

Possiamo modificare manualmente la migrazione come:

  • Aperto app/db/migrate/xxxxxxxxx_migration_file.rb

  • Aggiorna hased_passwordahashed_password

  • Esegui il comando seguente

    $> rake db:migrate:down VERSION=xxxxxxxxx

Quindi rimuoverà la migrazione:

$> rake db:migrate:up VERSION=xxxxxxxxx

Aggiungerà la tua migrazione con la modifica aggiornata.


non sarà sicuro perché potresti perdere dati - se la colonna è già attiva. ma può fare per la nuova colonna e / o tabella.
Tejas Patel,

5

Genera il file di migrazione:

rails g migration FixName

# Crea db / migrate / xxxxxxxxxx.rb

Modifica la migrazione per fare la tua volontà.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

5

Esegui rails g migration ChangesNameInUsers(o come vuoi nominarlo)

Apri il file di migrazione che è stato appena generato e aggiungi questa riga nel metodo (tra def changee end):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

Salvare il file ed eseguirlo rake db:migratenella console

Controlla il tuo schema.dbper vedere se il nome è stato effettivamente modificato nel database!

Spero che sia di aiuto :)


5

Facciamo BACIO . Bastano tre semplici passaggi. Quanto segue funziona per Rails 5.2 .

1 Crea una migrazione

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName- in questo modo è perfettamente chiaro ai manutentori della base di codice in seguito. (usa un plurale per il nome della tabella).

2. Modifica la migrazione

# I prefer to explicitly write thesu andgiùmethods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end

3. Esegui le tue migrazioni

rake db:migrate

E sei partito per le gare!


4
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

Apri quel file di migrazione e modifica quel file come di seguito (inserisci il tuo originale table_name)

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end

4
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end

3

Genera una migrazione Ruby on Rails :

$:> rails g migration Fixcolumnname

Inserisci il codice nel file di migrazione (XXXXXfixcolumnname.rb) :

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

2

Apri la tua console Ruby on Rails ed inserisci:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

2

Hai due modi per farlo:

  1. In questo tipo, esegue automaticamente il codice inverso, al momento del rollback.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
  2. Per questo tipo, esegue il metodo up quando rake db:migratee il metodo down quando rake db:rollback:

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end

2

Sono su rotaie 5.2 e sto provando a rinominare una colonna su un utente ideato.

il rename_columnbit ha funzionato per me, ma il singolare :table_nameha generato un errore "Tabella utente non trovata". Plural ha funzionato per me.

rails g RenameAgentinUser

Quindi modificare il file di migrazione in questo:

rename_column :users, :agent?, :agent

Dove: agente? è il vecchio nome della colonna.


0

Aggiornamento - Un cugino stretto di create_table è change_table, utilizzato per modificare le tabelle esistenti. Viene usato in modo simile a create_table ma l'oggetto ceduto al blocco conosce più trucchi. Per esempio:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

In questo modo è più efficiente se lo facciamo con altri metodi di modifica come: rimuovi / aggiungi indice / rimuovi indice / aggiungi colonna, ad esempio possiamo fare ulteriormente come:

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...

0

Basta generare la migrazione usando il comando

rails g migration rename_hased_password

Dopo aver modificato la migrazione, aggiungere la seguente riga nel metodo change

rename_column :table, :hased_password, :hashed_password

Questo dovrebbe fare il trucco.


0

Rails 5 modifiche alla migrazione

per esempio:

rotaie g modello Student nome_ studente: stringa età: intero

se vuoi cambiare la colonna student_name come nome

Nota: - se non si esegue rails db: migrate

Puoi fare i seguenti passi

rotaie modello Student nome_ studente: stringa età: intero

Questo rimuoverà il file di migrazione generato, Ora puoi correggere il nome della tua colonna

rotaie modello g Nome dello studente: stringa età: intero

Se è stata eseguita la migrazione (rails db: migrate), seguire le opzioni per modificare il nome della colonna

rails g migrazione RemoveStudentNameFromStudent nome_ studente: stringa

rotaie g AddNameToStudent nome: stringa


Non dovrebbe essere: rails g migration RemoveStudentNameFromStudentS student_name:string(gli studenti sono plurali)?
BKSpurgeon,

Anche questo è pericoloso: la colonna non viene rinominata, ma completamente rimossa e quindi ritoccata. Cosa accadrà ai dati? Questo potrebbe non essere quello che l'utente vorrà.
BKSpurgeon,
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.