Tambahkan migrasi kolom referensi di Rails 4

311

Seorang pengguna memiliki banyak unggahan. Saya ingin menambahkan kolom ke uploadstabel yang mereferensikanuser . Seperti apa seharusnya migrasi itu?

Inilah yang saya miliki. Saya tidak yakin apakah saya harus menggunakan (1) :user_id, :intatau (2) :user, :references. Saya bahkan tidak yakin apakah (2) berfungsi. Hanya mencoba melakukan ini dengan cara "rel".

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_column :uploads, :user_id, :integer
  end
end

Pertanyaan yang relevan kecuali untuk rel 3. Migrasi 3 rail: Menambahkan kolom referensi?

Don P
sumber

Jawaban:

707

Rails 4.x

Saat Anda sudah memiliki users dan uploadstabel dan ingin menambahkan hubungan baru di antara mereka.

Yang perlu Anda lakukan adalah: cukup buat migrasi menggunakan perintah berikut:

rails g migration AddUserToUploads user:references

Yang akan membuat file migrasi sebagai:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
  end
end

Kemudian, jalankan migrasi menggunakan rake db:migrate. Migrasi ini akan membantu menambahkan kolom baru bernama user_idto uploadstable (merujuk idkolom dalam userstabel), PLUS juga akan menambahkan indeks pada kolom baru.

PEMBARUAN [Untuk Rails 4.2]

Rail tidak dapat dipercaya untuk mempertahankan integritas referensial; database relasional datang untuk menyelamatkan kami di sini. Artinya adalah bahwa kita dapat menambahkan batasan kunci asing di tingkat basis data itu sendiri dan memastikan bahwa basis data akan menolak operasi apa pun yang melanggar integritas referensial yang disetel ini. Seperti yang dikomentari @infoget, Rails 4.2 dikirimkan dengan dukungan asli untuk kunci asing (integritas referensial) . Ini tidak diperlukan tetapi Anda mungkin ingin menambahkan kunci asing (karena sangat berguna) ke referensi yang kami buat di atas.

Untuk menambahkan kunci asing ke referensi yang ada , buat migrasi baru untuk menambahkan kunci asing:

class AddForeignKeyToUploads < ActiveRecord::Migration
  def change
    add_foreign_key :uploads, :users
  end
end

Untuk membuat referensi yang benar-benar baru dengan kunci asing (dalam Rails 4.2) , hasilkan migrasi menggunakan perintah berikut:

rails g migration AddUserToUploads user:references

yang akan membuat file migrasi sebagai:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
    add_foreign_key :uploads, :users
  end
end

Ini akan menambahkan kunci asing baru ke user_idkolom uploadstabel. Kunci referensi idkolom dalam userstabel.

CATATAN: Ini selain menambahkan referensi sehingga Anda masih perlu membuat referensi terlebih dahulu daripada kunci asing ( Anda dapat memilih untuk membuat kunci asing dalam migrasi yang sama atau file migrasi terpisah ). Rekaman Aktif hanya mendukung kunci asing kolom tunggal dan saat ini saja mysql, mysql2dan PostgreSQLadaptor didukung. Jangan coba ini dengan adaptor lain seperti sqlite3, dll. Lihat Panduan Rails: Kunci Asing untuk referensi Anda.

Kirti Thorat
sumber
8
Dalam banyak kasus, ada baiknya menambahkan kunci asing juga. add_foreign_key (Rails 4.2)
poerror
18
Saya yakin Anda dapat melakukan semuanya dalam satu baris: add_reference: unggahan,: pengguna, indeks: true, foreign_key: true @KirtiThorat
user1801879
33
Sekarang, jika Anda menggunakan sintaks generator khusus untuk migrasi, Rails 4.2 akan secara otomatis membuat migrasi yang benar dengan menyertakan batasan kunci asing. rails g migration AddUserToUploads user:referencesmenghasilkan add_reference :uploads, :user, index: true, foreign_key: truedalam migrasi yang sesuai.
jrhorn424
10
Gunakan ...index: true, foreign_key: truesebagai ganti o line add_foreign_key.
Washington Botelho
2
Mengapa kita membutuhkan keduanya foreign_keydan t.reference? Bukankah t.referencepada dasarnya setara dengan foriegn_key+ index?
geoboy
189

