Rails 3 migrations: การเพิ่มคอลัมน์อ้างอิง?


162

ถ้าฉันสร้างการโยกย้าย 3 ทางรถไฟใหม่ด้วย (ตัวอย่าง)

rails g migration tester title:tester user:references

ทุกอย่างทำงานได้ดี ... แต่ถ้าฉันเพิ่มคอลัมน์ที่มีบางอย่างตามแนวของ:

rails g migration add_user_to_tester user:references

เขตข้อมูลอ้างอิงไม่เป็นที่รู้จัก ในระยะสั้นคำถามคือฉันจะเพิ่มคอลัมน์อ้างอิงไปยังการโยกย้ายรางจากบรรทัดคำสั่งได้อย่างไร

คำตอบ:


205

หากคุณกำลังใช้Rails 4.xคุณสามารถสร้างการย้ายข้อมูลด้วยการอ้างอิงเช่นนี้:

rails generate migration AddUserRefToProducts user:references

อย่างที่คุณเห็นในคู่มือราง


1
ดูหัวข้อ 2.1 จากedgeguides.rubyonrails.org/active_record_migrations.htmlตัวอย่างเช่น
B เซเว่น

2
คุณจะระบุชื่อคอลัมน์สำหรับคีย์ต่างประเทศแทนชื่อที่สร้างอัตโนมัติได้อย่างไร
j จะ

@jwill คุณสามารถใช้ polymorphic: ผู้ใช้: การอ้างอิง {polymorphic}
เปาโล Fidalgo

@PauloFidalgo คุณช่วยอธิบายเล็กน้อยเกี่ยวกับวิธีการทำเช่นนั้นได้หรือไม่? อาจเป็นแนวทางของลิงก์? (พูดถึง polymorphic)
Anwar

@ อันวาร์: นี่คือเอกสารapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ …
เปาโล Fidalgo

186

แก้ไข : นี่เป็นคำตอบที่ล้าสมัยและไม่ควรใช้กับRails 4.x +

คุณไม่จำเป็นต้องเพิ่มการอ้างอิงเมื่อคุณสามารถใช้รหัสจำนวนเต็มในคลาสที่อ้างอิงของคุณ

ฉันจะบอกว่าข้อดีของการใช้การอ้างอิงแทนที่จะเป็นจำนวนเต็มธรรมดาคือโมเดลจะถูกกำหนดไว้ล่วงหน้าด้วย own_to และเนื่องจากแบบจำลองนั้นถูกสร้างขึ้นแล้วและจะไม่ได้รับผลกระทบเมื่อคุณย้ายสิ่งที่มีอยู่ไปแล้ว

ดังนั้นฉันจะทำเช่นนี้แทน:

rails g migration add_user_id_to_tester user_id:integer

จากนั้นเพิ่มด้วยตนเองเป็นของผู้ใช้: ในรูปแบบทดสอบ


9
แต่นั่นจะไม่สร้างข้อ จำกัด foreign key ที่เหมาะสมบนฐานข้อมูลที่สนับสนุนใช่ไหม
abahgat

19
ไม่ afaik Rails จะไม่สร้าง foreign key restraints ในฐานข้อมูลเว้นแต่คุณจะเพิ่มปลั๊กอินเพื่อให้เหมาะกับคุณ
DanneManne

เพียงศึกษาโพสต์นี้ฉันจะเพิ่มการอ้างอิงได้อย่างไร
El nino

13
อย่าลืมเพิ่มดัชนีด้วยผู้ใช้: จำนวนเต็ม: index
rickypai

3
คำตอบลงวันที่โปรดดูคำตอบของ @ เปาโลสำหรับรางรถไฟที่ทันสมัย
OneHoopyFrood

102

โปรดทราบว่าคุณอาจต้องการดัชนีในคอลัมน์นั้นด้วย

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end

1
ทำไม? สิ่งนี้เป็นจริงสำหรับความสัมพันธ์ที่เป็นของส่วนใหญ่หรือไม่
ahnbizcad

มันมีเหตุผลด้านประสิทธิภาพและมีประโยชน์ถ้าคุณมี has_many / has_one ที่อีกด้านหนึ่งของ หากคุณแน่ใจอย่างแน่นอนว่าคุณจะไม่ผ่านuser.testersคุณสามารถละเว้นดัชนี
ยูจีน

