Rinominare la tabella in rotaie


154

Voglio rinominare una tabella ... (qualsiasi tabella.)

Ho provato questa riga di codice:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Ecco la cosa strana. So di averlo fatto funzionare la prima volta, ma ora ho questo errore: metodo indefinito `rename_table 'per ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

C'era qualcosa che devo impostare?

Risposte:


248

In genere si fa questo genere di cose in una migrazione:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end

1
Grazie che ha funzionato! Sono ancora perplesso sul perché la riga precedente non l'abbia fatto. Oh bene ..
Tommy,

@ Tommy, il rename_tablemetodo è definito in ActiveRecord::ConnectionAdapters::SchemaStatements. È pensato per essere miscelato con altri moduli. Se volessi eseguirlo direttamente, penso che potresti farloinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam

oppure potresti usare ActiveRecord :: Migration.rename_table (: foo,: bar) se eri così incline. Ma la migrazione funziona meglio. Vorresti anche cambiare il nome del modello o vuoi conservare il nome del modello come quello vecchio? In tal caso, potresti voler specificare il nome della tabella nel modello ActiveRecord usando "set_table_name: bar".
Aditya Sanghi,

1
Puoi anche utilizzare il nuovo modulo per le migrazioni con il metodo "modifica" anziché su e giù. esempio
MegaTux il

def change, non def self.up / def.self.down nelle moderne implementazioni di Rails. Fare quest'ultimo fallirà silenziosamente.
Huertanix,

294

Ricorda che in Rails> = 3.1 puoi usare il changemetodo.

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

37
Questo sarà anche la migrazione di tutti gli indici da :old_table_nameal:new_table_name
Gavin Miller

7
Solo un piccolo commento: forse cambia in: old_named_things,: new_named_things per ricordare alle persone che i nomi delle tabelle in activerecord sono generalmente pluralizzati.
Carpela,

24

.rename_tableè un metodo di istanza, non un metodo di classe, quindi la chiamata Class.methodnon funzionerà. Invece dovrete creare un'istanza della classe, e chiamare il metodo nell'istanza, in questo modo: Class.new.method.

[EDIT] In questo caso, ActiveRecord::ConnectionAdapters::SchemaStatementsnon è nemmeno una classe (come sottolineato da cam), il che significa che non puoi nemmeno crearne un'istanza come da quello che ho detto sopra. E anche se hai usato l'esempio di cam class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, non funzionerebbe ancora perché rename_tablesolleva un'eccezione.

D'altra parte, ActiveRecord::ConnectionAdapters::MysqlAdapter è una classe ed è probabile che questa classe dovresti usare per rinominare la tua tabella (o SQLite o PostgreSQL, a seconda del database che stai usando). Ora, come succede, ActiveRecord::ConnectionAdapters::MysqlAdapterè già accessibile attraverso Model.connection, quindi dovresti essere completamente in grado di fare Model.connection.rename_table, usando qualsiasi modello nella tua applicazione. [/MODIFICARE]

Tuttavia, se desideri rinominare in modo permanente una tabella, ti suggerirei di utilizzare una migrazione per farlo. È facile e il modo preferito di manipolare la struttura del database con Rails. Ecco come farlo:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Quindi, è possibile eseguire la migrazione con rake db:migrate(che chiama il self.upmetodo) e utilizzare rake db:rollback(che chiama self.down) per annullare la migrazione.


Sono d'accordo che si rename_tabletratta di un metodo di istanza, ma non è definito in una classe, quindi il tuo suggerimento di chiamare Class.new.methodnon funzionerà (ad esempio: ActiveRecord::ConnectionAdapters::SchemaStatements.newdà l'errore oMethodError: undefined method nuovo 'per ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam

1
Vale anche la pena sottolineare che se si dispone di un modello associato alla tabella, si sta rinominando, eseguendo rake db:migrateo rake db:rollbacknon rinominando il file model.rb. Sarà necessario modificare manualmente il file model.rb.
9monkeys,

1
Nelle versioni più recenti di Rails (ad es. 5.x) è possibile utilizzare un metodo change anziché self.up e self.down , poiché anche Rails può eseguire un rollback. Quindi, solo questo codice è sufficiente: def change rename_table :my_table, :my_new_table end. . . . . A proposito: All'interno di changevoi un usare questi comandi: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Bellezza

2
ActiveRecord::Migration.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.