Migrasi Rails 3: Menambahkan kolom referensi?

162

Jika saya membuat migrasi rel 3 baru dengan (misalnya)

rails g migration tester title:tester user:references

, semuanya berfungsi dengan baik ... namun jika saya menambahkan kolom dengan sesuatu di sepanjang baris:

rails g migration add_user_to_tester user:references

bidang referensi tidak dikenali. Singkatnya, pertanyaannya adalah: bagaimana cara menambahkan kolom referensi ke migrasi rel dari baris perintah?

Plankton
sumber

Jawaban:

205

Jika Anda menggunakan Rails 4.x Anda sekarang dapat menghasilkan migrasi dengan referensi, seperti ini:

rails generate migration AddUserRefToProducts user:references

seperti yang Anda lihat di panduan rel

Paulo Fidalgo
sumber
1
Lihat bagian 2.1 dari edgeguides.rubyonrails.org/active_record_migrations.html misalnya.
B Seven
2
bagaimana Anda menentukan nama kolom untuk kunci asing, bukan nama yang dibuat secara otomatis?
akan
@jwill Anda dapat menggunakan polymorphic: user: Reference {polymorphic}.
Paulo Fidalgo
@PauloFidalgo Bisakah Anda menjelaskan sedikit tentang cara melakukan itu? mungkin ada beberapa panduan tautan? (berbicara tentang polimorfik)
Anwar
@Anwar: di sini adalah dokumen api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/…
Paulo Fidalgo
186

EDIT : Ini adalah jawaban yang sudah usang dan tidak boleh diterapkan untuk Rails 4.x +

Anda tidak perlu menambahkan referensi ketika Anda dapat menggunakan id integer ke kelas referensi Anda.

Saya akan mengatakan keuntungan menggunakan referensi alih-alih bilangan bulat biasa adalah bahwa model akan ditentukan sebelumnya dengan hers_to dan karena model sudah dibuat dan tidak akan terpengaruh ketika Anda memigrasi sesuatu yang ada, tujuannya agak hilang.

Jadi saya akan melakukan ini sebagai gantinya:

rails g migration add_user_id_to_tester user_id:integer

Dan kemudian secara manual tambahkan milik: pengguna dalam model Penguji

DanneManne
sumber
9
Tapi itu tidak akan membuat batasan kunci asing yang sesuai pada database yang mendukungnya, kan?
abahgat
19
Tidak, afaik Rails tidak pernah membuat batasan kunci asing pada database kecuali Anda menambahkan plugin untuk melakukannya untuk Anda.
DanneManne
hanya mempelajari posting ini, tolong bagaimana saya menambahkan referensi setelah semua
El nino
13
ingatlah untuk menambahkan indeks dengan pengguna: integer: index
rickypai
3
Jawaban bertanggal, lihat jawaban @ Paulo untuk rel modern.
OneHoopyFrood
102

Harap perhatikan bahwa Anda kemungkinan besar akan membutuhkan indeks pada kolom itu juga.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end
Eugene
sumber
1
Mengapa? Apakah ini berlaku untuk sebagian besar hubungan hubungan milik?
ahnbizcad
Memang untuk alasan kinerja dan berguna jika Anda memiliki has_many / has_one di sisi lain dari hubungan milik_to. Jika Anda benar-benar yakin bahwa Anda tidak akan melalui user.testersAnda dapat menghilangkan indeks.
Eugene
1
Yang rails g migration ...dihasilkan add_reference :installs, :device, index: truejuga membuat indeks.
B Seven
49

Dengan dua langkah sebelumnya yang disebutkan di atas, Anda masih kehilangan batasan kunci asing. Ini seharusnya bekerja:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end
Martin Cabrera Diaubalick
sumber
Ini adalah satu-satunya jawaban aktual di sini. Kunci asing adalah bagian paling penting di sini
user2490003
ini harus ditandai sebagai jawaban yang benar karena pertanyaan meminta rel 3
Carlos Roque
35

Anda dapat menggunakan referensi dalam migrasi perubahan. Ini adalah kode Rails 3.2.13 yang valid:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table

gl03
sumber
1
ubah dan turunkan metode? bukan metode naik-turun saja?
MaicolBen
@ MaicolBen ya, dan Anda juga bisa meninggalkan metode down.
Hut8
@MaicolBen Tanpa downmetode, saya dapatkan ActiveRecord::IrreversibleMigrationketika memutar kembali menggunakan Rails 3.2. Saya juga harus pindah changeke up.
Andrew Grimm
27

Menjalankan rails g migration AddUserRefToSponsors user:referencesakan menghasilkan migrasi berikut:

def change
  add_reference :sponsors, :user, index: true
end
Wirwing
sumber
Untuk versi Rails apa ini?
Andrew Grimm
8

Saat menambahkan kolom, Anda harus membuat kolom itu bilangan bulat dan jika mungkin tetap dengan konvensi rel. Jadi untuk kasus Anda, saya berasumsi Anda sudah memiliki Tester dan model Pengguna, dan tabel penguji dan pengguna.

Untuk menambahkan kunci asing, Anda perlu membuat kolom integer dengan nama user_id (konvensi):

add_column :tester, :user_id, :integer

Kemudian tambahkan milik_ ke model penguji:

class Tester < ActiveRecord::Base
  belongs_to :user
end

Dan Anda mungkin juga ingin menambahkan indeks untuk kunci asing (ini adalah sesuatu yang sudah dilakukan referensi untuk Anda):

add_index :tester, :user_id
Zamith
sumber
8

Itu akan melakukan trik:

rails g migration add_user_to_tester user_id:integer:index
mahir
sumber
Saya suka ini juga menambahkan indeks yang kemungkinan besar Anda inginkan.
bheeshmar
3

Anda dapat menambahkan referensi ke model Anda melalui baris perintah dengan cara berikut:

rails g migration add_column_to_tester user_id:integer

Ini akan menghasilkan file migrasi seperti:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Ini berfungsi dengan baik setiap kali saya menggunakannya ..

Neha
sumber
3

Untuk Rails 4

Generator menerima jenis kolom sebagai referensi (juga tersedia sebagai belongs_to).

Migrasi ini akan membuat user_idkolom dan indeks yang sesuai:

$ rails g migration AddUserRefToProducts user:references 

menghasilkan:

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

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

Untuk Rel 3

Helper disebut referensi (juga tersedia sebagai belongs_to).

Migrasi ini akan membuat category_idkolom dengan tipe yang sesuai. Perhatikan bahwa Anda memasukkan nama model, bukan nama kolom. Rekaman Aktif menambahkan _iduntuk Anda.

change_table :products do |t|
  t.references :category
end

Jika Anda memiliki belongs_toasosiasi polimorfik maka referensi akan menambahkan kedua kolom yang diperlukan:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Akan menambahkan kolom attachment_id dan attachment_typekolom string dengan nilai default Photo.

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

shilovk
sumber