Mengganti nama tabel di rel

154

Saya ingin mengganti nama tabel ... (tabel apa saja.)

Saya mencoba baris kode ini:

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

Inilah yang aneh. Saya tahu saya membuatnya berfungsi pertama kali, tetapi sekarang saya mendapatkan kesalahan ini: metode `rename_table 'tidak terdefinisi untuk ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

Apakah ada sesuatu yang perlu saya atur?

Tommy
sumber

Jawaban:

248

Anda biasanya akan melakukan hal semacam ini dalam migrasi:

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

  def self.down
    rename_table :bar, :foo
  end
end
cam
sumber
1
Terima kasih, itu berhasil! Saya masih bingung mengapa kalimat sebelumnya tidak. Oh well ..
Tommy
@Tommy, rename_tablemetode ini didefinisikan dalam ActiveRecord::ConnectionAdapters::SchemaStatements. Ini dimaksudkan untuk dicampur ke modul lain. Jika Anda ingin menjalankannya secara langsung, saya pikir Anda bisa melakukannyainclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam
atau Anda bisa menggunakan ActiveRecord :: Migration.rename_table (: foo,: bar) jika Anda ingin. Tetapi migrasi bekerja dengan sangat baik. Apakah Anda juga ingin mengubah nama model atau ingin mempertahankan nama model sebagai yang lama? Jika demikian, Anda mungkin ingin menentukan nama tabel dalam model ActiveRecord menggunakan "set_table_name: bar".
Aditya Sanghi
1
Anda juga dapat menggunakan formulir baru untuk migrasi dengan metode 'ubah' alih-alih naik turun. contoh
MegaTux
def perubahan, bukan def self.up / def.self.down dalam implementasi Rails modern. Melakukan yang terakhir akan gagal secara diam-diam.
huertanix
294

Ingat bahwa dalam Rails> = 3.1 Anda dapat menggunakan changemetode ini.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Mikhail Grishko
sumber
37
Ini juga akan memigrasi indeks apa pun dari :old_table_nameke:new_table_name
Gavin Miller
7
Hanya sedikit komentar: Mungkin berubah menjadi: old_named_things,: new_named_things untuk mengingatkan orang bahwa nama tabel dalam activerecord umumnya jamak.
Carpela
24

.rename_table adalah metode instan, bukan metode kelas, jadi memanggil Class.method tidak akan berfungsi. Sebaliknya Anda harus membuat sebuah instance dari kelas, dan memanggil metode pada contoh, seperti ini: Class.new.method.

[EDIT] Dalam contoh ini, ActiveRecord::ConnectionAdapters::SchemaStatementsbahkan bukan kelas (seperti yang ditunjukkan oleh cam), yang berarti bahwa Anda bahkan tidak dapat membuat turunannya seperti yang saya katakan di atas. Dan bahkan jika Anda menggunakan contoh cam class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, tetap saja tidak akan berhasilrename_table menimbulkan pengecualian.

Di sisi lain, ActiveRecord::ConnectionAdapters::MysqlAdapter adalah kelas, dan kemungkinan kelas ini yang harus Anda gunakan untuk mengubah nama tabel Anda (atau SQLite atau PostgreSQL, tergantung pada database apa yang Anda gunakan). Sekarang, seperti yang terjadi, ActiveRecord::ConnectionAdapters::MysqlAdaptersudah dapat diakses Model.connection, jadi Anda harus benar-benar dapat melakukannya Model.connection.rename_table, menggunakan model apa pun dalam aplikasi Anda. [/ EDIT]

Namun, jika Anda ingin mengganti nama tabel secara permanen, saya akan menyarankan menggunakan migrasi untuk melakukannya. Mudah dan cara yang disukai untuk memanipulasi struktur basis data Anda dengan Rails. Inilah cara melakukannya:

# 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

Lalu, Anda dapat menjalankan migrasi dengan rake db:migrate(yang memanggil self.upmetode), dan menggunakan rake db:rollback(yang memanggil self.down) untuk membatalkan migrasi.

vonconrad
sumber
Saya setuju itu rename_tableadalah metode instan, tetapi tidak didefinisikan dalam kelas, jadi saran Anda untuk menelepon Class.new.methodtidak akan berfungsi (misalnya: ActiveRecord::ConnectionAdapters::SchemaStatements.newmemberikan kesalahan oMethodError: undefined method baru 'untuk ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
Juga patut ditunjukkan, bahwa jika Anda memiliki model yang terkait dengan tabel yang Anda ganti namanya, berjalan rake db:migrateatau rake db:rollbacktidak akan mengganti nama file model.rb. Anda perlu mengubah file model.rb secara manual.
9monkeys
1
Dalam versi Rails yang lebih baru (mis. 5.x) Anda dapat menggunakan metode perubahan alih-alih self.up dan self.down , karena Rails dapat melakukan rollback dengan cara ini juga. Jadi hanya kode ini cukup: def change rename_table :my_table, :my_new_table end. . . . . Dengan cara: Inside of changeAnda sebuah menggunakan perintah ini: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Kecantikan
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
sumber