1
rails g migration ...สร้างadd_reference :installs, :device, index: trueซึ่งยังสร้างดัชนี
B เซเว่น

49

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

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end

นี่เป็นคำตอบที่แท้จริงเท่านั้นที่นี่ คีย์ต่างประเทศเป็นส่วนที่สำคัญที่สุดที่นี่
user2490003

ควรทำเครื่องหมายเป็นคำตอบที่ถูกต้องเนื่องจากคำถามถามสำหรับราง 3
Carlos Roque

35

คุณสามารถใช้การอ้างอิงในการโยกย้ายการเปลี่ยนแปลง นี่คือรหัส Rails 3.2.13 ที่ถูกต้อง:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table


1
วิธีการเปลี่ยนและลง? ไม่ใช่วิธีการขึ้นและลงแทน?
MaicolBen

@MaicolBen ใช่แล้วคุณยังสามารถออกจากวิธีการลง
Hut8 8

@MaicolBen โดยไม่ใช้downวิธีการฉันได้รับActiveRecord::IrreversibleMigrationเมื่อย้อนกลับด้วย Rails 3.2 ฉันยังมีการเปลี่ยนแปลงไปchange up
Andrew Grimm

27

การรันrails g migration AddUserRefToSponsors user:referencesจะสร้างการย้ายข้อมูลต่อไปนี้:

def change
  add_reference :sponsors, :user, index: true
end

Rails รุ่นนี้ใช้ทำอะไร?
Andrew Grimm

8

เมื่อเพิ่มคอลัมน์คุณต้องทำให้คอลัมน์นั้นเป็นจำนวนเต็มและหากเป็นไปได้ให้ใช้หลักการของทางรถไฟ ดังนั้นสำหรับกรณีของคุณฉันสมมติว่าคุณมีเครื่องทดสอบและรุ่นผู้ใช้อยู่แล้วและผู้ทดสอบและผู้ใช้ตาราง

ในการเพิ่ม foreign key คุณต้องสร้างคอลัมน์จำนวนเต็มด้วยชื่อ user_id (แบบแผน):

add_column :tester, :user_id, :integer

จากนั้นเพิ่มค่าของสมบัติไปเป็นโมเดลทดสอบ:

class Tester < ActiveRecord::Base
  belongs_to :user
end

และคุณอาจต้องการเพิ่มดัชนีสำหรับ foreign key (นี่คือสิ่งที่การอ้างอิงทำไว้แล้วสำหรับคุณ):

add_index :tester, :user_id

8

ที่จะทำเคล็ดลับ:

rails g migration add_user_to_tester user_id:integer:index

ฉันชอบที่จะเพิ่มดัชนีที่คุณจะต้องการมากที่สุด
bheeshmar

3

คุณสามารถเพิ่มการอ้างอิงถึงโมเดลของคุณผ่านบรรทัดรับคำสั่งในลักษณะต่อไปนี้:

rails g migration add_column_to_tester user_id:integer

สิ่งนี้จะสร้างไฟล์การโยกย้ายเช่น:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

ทำงานได้ดีทุกครั้งที่ฉันใช้ ..


3

สำหรับ Rails 4

เครื่องกำเนิดไฟฟ้ายอมรับประเภทคอลัมน์เป็นการอ้างอิง (มีให้เช่นกันbelongs_to)

การย้ายข้อมูลนี้จะสร้างuser_idคอลัมน์และดัชนีที่เหมาะสม:

$ rails g migration AddUserRefToProducts user:references 

สร้าง:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

สำหรับ Rails 3

ตัวช่วยเรียกว่าการอ้างอิง (มีให้เช่นกันbelongs_to)

การย้ายข้อมูลนี้จะสร้างcategory_idคอลัมน์ประเภทที่เหมาะสม โปรดทราบว่าคุณส่งชื่อรุ่นไม่ใช่ชื่อคอลัมน์ บันทึกการใช้งานเพิ่ม_idสำหรับคุณ

change_table :products do |t|
  t.references :category
end

หากคุณมีความbelongs_toสัมพันธ์แบบpolymorphic การอ้างอิงจะเพิ่มทั้งสองคอลัมน์ที่ต้องการ:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

จะเพิ่มคอลัมน์ Attach_id และattachment_typeคอลัมน์สตริงที่มีค่าเริ่มต้นเป็นPhotoคอลัมน์ที่มีค่าเริ่มต้น

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

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