Bagaimana Anda menulis migrasi untuk mengganti nama model ActiveRecord dan tabelnya di Rails?

408

Saya mengerikan dalam penamaan dan menyadari bahwa ada satu set nama yang lebih baik untuk model saya di aplikasi Rails saya.
Apakah ada cara untuk menggunakan migrasi untuk mengganti nama model dan tabel yang sesuai?

Hanya baca
sumber
11
Saya menyarankan menambahkan "ActiveRecord" ke pertanyaan ini untuk meningkatkan kecocokan mesin pencari. Saya sudah mencari ini menggunakan "nama tabel ActiveRecord".
Landon Kuhn
6
Jika Anda menggunakan migrasi, masalah ini lebih rumit daripada yang terlihat. Solusi yang dipilih mengatakan untuk kembali dan secara manual mengganti nama model, pengontrol, dll. Setelah Anda mengubah nama tabel. Jika Anda melakukan ini, semua migrasi lama yang merujuk ke model Anda dengan nama yang lebih lama akan gagal. Jadi ketika seseorang mengkloning repo Anda dan mencoba menjalankannya rake db:migrate, itu akan gagal. Anda bisa kembali dan mengubah nama-nama itu dalam migrasi, tetapi itu akan berantakan. Anda mungkin lebih baik hanya membuat model yang sama sekali baru daripada mengganti namanya.
andrew
4
@andrewhannigan: Bukankah poin Anda bisa diperdebatkan jika seseorang mengkloning repo Anda dan hanya berjalan rake db:schema:load?
istrasci
3
@istrasci: tentu saja. Bahkan, menjalankan rake db:migrateuntuk membuat database dari awal secara aktif tidak dianjurkan, justru karena kekhawatiran yang ditunjukkan oleh andrew.
Giuseppe

Jawaban:

584

Ini sebuah contoh:

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

Saya harus pergi dan mengganti nama file pernyataan model secara manual.

Edit:

Di Rails 3.1 & 4, ActiveRecord::Migration::CommandRecordertahu cara membalikkan migrasi rename_table, sehingga Anda bisa melakukan ini:

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

(Anda masih harus melalui dan secara manual mengubah nama file Anda.)

Hanya baca
sumber
6
@mathee: ya, Anda harus mengubahnya secara manual, atau menggunakan IDE yang dapat melakukan Ruby refactoring dan mengkomitnya ke sistem kontrol versi Anda.
pupeno
13
git grep adalah temanmu. Saya mengganti nama suatu Kegiatan menjadi Kebiasaan sekarang: git grep -i activitsangat terbuka.
Felix Rabe
1
Anda juga harus mengubah konten controller Anda, bukan?
alemur
5
Dan jangan lupakan rute Anda.
Dan Herman
26
Juga, hanya sebagai kepala, Anda ingin menggunakan versi jamak dari nama tabel Anda di panggilan rename_table.
Han
66

Di Rails 4 yang harus saya lakukan adalah perubahan def

def change
  rename_table :old_table_name, :new_table_name
end

Dan semua indeks saya diurus untuk saya. Saya tidak perlu memperbarui indeks secara manual dengan menghapus yang lama dan menambahkan yang baru.

Dan itu berfungsi menggunakan perubahan untuk naik atau turun dalam hal indeks juga.

bfcoder
sumber
47

Jawaban dan komentar lainnya mencakup penggantian nama tabel, penggantian nama file, dan memahami kode Anda.

Saya ingin menambahkan beberapa peringatan lagi:

Mari kita gunakan contoh dunia nyata yang saya hadapi hari ini: mengganti nama model dari 'Merchant' menjadi 'Business.'

  • Jangan lupa untuk mengubah nama tabel dan model dependen dalam migrasi yang sama. Saya mengubah model Merchant dan MerchantStat saya ke Bisnis dan BusinessStat pada saat yang sama. Kalau tidak, aku harus melakukan terlalu banyak memetik dan memilih ketika melakukan pencarian-dan-ganti.
  • Untuk model lain yang bergantung pada model Anda melalui kunci asing, nama kolom kunci asing tabel lainnya akan diturunkan dari nama model asli Anda. Jadi, Anda juga ingin melakukan beberapa panggilan rename_column pada model dependen ini. Misalnya, saya harus mengganti nama kolom 'merchant_id' menjadi 'business_id' di berbagai tabel bergabung (untuk hubungan has_and_belongs_to_many) dan tabel dependen lainnya (untuk hubungan has_one dan has_many normal). Kalau tidak, saya akan berakhir dengan kolom seperti 'business_stat.merchant_id' menunjuk ke 'business.id'. Berikut jawaban yang bagus tentang melakukan penggantian nama kolom.
  • Saat mengambil, ingatlah untuk mencari versi singular, jamak, huruf besar, huruf kecil, dan bahkan UPPERCASE (yang mungkin muncul dalam komentar) dari string Anda.
  • Yang terbaik adalah mencari versi jamak terlebih dahulu, kemudian singular. Dengan begitu jika Anda memiliki bentuk jamak tidak beraturan - seperti di merchant saya :: bisnis contoh - Anda bisa mendapatkan semua bentuk jamak tidak teratur yang benar. Kalau tidak, Anda mungkin berakhir dengan, misalnya, 'bisnis' (3 detik) sebagai kondisi perantara, yang menghasilkan pencarian dan penggantian yang lebih banyak.
  • Jangan mengganti setiap kejadian secara membabi buta. Jika nama model Anda bertabrakan dengan istilah pemrograman umum, dengan nilai-nilai dalam model lain, atau dengan konten teks dalam tampilan Anda, Anda mungkin berakhir terlalu bersemangat. Dalam contoh saya, saya ingin mengubah nama model saya menjadi 'Bisnis' tetapi masih menyebutnya sebagai 'pedagang' di konten di UI saya. Saya juga memiliki peran 'pedagang' untuk pengguna saya di CanCan - itu adalah kebingungan antara peran pedagang dan model Merchant yang menyebabkan saya mengganti nama model di tempat pertama.
armchairdj
sumber
26

Anda juga perlu mengganti indeks Anda:

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

Dan ganti nama file Anda dll, secara manual seperti dijelaskan oleh jawaban lain di sini.

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

Pastikan Anda dapat mengembalikan dan memutar ke depan setelah Anda menulis migrasi ini. Ini bisa menjadi rumit jika Anda mendapatkan sesuatu yang salah dan macet dengan migrasi yang mencoba mempengaruhi sesuatu yang tidak ada lagi. Sampah seluruh database terbaik dan mulai lagi jika Anda tidak dapat memutar kembali. Jadi waspadai Anda mungkin perlu membuat cadangan sesuatu.

Juga: periksa schema_db untuk setiap nama kolom yang relevan di tabel lain yang ditentukan oleh has_ ​​atau milik_to atau sesuatu. Anda mungkin perlu mengeditnya juga.

Dan akhirnya, melakukan ini tanpa suite uji regresi akan menjadi gila.

Rimian
sumber
11
Adapun migrasi 4.0.0.beta1 rails, tidak perlu memperbarui indeks secara manual. AR memperbarui dengan sendirinya.
freemanoid
1

Anda dapat menjalankan perintah ini: rails g migration rename_ {old_table_name} ke {new_table_name}

setelah Anda mengedit file dan menambahkan kode ini dalam perubahan metode

rename_table: {old_table_name},: {new_table_name}

Mouhamadou Bamba Mboup
sumber