การระบุชื่อคอลัมน์ในการย้าย "การอ้างอิง"


124

ฉันต้องการสร้างmigrationใน Rails โดยอ้างอิงตารางอื่น โดยปกติฉันจะทำบางสิ่งเช่น:

add_column :post, :user, :references

สิ่งนี้สร้างคอลัมน์ที่ตั้งชื่อuser_idในpostsตาราง แต่สิ่งที่ถ้าแทนuser_idฉันต้องการสิ่งที่ชอบauthor_id? ฉันจะทำเช่นนั้นได้อย่างไร?

คำตอบ:


59

ทำด้วยตนเอง:

add_column :post, :author_id, :integer

แต่ตอนนี้เมื่อคุณสร้างคำสั่ง belong_to คุณจะต้องแก้ไขดังนั้นตอนนี้คุณต้องโทร

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

1
ฉันไม่ต้องเพิ่มดัชนีใด ๆ ?
caarlos0

1
ใช่คุณจะต้องสร้างดัชนีในการย้ายข้อมูล
Tom Harrison

1
กลโกงทางรถไฟ - มันไม่ได้ใช้ดัชนีโดยค่าเริ่มต้นจริงๆ ตอนนี้ถ้าคุณต้องการดัชนี (ซึ่งเป็นความคิดที่ดี - แม้ว่ารางจะเพิกเฉยโดยสิ้นเชิงก็ตาม) คุณสามารถเพิ่มได้อย่างแน่นอน คุณจะต้องตรวจสอบคำแนะนำฉันลิงก์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลโดยทั่วไปและคุณอาจลงเอยด้วยการเรียกรหัส SQL โดยตรงในการย้ายข้อมูลของคุณ ฉันจะบอกว่าไม่ต้องสนใจเพราะมันไม่ใช่ส่วนปกติของรางคุณจะได้รับ 0 ประสิทธิภาพจากมันเนื่องจากการสืบค้น SQL ที่สร้างขึ้นเริ่มต้นของรางจะไม่ได้รับประโยชน์จากมัน ลิงค์
mschultz

อืมเข้าใจแล้ว ขอบคุณมาก!
caarlos0

การใช้schema_plusอัญมณีt.references :category, index: true, foreign_key: true, references: :match_categoriesยังใช้งานได้สำหรับฉันในไฟล์การย้ายข้อมูล
elquimista

252

สำหรับ Rails 5+

นิยามเริ่มต้น:

หากคุณกำลังกำหนดของPostตารางรุ่นคุณสามารถตั้งค่าreferences, indexและforeign_keyในหนึ่งบรรทัด:

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

อัปเดตที่มีอยู่:

หากคุณกำลังเพิ่มการอ้างอิงไปยังตารางที่มีอยู่คุณสามารถทำได้:

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

หมายเหตุ: ค่าเริ่มต้นสำหรับindexเป็นจริง


คำจำกัดความเริ่มต้นจะอนุญาตให้มีค่าว่างหรือไม่? ถ้าไม่คุณรู้จักทางเลือกที่เป็นโมฆะหรือไม่?
Vorpulus Lyphane

5
คำจำกัดความนี้อนุญาตให้nulls null: falseที่จะไม่อนุญาตให้เพิ่มตัวเลือกตามปกติ
Ashitaka

ขอบคุณ สำหรับ "คำจำกัดความเริ่มต้น" ฉันคิดว่า "ดัชนี: จริง" ไม่จำเป็น ฉันได้รับการเปลี่ยนแปลงสคีมาเดียวกันโดยมีหรือไม่มีก็ได้ ไม่เป็นไร; เพิ่งเห็นบันทึกของคุณในตอนท้าย
Joey

ขอบคุณนี่คือสิ่งที่ฉันกำลังมองหา!
Philippe B.

250

ในRails 4.2 +คุณยังสามารถตั้งค่าปุ่มต่างประเทศในฐานข้อมูลเช่นกันซึ่งเป็นความคิดที่ดี

สำหรับการเชื่อมโยงอย่างง่ายสามารถทำได้โดยt.referencesการเพิ่มforeign_key: trueแต่ในกรณีนี้คุณจะต้องมีสองบรรทัด

