Migrasi rel: t.referensi dengan nama alternatif?

121

Jadi saya memiliki create_table seperti ini untuk Kursus di Sekolah:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

tetapi saya ingin merujuk pada dua kursus lain seperti:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Bisakah saya mengatakan yang berikut ini?

t.references :transferrable_as, :as=> :course
kaca
sumber

Jawaban:

161

Anda dapat melakukan ini semua dalam definisi migrasi / kolom awal (setidaknya saat ini di Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}
Ryan
sumber
10
Ini berfungsi pada Rails 5.1 dan tidak ada saran lain yang berfungsi. Jauh lebih bersih, dan terasa pas.
stephenmurdoch
2
Saya menggunakan Rails 5.1.4 tetapi tidak berhasil. Ketika saya menentukan foreign_keyopsi dalam pembuatan tabel seperti ini, itu menimbulkan kesalahan yang mengatakan bahwa tabel yang saya buat tidak ada ... Jadi saya curiga itu tidak benar-benar didukung oleh API resmi.
Quv
3
Saya juga membaca bahwa indextelah ditambahkan ke kunci asing pada Rails stackoverflow.com/questions/39769981/…
Jonathan Reyes
99

Anda bisa melakukannya dengan cara ini:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

atau digunakan t.belongs_tosebagai alias untukt.references

Anda tidak dapat menambahkan foreign_key: trueke dua baris referensi tersebut. Jika Anda ingin menandainya sebagai kunci asing di tingkat database, Anda perlu melakukan migrasi dengan ini:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Memperbarui

Di Rails 5.1 dan di atasnya, Anda dapat menambahkan kunci asing dalam migrasi di create_tableblok seperti ini:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end
Toby 1 Kenobi
sumber
5
Bagian tentang tidak bisa menambahkan foreign_key: trueke garis referensi adalah apa yang membuat saya tersandung. Menambahkan add_foreign_keydan menentukan nama kolom untuk itu berhasil.
Matthew Clark
Apakah ini berhasil di luar kotak di Rails? Menurut stackoverflow.com/a/22384289/239657 , ini membutuhkan schema_pluspermata. Dokumen add_reference Rails tidak menyebutkan opsi: referensi.
Beni Cherniavsky-Paskin
1
Saya tidak mengikuti untuk apa references:opsi itu ( t.referencesbukankah itu hanya relevan pada tingkat model, dengan pertimbangan foreign_key diurus oleh add_foreign_key?
MCB
1
@MCB t.referencesmengatakan "tambahkan bidang ke tabel ini yang merupakan kunci utama dari tabel lain." The references:pilihan mengatakan itu yang meja itu adalah kunci utama (diperlukan jika tidak jelas dengan nama lapangan). The add_foreign_keyFungsi memberitahu database untuk ditegakkan integritas referensial di sini.
Toby 1 Kenobi
2
@MCB setelah sekian lama aku menyadari kamu benar selama ini. Komentar pertama Anda di atas benar-benar benar - add_foreign_keybaris - baris tersebut menginformasikan database apa itu kunci asing dari apa. The references:parameter melakukan apa-apa.
Toby 1 Kenobi
13

Saya pikir utas ini memiliki cara Rails-ish yang berbeda: Scaffolding ActiveRecord: dua kolom dengan tipe data yang sama

Dalam migrasi:

t.belongs_to: transferrable_as

t.belongs_to: same_as

kaca
sumber
1
tetapi bagaimana db mengetahui kunci asing mana yang akan ditautkan ke tabel? Saya mencoba ini dengan database Postgres dan ini memberi saya kesalahan PG::UndefinedTable: ERRORkarena mencoba menambahkan batasan kunci asing ke tabel yang tidak ada.
Toby 1 Kenobi
Dalam kasus ada yang bertanya-tanya, belongs_tohanya sebuah alias untuk referencesdan sehingga memiliki fungsi yang sama persis.
Jason Swett
11

Sebagai jawaban tambahan untuk pertanyaan ini - Model harus memiliki baris berikut untuk menyelesaikan pengaitan:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"
Diego Diaz de Berenguer
sumber
3

Saya tidak berpikir referencesmenerima :asopsi, tetapi Anda dapat membuat kolom Anda secara manual ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
Ju Nogueira
sumber