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


340

ฉันมีรูปแบบผู้ใช้ที่ต้องการ:emailคอลัมน์ (ฉันลืมที่จะเพิ่มคอลัมน์นั้นในช่วงนั่งร้านเริ่มต้น)

ผมเปิดไฟล์การโยกย้ายและเพิ่มt.string :emailทำและมีrake db:migrate NoMethodErrorจากนั้นฉันเพิ่มบรรทัด

add_column :users, :email, :string

อีกครั้งอีกครั้งrake db:migrate NoMethodErrorฉันพลาดขั้นตอนที่นี่หรือไม่

แก้ไข: นี่คือไฟล์การโยกย้าย

class CreateUsers < ActiveRecord::Migration  
  def self.up  
    add_column :users, :email, :string  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  

      t.timestamps  
    end  
  end  

  def self.down  
    drop_table :users  
  end  
end

คำตอบ:


573

หากคุณเรียกใช้การย้ายข้อมูลดั้งเดิม (ก่อนที่จะแก้ไข) คุณต้องสร้างการย้ายข้อมูลใหม่ ( rails generate migration add_email_to_users email:stringจะทำการหลอกลวง) มันจะสร้างไฟล์การโยกย้ายที่มีบรรทัด: add_column :users, email, string จากนั้นทำrake db:migrateและมันจะเรียกใช้การโยกย้ายใหม่สร้างคอลัมน์ใหม่

หากคุณยังไม่ได้ทำการโยกย้ายดั้งเดิมคุณสามารถแก้ไขได้เช่นเดียวกับที่คุณพยายามจะทำ รหัสการโยกย้ายของคุณเกือบจะสมบูรณ์แบบ: คุณเพียงแค่ลบadd_columnบรรทัดทั้งหมด (รหัสนั้นพยายามที่จะเพิ่มคอลัมน์ในตารางก่อนที่จะมีการสร้างตารางและรหัสการสร้างตารางของคุณได้รับการอัปเดตเพื่อรวมไว้t.string :emailแล้ว)


6
เพื่อให้ชัดเจนเราใช้พหูพจน์หรือไม่ ดังนั้นมันadd_email_to_usersและไม่add_email_to_user?
Purplejacket

9
แก้ไข. ชื่อตารางใน Rails เป็นพหูพจน์เสมอ (เพื่อให้ตรงกับอนุสัญญา DB)
camdez

2
คุณยังสามารถใช้rails db:migrateสำหรับขั้นตอนสุดท้าย
Dylan Vander Berg

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

2
@neeraj คุณอาจมีคำตอบในตอนนี้ แต่สำหรับผู้ค้นหาคนอื่น ๆ ใช่คุณสามารถทำได้เช่นt.string :column_x, limit: 10, after: :column_y(สำหรับ Rails 4 อย่างน้อย)
244

124

ใช้คำสั่งนี้ที่คอนโซลทางรถไฟ

rails generate migration add_fieldname_to_tablename fieldname:string

และ

rake db:migrate

เพื่อเรียกใช้การโยกย้ายนี้


57

บางครั้งrails generate migration add_email_to_users email:stringการโยกย้ายเช่นนี้

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
  end
end

ในกรณีนั้นคุณจะadd_columnต้องchange:

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :email, :string
  end
end

จากนั้นเรียกใช้ rake db:migrate


1) ควรrails generate migration add_email_to_users email:stringรันหลังจากbundle exec rails cหรือภายในเทอร์มินัลหรือไม่ 2) ไฟล์ที่สร้างจะถูกวางไว้ที่ไหนเมื่อเราประมวลผลแบบสอบถาม?
sofs1

28

คุณยังสามารถทำ

rake db:rollback

หากคุณยังไม่ได้เพิ่มข้อมูลใด ๆ ลงในตารางจากนั้นแก้ไขไฟล์การโยกย้ายโดยการเพิ่มคอลัมน์อีเมลไปที่มันแล้วโทร

rake db:migrate

สิ่งนี้จะใช้งานได้หากคุณติดตั้งราง 3.1 ขึ้นไปในระบบ

วิธีที่ง่ายกว่าในการเปลี่ยนแปลงคือให้การเปลี่ยนแปลงในไฟล์การย้ายข้อมูลเป็นไปตามที่เป็นอยู่ ใช้

