การโยกย้าย Rails: t.references ด้วยชื่ออื่น?


121

ดังนั้นฉันจึงมี create_table แบบนี้สำหรับหลักสูตรที่โรงเรียน:

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

แต่ฉันต้องการให้อ้างอิงอีกสองหลักสูตรเช่น:

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

ฉันสามารถพูดต่อไปนี้ได้หรือไม่?

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

คำตอบ:


161

คุณสามารถทำสิ่งนี้ได้ทั้งหมดในการย้ายข้อมูล / นิยามคอลัมน์เริ่มต้น (อย่างน้อยก็อยู่ใน Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}

10
สิ่งนี้ใช้ได้กับ Rails 5.1 และไม่มีคำแนะนำอื่นใดทำ สะอาดกว่ามากและรู้สึกดี
stephenmurdoch

2
ฉันใช้ Rails 5.1.4 แต่ไม่ได้ผล เมื่อฉันระบุforeign_keyตัวเลือกในการสร้างตารางในลักษณะนี้มันทำให้เกิดข้อผิดพลาดขึ้นว่าไม่มีตารางที่ฉันสร้าง ... ดังนั้นฉันจึงสงสัยว่า API อย่างเป็นทางการไม่รองรับจริงๆ
Quv

3
ฉันยังอ่านว่าindexมีการเพิ่มคีย์ต่างประเทศแล้วใน Rails stackoverflow.com/questions/39769981/…
Jonathan Reyes

100

คุณสามารถทำได้ด้วยวิธีนี้:

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

หรือใช้t.belongs_toเป็นนามแฝงสำหรับt.references

คุณไม่สามารถเพิ่มforeign_key: trueในสองบรรทัดการอ้างอิงเหล่านั้น หากคุณต้องการทำเครื่องหมายเป็นคีย์ต่างประเทศในระดับฐานข้อมูลคุณต้องมีการโยกย้ายด้วยสิ่งนี้:

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

ปรับปรุง

ใน Rails 5.1 ขึ้นไปคุณสามารถเพิ่ม Foreign Key ในการย้ายข้อมูลในcreate_tableบล็อกได้ดังนี้:

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

5
ส่วนที่เกี่ยวกับการไม่สามารถเพิ่มforeign_key: trueบรรทัดอ้างอิงคือสิ่งที่ทำให้ฉันสะดุด การเพิ่มadd_foreign_keyและระบุชื่อคอลัมน์สำหรับสิ่งเหล่านั้นเป็นการหลอกลวง
Matthew Clark

สิ่งนี้ทำงานนอกกรอบใน Rails หรือไม่? ตามstackoverflow.com/a/22384289/239657สิ่งนี้ต้องการschema_plusอัญมณี เอกสารadd_referenceของ Rails ไม่ได้กล่าวถึงตัวเลือกการอ้างอิง
Beni Cherniavsky-Paskin

1
ฉันไม่ได้ทำตามสิ่งที่references:ตัวเลือกนี้มีไว้สำหรับ (ตรงข้ามกับที่t.referencesจะไม่เกี่ยวข้องกับระดับโมเดลเท่านั้นโดยการพิจารณา Foreign_key จะได้รับการดูแลโดยadd_foreign_key?
MCB

1
@MCB t.referencesกล่าวว่า "เพิ่มฟิลด์ในตารางนี้ซึ่งเป็นคีย์หลักของตารางอื่น" references:ตัวเลือกที่จะบอกว่ามันตารางมันเป็นคีย์หลักของ (จำเป็นถ้ามันจะไม่ชัดเจนโดยใช้ชื่อของสนาม) add_foreign_keyฟังก์ชั่นบอกฐานข้อมูลเพื่อการบังคับใช้การอ้างอิงที่นี่
Toby 1 Kenobi

2
@MCB หลังจากนั้นฉันก็รู้ว่าคุณพูดถูกมาตลอด ความคิดเห็นแรกของคุณข้างต้นถูกต้องทุกadd_foreign_keyประการ- สายต่างๆจะดูแลในการแจ้งฐานข้อมูลว่าคีย์ต่างประเทศคืออะไร references:พารามิเตอร์จะทำอะไร
Toby 1 Kenobi

13

ฉันคิดว่าเธรดนี้มีวิธี Rails-ish ที่แตกต่างออกไป: Scaffolding ActiveRecord: สองคอลัมน์ที่มีประเภทข้อมูลเดียวกัน

ในการย้ายข้อมูล:

t.belongs_to: transferrable_as

t.belongs_to: same_as


1
แต่ฐานข้อมูลจะรู้ได้อย่างไรว่าจะเชื่อมโยงตารางไปยังคีย์ต่างประเทศใด ฉันกำลังลองใช้กับฐานข้อมูล Postgres และมันทำให้ฉันเกิดข้อผิดพลาดPG::UndefinedTable: ERRORว่ากำลังพยายามเพิ่มข้อ จำกัด ของคีย์ต่างประเทศในตารางที่ไม่มีอยู่
Toby 1 Kenobi

ในกรณีที่ใครที่สงสัยว่าbelongs_toเป็นเพียงนามแฝงไปreferencesและเพื่อให้มีการทำงานที่เดียวกันแน่นอน
Jason Swett

11

เพื่อเป็นคำตอบเพิ่มเติมสำหรับคำถามนี้โมเดลควรมีบรรทัดต่อไปนี้เพื่อให้การเชื่อมโยงสมบูรณ์:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"

3

ฉันไม่คิดว่าreferencesยอมรับ:asตัวเลือกนี้ แต่คุณสามารถสร้างคอลัมน์ด้วยตนเอง ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.