Rel 5

Anda masih dapat menggunakan perintah ini untuk membuat migrasi:

rails g migration AddUserToUploads user:references

Migrasi terlihat sedikit berbeda dari sebelumnya, tetapi masih berfungsi:

class AddUserToUploads < ActiveRecord::Migration[5.0]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

Perhatikan bahwa :usertidak:user_id

Mirror318
sumber
2
Untuk kelas dengan spasi nama, seperti Local::Useralih - alih Usermelakukan sesuatu seperti rails g migration AddLocalUserToUploads user:references.
Ka Mok
3
apakah ini secara otomatis menambahkan:index
Saravanabalagi Ramachandran
4
@Zeke Ya, jalankan migrasi dan periksa skema Anda, harusnya mengatakan sesuatu sepertit.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318
1
ya, saya mendapat kesalahan "indeks ada" ketika saya secara manual menambahkan add_index dalam migrasi: P @ Mirror318
Saravanabalagi Ramachandran
2
Kita juga harus menambahkan belongs_to :userdi Uploadkelas, sehingga kita dapat menggunakan upload.useruntuk mendapatkan contoh pengguna.
Wit
17

jika Anda menyukai pendekatan updan downmetode alternatif lain, coba ini:

  def up
    change_table :uploads do |t|
      t.references :user, index: true
    end
  end

  def down
    change_table :uploads do |t|
      t.remove_references :user, index: true
    end
  end
Kiry Meas
sumber
9

[Menggunakan Rails 5]

Hasilkan migrasi:

rails generate migration add_user_reference_to_uploads user:references

Ini akan membuat file migrasi:

class AddUserReferenceToUploads < ActiveRecord::Migration[5.1]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

Sekarang jika Anda mengamati file skema, Anda akan melihat bahwa tabel unggahan berisi bidang baru. Sesuatu seperti: t.bigint "user_id"ataut.integer "user_id" .

Migrasikan basis data:

rails db:migrate
vantony
sumber
1
Jawaban ini tampaknya merupakan duplikat dari jawaban @ Mirror318. Berikan komentar tentang jawaban di atas jika Anda merasa ada yang kurang darinya. Terima kasih.
M. Habib
8

Sintaks lain untuk melakukan hal yang sama adalah:

rails g migration AddUserToUpload user:belongs_to
Nadeem Yasin
sumber
7

Hanya untuk mendokumentasikan jika seseorang memiliki masalah yang sama ...

Dalam situasi saya, saya telah menggunakan :uuidbidang, dan jawaban di atas tidak berfungsi untuk kasus saya, karena rel 5 membuat kolom menggunakan :bigintsebagai gantinya :uuid:

add_column :uploads, :user_id, :uuid
add_index :uploads, :user_id
add_foreign_key :uploads, :users
Bruno Casali
sumber
Ini juga jauh lebih jelas apa yang terjadi. Tapi ya UUID harus menjadi standar sekarang.
hadits
2

Buat file migrasi

rails generate migration add_references_to_uploads user:references

Nama kunci asing default

Ini akan membuat kolom user_id di tabel unggahan sebagai kunci asing

class AddReferencesToUploads < ActiveRecord::Migration[5.2]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

model pengguna:

class User < ApplicationRecord
  has_many :uploads
end

unggah model:

class Upload < ApplicationRecord
  belongs_to :user
end

Kustomisasi nama kunci asing:

add_reference :uploads, :author, references: :user, foreign_key: true

Ini akan membuat kolom author_id di tabel unggahan sebagai kunci asing.

model pengguna:

class User < ApplicationRecord
  has_many :uploads, foreign_key: 'author_id'
end

unggah model:

class Upload < ApplicationRecord
  belongs_to :user
end
Clint Clinton
sumber