# 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
ขอบคุณ แต่คำถามถูกแท็ก Rails3 ฉันยินดีที่จะช่วย
ecoologic

2
โอฉันไม่ได้สังเกตเห็นสิ่งนั้น มันมีประโยชน์มากกับ me :)
bonh

2
ฉันเกือบจะหมดความหวังเมื่อเห็นสิ่งนี้! ขอบคุณ @ecoologic!
Dan Williams

2
@ecoologic สิ่งหนึ่งที่คุณอาจต้องการเพิ่ม add_foreign_key คือราง 4.2+ เท่านั้น ;)
Dan Williams

4
ฉันไม่แน่ใจว่าคุณต้องการreferences: :usersตัวเลือกนี้ในการadd_referenceโทร ฉันไม่เห็นเอกสารนี้ในเอกสารและดูเหมือนว่าจะใช้งานได้เมื่อไม่มีมัน
jakecraige

88

ในราง 4 เมื่อใช้ postgresql และschema_plus gem คุณสามารถเขียนได้

add_reference :posts, :author, references: :users

นี้จะสร้างคอลัมน์ที่ถูกต้องหมายถึงauthor_idusers(id)

และในโมเดลของคุณคุณเขียน

belongs_to :author, class_name: "User"

หมายเหตุเมื่อสร้างตารางใหม่คุณสามารถเขียนได้ดังนี้:

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

หมายเหตุ: schema_plusอัญมณีทั้งหมดเข้ากันไม่ได้กับราง 5+ แต่ฟังก์ชันนี้นำเสนอโดย gem schema_auto_foreign_keys (ส่วนหนึ่งของ schema_plus) ซึ่งเข้ากันได้กับราง 5


28
และหากคุณใช้create_table:t.references :author, references: :users
Michael Radionov

2
การเพิ่มความคิดเห็นของ @ MichaelRadionov ในคำตอบของคุณจะทำให้สมบูรณ์แบบ
toxaq

2
ฉันดูแหล่งข้อมูล Rails 4.1 แล้วและไม่พบหลักฐานว่า:referencesทำอะไรได้จริง
jes5199

1
ใช่คุณพูดถูกฉันใช้schema_plusอัญมณีมานานแล้วและกำลังเพิ่มฟังก์ชันนั้นจริงๆ ฉันแก้ไขคำตอบของฉันตามนั้น
nathanvda

2
ใน Rails 6 ดูเหมือนว่าไวยากรณ์จะt.references :col_name, references: other_table_nameทำงานได้โดยไม่ต้องติดตั้งอัญมณีเพิ่มเติม
Qqwy

51

หากคุณไม่ได้ใช้คีย์ต่างประเทศก็ไม่สำคัญว่าชื่อตารางจริงของตารางอื่นคืออะไร

add_reference :posts, :author

ใน Rails 5หากคุณใช้คีย์นอกคุณสามารถระบุชื่อของตารางอื่นในตัวเลือกคีย์ต่างประเทศ (ดูhttps://github.com/rails/rails/issues/21563สำหรับการสนทนา)

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

ก่อนหน้า Rails 5 คุณควรเพิ่ม Foreign Key เป็นขั้นตอนแยกกัน:

add_foreign_key :posts, :users, column: :author_id

12
to_table เป็นรูปแบบ{to_table: :users}
พหูพจน์

-3

alias_attribute (new_name, old_name)มีประโยชน์มาก เพียงสร้างโมเดลของคุณและความสัมพันธ์:

rails g model Post title user:references

จากนั้นแก้ไขโมเดลและเพิ่มชื่อแทนแอตทริบิวต์ด้วย

alias_attribute :author, :user

หลังจากนั้นคุณจะสามารถเรียกใช้สิ่งต่างๆเช่น

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

1
สิ่งนี้ใช้ไม่ได้เมื่อคุณต้องการกำหนดการอ้างอิงหลายรายการไปยังโมเดลอื่นเช่นโพสต์ (ผู้เขียนบรรณาธิการ)
ultrajohn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.