Menentukan nama kolom dalam migrasi "referensi"


124

Saya ingin membuat migrationdi Rails, mereferensikan tabel lain. Biasanya, saya akan melakukan sesuatu seperti:

add_column :post, :user, :references

Ini membuat kolom bernama user_iddalam poststabel. Tetapi bagaimana jika, alih-alih user_id, saya menginginkan sesuatu seperti itu author_id? Bagaimana saya bisa melakukan itu?

Jawaban:


59

Lakukan secara manual:

add_column :post, :author_id, :integer

tetapi sekarang, ketika Anda membuat pernyataan milik_to, Anda harus memodifikasinya, jadi sekarang Anda harus memanggil

def post
    belongs_to :user, :foreign_key => 'author_id'
end

1
Apakah saya tidak perlu menambahkan indeks apa pun?
caarlos0

1
Ya, Anda harus membuat indeks dalam migrasi.
Tom Harrison

1
Curang Rails - tidak benar-benar menggunakan indeks secara default. Sekarang jika Anda menginginkan indeks (yang merupakan ide bagus - terlepas dari kenyataan bahwa rails akan mengabaikannya sepenuhnya), Anda pasti dapat menambahkannya. Anda akan ingin melihat panduan yang saya tautkan untuk info lebih lanjut tentang migrasi secara umum, dan Anda bahkan mungkin akhirnya memasukkan kode SQL panggilan langsung dalam migrasi Anda. Saya akan mengatakan abaikan itu, karena ini bukan bagian normal dari rel, Anda akan mendapatkan 0 kinerja darinya, karena kueri SQL yang dihasilkan default dari rel tidak memanfaatkannya. tautan
mschultz

hmm mengerti. Terima kasih banyak!
caarlos0

menggunakan schema_pluspermata, t.references :category, index: true, foreign_key: true, references: :match_categoriesjuga berfungsi untuk saya dalam file migrasi.
elquimista

251

Untuk Rails 5+

Definisi Awal:

Jika Anda mendefinisikan Posttabel model Anda, Anda dapat mengatur references, indexdan foreign_keydalam satu baris:

t.references :author, index: true, foreign_key: { to_table: :users }

Perbarui yang Ada:

Jika Anda menambahkan referensi ke tabel yang sudah ada, Anda bisa melakukan ini:

add_reference :posts, :author, foreign_key: { to_table: :users }

Catatan: Nilai default indexadalah benar.


Apakah definisi awal memungkinkan nulls? Jika tidak, apakah Anda tahu alternatif nullable?
Vorpulus Lyphane

5
Definisi ini memungkinkan nulls. Untuk tidak mengizinkannya, tambahkan opsi biasa null: false.
Ashitaka

Terima kasih. Untuk "Definisi Awal", menurut saya "index: true" tidak diperlukan. Saya mendapatkan perubahan skema yang sama dengan atau tanpa itu. Lupakan; baru saja melihat catatan Anda di bagian akhir.
Joey

Terima kasih, inilah yang saya cari!
Philippe B.

250

Di Rails 4.2+ Anda juga dapat mengatur kunci asing di db, yang merupakan ide bagus .

Untuk asosiasi sederhana, ini juga dapat dilakukan dengan t.referencesmenambahkan foreign_key: true, tetapi dalam kasus ini Anda memerlukan dua baris.

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

2
Terima kasih, tetapi pertanyaannya adalah Rails3, dengan senang hati saya akan membantu
ekologi

2
Ooh, saya tidak menyadarinya. Yah, itu sangat membantu to.me. :)
bonh

2
Saya hampir putus asa saat melihat ini! Terima kasih @ecoologic!
Dan Williams

2
@ ecologic, hanya satu hal yang mungkin ingin Anda tambahkan, add_foreign_key hanya rel 4.2+. ;)
Dan Williams

4
Saya tidak yakin Anda memerlukan references: :usersopsi saat add_referencemenelepon. Saya tidak melihatnya didokumentasikan di dokumen dan tampaknya berfungsi di pihak saya tanpa itu.
jakecraige

87

Di rel 4, saat menggunakan postgresql dan permata schema_plus Anda cukup menulis

add_reference :posts, :author, references: :users

Ini akan membuat kolom author_id, yang mengacu dengan benar users(id).

Dan dalam model Anda, Anda menulis

belongs_to :author, class_name: "User"

Catatan, saat membuat tabel baru Anda dapat menuliskannya sebagai berikut:

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

Catatan: schema_plusgem secara keseluruhan tidak kompatibel dengan rails 5+, tetapi fungsionalitas ini ditawarkan oleh gem schema_auto_foreign_keys (bagian dari schema_plus) yang kompatibel dengan rails 5.


28
dan jika Anda menggunakan create_table:t.references :author, references: :users
Michael Radionov

2
Menambahkan komentar @ MichaelRadionov pada jawaban Anda akan membuatnya sempurna.
Toxaq

2
Saya telah melihat sumber Rails 4.1, dan saya tidak dapat menemukan bukti apa pun yang :referencesbenar - benar berfungsi.
jes5199

1
Ya, Anda benar, saya telah menggunakan schema_pluspermata itu selama berabad-abad, dan itu sebenarnya menambahkan fungsi itu. Saya mengedit jawaban saya sesuai.
nathanvda

2
Di Rails 6, sepertinya sintaksnya t.references :col_name, references: other_table_nameberfungsi tanpa memasang permata tambahan.
Qqwy

51

Jika Anda tidak menggunakan kunci asing, maka tidak masalah apa nama tabel sebenarnya dari tabel lain.

add_reference :posts, :author

Pada Rails 5 , jika Anda menggunakan kunci asing, Anda dapat menentukan nama tabel lain di opsi kunci asing. (lihat https://github.com/rails/rails/issues/21563 untuk diskusi)

add_reference :posts, :author, foreign_key: {to_table: :users}

Sebelum Rails 5, Anda harus menambahkan kunci asing sebagai langkah terpisah:

add_foreign_key :posts, :users, column: :author_id

12
to_table adalah bentuk jamak:{to_table: :users}
hoffmanc

-3

alias_attribute (nama_baru, nama_lama) sangat berguna. Buat saja model Anda dan hubungannya:

rails g model Post title user:references

lalu edit model dan tambahkan alias atribut dengan

alias_attribute :author, :user

Setelah itu Anda akan dapat menjalankan hal-hal seperti

Post.new(title: 'My beautiful story', author: User.first)

1
ini tidak berfungsi ketika Anda perlu mendefinisikan banyak referensi ke model lain, misalnya, posting (penulis, editor)
ultrajohn
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.