Rails: Menambahkan indeks setelah menambahkan kolom

119

Misalkan saya membuat tabel tabledi aplikasi Rails. Beberapa waktu kemudian, saya menambahkan kolom yang berjalan:

rails generate migration AddUser_idColumnToTable user_id:string. 

Kemudian saya menyadari bahwa saya perlu menambahkan user_idsebagai indeks. Saya tahu tentang add_indexmetodenya, tetapi di manakah metode ini harus dipanggil? Apakah saya seharusnya menjalankan migrasi (jika ya, yang mana?), Lalu menambahkan dengan tangan metode ini?

pengguna1611830
sumber

Jawaban:

235

Anda dapat menjalankan migrasi lain, hanya untuk indeks:

class AddIndexToTable < ActiveRecord::Migration
  def change
    add_index :table, :user_id
  end
end
Jaap Haagmans
sumber
4
Jadi saya cukup menjalankan di konsol saya: rel menghasilkan migrasi AddIndexToTable?
pengguna1611830
3
Ya, Anda dapat melakukannya, tetapi Anda harus mengedit migrasi itu setelah itu untuk mencerminkan kode di atas.
Jaap Haagmans
Apakah: tabel seharusnya jamak?
makam
1
@tomb Saya menggunakan contoh dari pertanyaan asli. :tableadalah sebenarnya nama tabel, sehingga dalam kasus usersmeja, Anda akan menggantikan :usersuntuk :table.
Jaap Haagmans
65

Jika Anda perlu membuat, user_idmaka itu akan menjadi asumsi yang masuk akal bahwa Anda mereferensikan tabel pengguna. Dalam hal ini migrasi harus:

rails generate migration AddUserRefToProducts user:references

Perintah ini akan menghasilkan migrasi berikut:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :user, :product, index: true
  end
end

Setelah menjalankan rake db:migratekedua user_idkolom dan indeks akan ditambahkan keproducts meja.

Jika Anda hanya perlu menambahkan indeks ke kolom yang ada, misalnya nameauser meja, teknik berikut ini mungkin membantu:

rails generate migration AddIndexToUsers name:string:index akan menghasilkan migrasi berikut:

class AddIndexToUsers < ActiveRecord::Migration
  def change
    add_column :users, :name, :string
    add_index :users, :name
  end
end

Menghapus add_column baris dan jalankan migrasi.

Dalam kasus yang dijelaskan, Anda bisa mengeluarkan rails generate migration AddIndexIdToTable index_id:integer:indexperintah dan kemudian menghapus add_columnbaris dari migrasi yang dihasilkan. Tetapi saya lebih suka merekomendasikan untuk membatalkan migrasi awal dan menambahkan referensi sebagai gantinya:

rails generate migration RemoveUserIdFromProducts user_id:integer
rails generate migration AddUserRefToProducts user:references
Vadym Tyemirov
sumber
Terima kasih Vadym untuk jawaban lengkapnya. Satu pertanyaan terakhir: mengapa Anda merekomendasikan untuk membatalkan migrasi awal? Apakah nanti ada masalah kinerja terkait dengan penambahan indeks?
Flavio Wuensche
2
Untuk @fwuensche: tidak ada penalti kinerja untuk menambahkan indeks nanti. Logika domain akan menjadi kurang jelas. Misalnya jika Anda memutuskan untuk memutuskan / mengabstraksi / dll asosiasi nanti, Anda harus berurusan dengan dua migrasi terpisah, yang seharusnya menjadi satu ...
Vadym Tyemirov
6
PERINGATAN: Perhatikan bahwa index: true hanya berfungsi dalam migrasi create_table. Migrasi akan berjalan, tetapi tidak ada indeks yang akan dibuat. Lihat makandracards.com/makandra/…
rmcsharry
9

Tambahkan migrasi yang dihasilkan setelah membuat kolom berikut (contoh)

add_index :photographers, :email, :unique => true
rdeandrade.dll
sumber
maksud Anda sesuatu seperti ini: def self.up add_column ... end add_index ...?
pengguna1611830
5

Untuk referensi Anda bisa menelepon

rails generate migration AddUserIdColumnToTable user:references

Jika di masa mendatang Anda perlu menambahkan indeks umum, Anda dapat meluncurkan ini

rails g migration AddOrdinationNumberToTable ordination_number:integer:index

Hasilkan kode:

class AddOrdinationNumberToTable < ActiveRecord::Migration
  def change
   add_column :tables, :ordination_number, :integer
   add_index :tables, :ordination_number, unique: true
  end
end
Mauro
sumber
0

Anda dapat menggunakan ini, anggap saja Job adalah nama model yang Anda tambahkan index cader_id :

class AddCaderIdToJob < ActiveRecord::Migration[5.2]
  def change
    change_table :jobs do |t|
      t.integer :cader_id
      t.index :cader_id
    end
  end
end
vidur punj
sumber