$rake db:migrate:redo

นี่จะย้อนกลับการโอนย้ายครั้งล่าสุดและโอนย้ายอีกครั้ง


21

ในการเพิ่มคอลัมน์ฉันต้องทำตามขั้นตอนเหล่านี้:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    ทางเลือก

    rails generate migration addFieldnameToTablename

    เมื่อสร้างการโยกย้ายแล้วให้แก้ไขการย้ายและกำหนดแอตทริบิวต์ทั้งหมดที่คุณต้องการให้คอลัมน์นั้นมี

    หมายเหตุ : ชื่อตารางใน Rails เป็นพหูพจน์เสมอ (เพื่อให้ตรงกับอนุสัญญา DB) ตัวอย่างการใช้หนึ่งในขั้นตอนที่กล่าวถึงก่อนหน้านี้ -

    rails generate migration addEmailToUsers

  2. rake db:migrate

หรือ

  1. คุณสามารถเปลี่ยนสคีมาจากdb/schema.rbเพิ่มคอลัมน์ที่คุณต้องการในแบบสอบถาม SQL
  2. เรียกใช้คำสั่งนี้: rake db:schema:load

    คำเตือน / หมายเหตุ

    โปรดทราบว่าการเรียกใช้rake db:schema:loadจะลบข้อมูลทั้งหมดในตารางโดยอัตโนมัติ


ฉันทำสิ่งนี้ แต่ไม่ได้ทำซ้ำ "นั่งร้าน" และเพิ่มคอลัมน์ใหม่ ฉันจะทำอย่างนั้น "อัตโนมัติ" ได้อย่างไร
John Wooten

@John Wooten คุณอาจต้องการลบ Scaffold และลองใหม่อีกครั้ง ปล่อยการโยกย้ายที่สอดคล้องกันด้วย
Afolabi Olaoluwa Akinwumi

เพื่อเพิ่มหมายเหตุ: การเปลี่ยนสคีมาโดยไม่เปลี่ยนการโยกย้ายอาจสร้างปัญหากับนักพัฒนารายอื่นที่ดูแลแอพ
BKSpurgeon

3

เมื่อฉันทำสิ่งนี้แทนที่จะทำตามการย้ายถิ่นแบบเดิมฉันสร้างใหม่ด้วยการเพิ่มคอลัมน์ในส่วน up และคอลัมน์ drop ในส่วน down

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

ตามที่โพสต์ในปัจจุบันคุณกำลังเพิ่มคอลัมน์และสร้างตาราง

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


1

นอกจากนี้คุณยังสามารถบังคับให้คอลัมน์คอลัมน์ในตารางใช้force: trueหากตารางของคุณมีอยู่แล้ว

ตัวอย่าง :

ActiveRecord::Schema.define(version: 20080906171750) do
  create_table "authors", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

1

คุณยังสามารถใช้วิธีการพิเศษchange_tableในการย้ายข้อมูลเพื่อเพิ่มคอลัมน์ใหม่:

change_table(:users) do |t|
  t.column :email, :string
end

0

คุณสามารถย้อนกลับการโยกย้ายครั้งสุดท้ายโดย

rake db:rollback STEP=1

หรือย้อนกลับการโยกย้ายนี้โดยเฉพาะ

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

และแก้ไขไฟล์จากนั้นเรียกใช้rake db:mirgateอีกครั้ง


0

คุณยังสามารถทำสิ่งนี้ได้ .. สร้างการโยกย้าย g add_column_to_users email: string

จากนั้น rake db: โอนย้ายยังเพิ่ม: แอตทริบิวต์อีเมลในตัวควบคุมผู้ใช้ของคุณ

สำหรับรายละเอียดเพิ่มเติมโปรดดูที่http://guides.rubyonrails.org/active_record_migrations.html


0

นอกจากนี้คุณยังสามารถเพิ่มคอลัมน์ในตำแหน่งที่ต้องการโดยใช้คอลัมน์ก่อนหน้าหรือหลังคอลัมน์เช่น:

rails generate migration add_dob_to_customer dob:date

ไฟล์การโยกย้ายจะสร้างรหัสต่อไปนี้ยกเว้นหลังจาก:: อีเมล คุณต้องเพิ่มหลังจาก:: อีเมลหรือก่อนหน้า:: อีเมล

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.