เพิ่มการย้ายข้อมูลคอลัมน์อ้างอิงใน Rails 4


310

ผู้ใช้มีการอัปโหลดจำนวนมาก ฉันต้องการที่จะเพิ่มคอลัมน์ไปยังตารางที่อ้างอิงuploads userการโยกย้ายควรมีลักษณะอย่างไร

นี่คือสิ่งที่ฉันมี ผมไม่แน่ใจว่าผมควรจะใช้ (1) :user_id, :intหรือ :user, :references(2) ฉันไม่แน่ใจด้วยซ้ำว่า (2) ใช้งานได้ เพียงแค่พยายามทำสิ่งนี้ด้วยวิธี "ทางรถไฟ"

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_column :uploads, :user_id, :integer
  end
end

คำถามที่เกี่ยวข้องยกเว้น Rails 3 Rails 3 migrations: การเพิ่มคอลัมน์อ้างอิง?

คำตอบ:


706

ราง 4.x

เมื่อคุณมีอยู่แล้ว usersและuploadsตารางและต้องการที่จะเพิ่มความสัมพันธ์ใหม่ระหว่างพวกเขา

สิ่งที่คุณต้องทำคือเพียงแค่สร้างการย้ายข้อมูลโดยใช้คำสั่งต่อไปนี้:

rails g migration AddUserToUploads user:references

ซึ่งจะสร้างไฟล์การโยกย้ายเป็น:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
  end
end

rake db:migrateจากนั้นเรียกใช้การย้ายโดยใช้ การโยกย้ายนี้จะดูแลการเพิ่มคอลัมน์ใหม่ที่มีชื่อuser_idลงในuploadsตาราง ( idคอลัมน์อ้างอิงในusersตาราง) บวกมันจะเพิ่มดัชนีในคอลัมน์ใหม่

อัพเดท [สำหรับ Rails 4.2]

Rails ไม่สามารถเชื่อถือได้เพื่อรักษาความสมบูรณ์ของการอ้างอิง ฐานข้อมูลเชิงสัมพันธ์มาช่วยเราที่นี่ นั่นหมายความว่าเราสามารถเพิ่มข้อ จำกัด foreign key ในระดับฐานข้อมูลเองและตรวจสอบให้แน่ใจว่าฐานข้อมูลจะปฏิเสธการดำเนินการใด ๆ ที่ละเมิด Referential Integrity นี้ ในฐานะที่เป็น @infoget ความเห็นRails 4.2มาพร้อมกับการสนับสนุนพื้นเมืองสำหรับปุ่มต่างประเทศ (มี Referential Integrity) ไม่จำเป็น แต่คุณอาจต้องการเพิ่มรหัสต่างประเทศ (เนื่องจากมีประโยชน์มาก) ในการอ้างอิงที่เราสร้างขึ้นด้านบน

หากต้องการเพิ่ม foreign key ไปยังการอ้างอิงที่มีอยู่ให้สร้างการโยกย้ายใหม่เพื่อเพิ่ม foreign key:

class AddForeignKeyToUploads < ActiveRecord::Migration
  def change
    add_foreign_key :uploads, :users
  end
end

ในการสร้างการอ้างอิงใหม่ทั้งหมดด้วย foreign key (ใน Rails 4.2)ให้สร้างการย้ายโดยใช้คำสั่งต่อไปนี้:

rails g migration AddUserToUploads user:references

ซึ่งจะสร้างไฟล์การโยกย้ายเป็น:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
    add_foreign_key :uploads, :users
  end
end

สิ่งนี้จะเพิ่ม foreign key ใหม่ไปยังuser_idคอลัมน์ของuploadsตาราง รหัสอ้างอิงidคอลัมน์ในusersตาราง

หมายเหตุ:นี่คือนอกเหนือจากการเพิ่มการอ้างอิงดังนั้นคุณยังคงต้องสร้างการอ้างอิงก่อนจากนั้นก็เป็นกุญแจสำคัญต่างประเทศ ( คุณสามารถเลือกที่จะสร้างกุญแจต่างประเทศในการโยกย้ายเดียวกันหรือไฟล์การโยกย้ายแยกต่างหาก ) Active Record สนับสนุนเฉพาะคีย์ต่างประเทศคอลัมน์เดียวและในปัจจุบันเท่านั้นmysql, mysql2และPostgreSQLอะแดปเตอร์ได้รับการสนับสนุน อย่าลองสิ่งนี้กับอะแดปเตอร์อื่น ๆ เช่นsqlite3ฯลฯ อ้างอิงถึงคู่มือราง: กุญแจต่างประเทศสำหรับการอ้างอิงของคุณ


8
ในหลายกรณีเป็นการดีที่จะเพิ่มคีย์ต่างประเทศเช่นกัน add_foreign_key (Rails 4.2)
poerror

18
ฉันเชื่อว่าคุณสามารถทำได้ทั้งหมดในหนึ่งบรรทัด: add_reference: อัพโหลด,: ผู้ใช้, ดัชนี: จริง, foreign_key: จริง @KirtiThorat
user1801879

32
ตอนนี้ถ้าคุณใช้ไวยากรณ์ตัวสร้างพิเศษสำหรับการย้ายข้อมูล Rails 4.2 จะสร้างการโยกย้ายที่ถูกต้องโดยอัตโนมัติพร้อมกับข้อ จำกัด foreign key rails g migration AddUserToUploads user:referencesผลิตadd_reference :uploads, :user, index: true, foreign_key: trueในการโยกย้ายที่เหมาะสม
jrhorn424

10
ใช้...index: true, foreign_key: trueแทน o add_foreign_keyสาย
Washington Botelho

2
ทำไมเราต้องการทั้งสองอย่างforeign_keyและt.reference? ไม่t.referenceเท่ากับforiegn_key+ indexใช่หรือไม่
geoboy

187

ราง 5

คุณยังสามารถใช้คำสั่งนี้เพื่อสร้างการย้ายข้อมูล:

rails g migration AddUserToUploads user:references

การย้ายข้อมูลมีลักษณะแตกต่างไปเล็กน้อยก่อนหน้านี้ แต่ยังคงใช้ได้:

class AddUserToUploads < ActiveRecord::Migration[5.0]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

โปรดทราบว่ามัน:userไม่ใช่:user_id


2
สำหรับการเรียนชื่อระยะห่างเช่นLocal::Userแทนที่จะเป็นบางสิ่งบางอย่างที่ต้องทำเช่นUser rails g migration AddLocalUserToUploads user:references
Ka Mok

3
สิ่งนี้จะเพิ่มโดยอัตโนมัติ:index
Saravanabalagi Ramachandran

4
@Zeke ใช่ทำการโยกย้ายและตรวจสอบสคีมาของคุณมันควรพูดอะไรทำนองนี้t.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318

1
ใช่ฉันได้รับข้อผิดพลาด "ดัชนีมีอยู่" เมื่อฉันเพิ่ม add_index ในการย้ายข้อมูลด้วยตนเอง: P @ Mirror318
Saravanabalagi Ramachandran

2
นอกจากนี้เรายังควรเพิ่มbelongs_to :userในUploadชั้นเรียนเพื่อให้เราสามารถใช้upload.userเพื่อให้ได้ตัวอย่างเช่นผู้ใช้
Wit

17

ถ้าคุณชอบวิธีอื่นด้วยupและdownวิธีลอง:

  def up
    change_table :uploads do |t|
      t.references :user, index: true
    end
  end

  def down
    change_table :uploads do |t|
      t.remove_references :user, index: true
    end
  end

9

[ใช้ Rails 5]

สร้างการโยกย้าย:

rails generate migration add_user_reference_to_uploads user:references

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

class AddUserReferenceToUploads < ActiveRecord::Migration[5.1]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

ตอนนี้ถ้าคุณสังเกตเห็นไฟล์สคีมาคุณจะเห็นว่าตารางการอัปโหลดมีฟิลด์ใหม่ สิ่งที่ชอบหรือt.bigint "user_id"t.integer "user_id"

โอนย้ายฐานข้อมูล:

rails db:migrate

1
คำตอบนี้ดูเหมือนจะซ้ำกับคำตอบของ @ Mirror318 โปรดแสดงความคิดเห็นกับคำตอบข้างต้นหากคุณคิดว่ามีบางอย่างขาดหายไป ขอบคุณ
M. Habib


7

เพียงแค่จัดทำเอกสารหากใครบางคนมีปัญหาเดียวกัน ...

ในสถานการณ์ของฉันฉันได้ใช้:uuidฟิลด์และคำตอบข้างต้นไม่สามารถใช้ได้กับเคสของฉันเพราะราง 5 กำลังสร้างคอลัมน์ที่ใช้:bigintแทน:uuid:

add_column :uploads, :user_id, :uuid
add_index :uploads, :user_id
add_foreign_key :uploads, :users

นอกจากนี้ยังมีความชัดเจนว่าเกิดอะไรขึ้น แต่ใช่ UUID ควรเป็นมาตรฐานในขณะนี้
Hadees

2

สร้างไฟล์การโยกย้าย

rails generate migration add_references_to_uploads user:references

ชื่อคีย์ต่างประเทศที่เป็นค่าเริ่มต้น

สิ่งนี้จะสร้างคอลัมน์ user_id ในตารางที่อัปโหลดเป็น foreign key

class AddReferencesToUploads < ActiveRecord::Migration[5.2]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

รุ่นของผู้ใช้:

class User < ApplicationRecord
  has_many :uploads
end

อัปโหลดโมเดล:

class Upload < ApplicationRecord
  belongs_to :user
end

กำหนดชื่อคีย์ต่างประเทศ:

add_reference :uploads, :author, references: :user, foreign_key: true

สิ่งนี้จะสร้างคอลัมน์ author_id ในตารางการอัปโหลดเป็น foreign key

รุ่นของผู้ใช้:

class User < ApplicationRecord
  has_many :uploads, foreign_key: 'author_id'
end

อัปโหลดโมเดล:

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